Metadata-Version: 2.5
Name: vnfinancialdata
Version: 0.1.2
Summary: Python interface for Vietnamese listed-company financial statement data.
Author: Ngo Phu Thanh
Requires-Python: >=3.10
Requires-Dist: huggingface-hub>=1.0
Requires-Dist: pandas>=2.0
Requires-Dist: pyarrow>=14
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: twine>=5; extra == 'dev'
Provides-Extra: polars
Requires-Dist: polars>=1.0; extra == 'polars'
Description-Content-Type: text/markdown

# vnfinancialdata

**Programmatic access to standardized financial statements of Vietnamese listed companies**

`vnfinancialdata` is a Python package for loading, exploring, filtering, and reshaping financial statement data for companies listed on **HSX** and **HNX**.

The package is designed for **academic research, financial econometrics, accounting analysis, corporate-finance research, data science, teaching, and reproducible analytical workflows**.

> **Package version:** `0.1.2`  
> **Dataset revision:** `v1.0.0`  
> **Schema version:** `1.0`  
> **Storage format:** Parquet  
> **Primary interface:** pandas DataFrame  
> **Supported exchanges:** HSX, HNX

---

## 1. Why `vnfinancialdata`?

Vietnamese corporate financial statements are commonly distributed in spreadsheet-oriented formats that are convenient for human reading but less convenient for panel-data research and programmatic analysis.

`vnfinancialdata` provides a standardized analytical interface so that users can:

- load a complete financial statement for one company;
- retrieve one accounting indicator across many companies;
- compare the same indicator across multiple years;
- construct firm-year panel datasets;
- inspect standardized `item_code`–`item_name` mappings;
- reshape long-format data into financial-statement or research-ready tables;
- reproduce analyses using explicit package, dataset, schema, and item identifiers.

---

# 2. Installation

```bash
pip install vnfinancialdata
```

Python requirement:

```text
Python >= 3.10
```

Basic import:

```python
import vnfinancialdata as vnf
```

---

# 3. Current Data Coverage

The current source files underlying dataset revision `v1.0.0` were reviewed directly for this documentation.

| Exchange | Statement | Company-year rows | Tickers | Year coverage | Source financial items |
|---|---|---:|---:|---|---:|
| HNX | Balance Sheet | 4,389 | 307 | 2009–2025 | 311 |
| HNX | Cash Flow | 4,376 | 307 | 2006–2025 | 196 |
| HNX | Income Statement | 4,387 | 307 | 2009–2025 | 195 |
| HSX | Balance Sheet | 5,483 | 386 | 2009–2025 | 311 |
| HSX | Cash Flow | 5,471 | 386 | 2008–2025 | 196 |
| HSX | Income Statement | 5,474 | 386 | 2009–2025 | 195 |

The HSX and HNX source files use the **same set of financial-item names within each statement type**, although physical column ordering in source workbooks may differ.

This is important for cross-exchange research because users can work with the same accounting concept across HSX and HNX after identifying the appropriate standardized item.

---

# 4. Supported Financial Statements

Use one of the following statement identifiers:

```text
balance_sheet
income_statement
cash_flow
```

Example:

```python
import vnfinancialdata as vnf

df = vnf.load(
    exchange="HSX",
    statement="balance_sheet"
)
```

---

# 5. User-Facing Analytical Schema

The recommended analytical fields are:

| Field | Description |
|---|---|
| `ticker` | Listed-company stock ticker |
| `year` | Reporting year |
| `exchange` | Exchange identifier such as `HSX` or `HNX` |
| `statement` | Standardized statement type |
| `item_code` | Standardized package-level identifier for a financial statement line item |
| `item_name` | Human-readable financial statement line item |
| `value` | Reported numeric value |

Recommended working structure:

```text
ticker
year
exchange
statement
item_code
item_name
value
```

### Provenance fields

The transformation pipeline may retain technical provenance information internally. Fields such as:

```text
source_file
source_sheet
```

are intentionally **not emphasized in the user-facing analytical documentation and examples for version 0.1.2**.

For normal research workflows, users should work with the standardized analytical fields above.

---

# 6. `item_name` vs `item_code` — Read This First

Correct use of `item_name` and `item_code` is essential.

## 6.1 `item_name`

`item_name` is the **human-readable financial statement line item**.

Examples verified directly from the source financial statement files include:

```text
TỔNG TÀI SẢN
Tiền và tương đương tiền
Hàng tồn kho
NỢ PHẢI TRẢ
VỐN CHỦ SỞ HỮU
Doanh số thuần
Lãi gộp
Lãi/(lỗ) thuần sau thuế
EBIT
EBITDA
Lưu chuyển tiền thuần trong kỳ
Tiền và tương đương tiền cuối kỳ
```

Use `item_name` when:

- exploring available accounting concepts;
- searching by familiar Vietnamese accounting terminology;
- checking alternative line-item names;
- identifying which standardized `item_code` should be used.

## 6.2 `item_code`

`item_code` is the **standardized identifier used in the package-level long-format dataset**.

The six reviewed source Excel files are wide-format source tables. They contain:

```text
Mã chứng khoán
Năm
<financial item 1>
<financial item 2>
...
```

They do **not** contain a native `item_code` column.

Therefore, this README deliberately does **not invent or infer undocumented item codes from Excel column positions**.

Instead, users should retrieve the actual `item_code`–`item_name` mapping from the loaded dataset.

This is the safest and most reproducible approach.

---

# 7. How to Discover the Actual `item_code`

Load the relevant statement and inspect the dictionary:

```python
import vnfinancialdata as vnf

income = vnf.load(
    exchange="HSX",
    statement="income_statement"
)

item_dictionary = (
    income[["item_code", "item_name"]]
    .drop_duplicates()
    .sort_values(["item_code", "item_name"])
    .reset_index(drop=True)
)

print(item_dictionary.to_string(index=False))
```

Search for a concept:

```python
matches = (
    item_dictionary.loc[
        item_dictionary["item_name"]
        .astype(str)
        .str.contains(
            "sau thuế",
            case=False,
            na=False
        )
    ]
)

print(matches.to_string(index=False))
```

Recommended workflow:

```text
Accounting concept
        ↓
Search item_name
        ↓
Review all candidate names
        ↓
Confirm the intended accounting meaning
        ↓
Read its actual item_code
        ↓
Use item_code for repeatable analysis
```

---

# 8. Verified Financial-Item Guide

The tables below are based on the actual line-item names observed in the source financial statement files.

They are intended to help users search correctly.

---

## 8.1 Balance Sheet — Common Corporate Items

| Analytical concept | Exact source `item_name` |
|---|---|
| Total assets | `TỔNG TÀI SẢN` |
| Current assets | `TÀI SẢN NGẮN HẠN` |
| Cash and cash equivalents | `Tiền và tương đương tiền` |
| Cash | `Tiền` |
| Cash equivalents | `Các khoản tương đương tiền` |
| Short-term investments | `Đầu tư ngắn hạn` |
| Receivables | `Các khoản phải thu` |
| Trade receivables | `Phải thu khách hàng` |
| Other receivables | `Phải thu khác` |
| Net inventory | `Hàng tồn kho, ròng` |
| Inventory | `Hàng tồn kho` |
| Inventory provision | `Dự phòng giảm giá HTK` |
| Long-term assets | `TÀI SẢN DÀI HẠN` |
| Fixed assets | `Tài sản cố định` |
| Net tangible fixed assets | `GTCL TSCĐ hữu hình` |
| Tangible fixed assets — cost | `Nguyên giá TSCĐ hữu hình` |
| Tangible fixed assets — accumulated depreciation | `Khấu hao lũy kế TSCĐ hữu hình` |
| Net intangible assets | `GTCL tài sản cố định vô hình` |
| Investment property | `Bất động sản đầu tư` |
| Long-term investment | `Đầu tư dài hạn` |
| Other long-term assets | `Tài sản dài hạn khác` |
| Total liabilities | `NỢ PHẢI TRẢ` |
| Current liabilities | `Nợ ngắn hạn` |
| Trade payables | `Phải trả người bán` |
| Short-term borrowing | `Vay ngắn hạn` |
| Long-term liabilities | `Nợ dài hạn` |
| Long-term borrowing | `Vay dài hạn` |
| Owners' equity | `VỐN CHỦ SỞ HỮU` |
| Contributed capital | `Vốn góp` |
| Share premium | `Thặng dư vốn cổ phần` |
| Retained earnings | `Lãi chưa phân phối` |
| Total capital and liabilities | `TỔNG CỘNG NGUỒN VỐN` |

### Important Balance Sheet naming variants

The source dataset also contains sector- or template-specific alternatives such as:

```text
Tổng nợ phải trả
Vốn chủ sở hữu
Vốn đầu tư của chủ sở hữu
Lợi nhuận chưa phân phối
Lợi nhuận sau thuế chưa phân phối
Tiền mặt, vàng bạc, đá quý
Tiền gửi tại Ngân hàng nhà nước Việt Nam
Tiền gửi của khách hàng
```

Do not automatically treat these as synonyms without considering the firm's sector and financial-statement template.

---

## 8.2 Income Statement — Common Non-Financial Corporate Items

| Analytical concept | Exact source `item_name` |
|---|---|
| Gross sales | `Doanh số` |
| Revenue deductions | `Các khoản giảm trừ` |
| Net sales / net revenue | `Doanh số thuần` |
| Cost of goods sold | `Giá vốn hàng bán` |
| Gross profit | `Lãi gộp` |
| Financial income | `Thu nhập tài chính` |
| Financial expenses | `Chi phí tài chính` |
| Interest expense | `Trong đó: Chi phí lãi vay` |
| Selling expenses | `Chi phí bán hàng` |
| General and administrative expenses | `Chi phí quản lý doanh nghiệp` |
| Operating profit | `Lãi/(lỗ) từ hoạt động kinh doanh` |
| Other income | `Thu nhập khác` |
| Other expenses | `Chi phí khác` |
| Profit before tax | `Lãi/(lỗ) ròng trước thuế` |
| Current income tax | `Thuế thu nhập doanh nghiệp – hiện thời` |
| Deferred income tax | `Thuế thu nhập doanh nghiệp – hoãn lại` |
| Income tax expense | `Chi phí thuế thu nhập doanh nghiệp` |
| **Profit after tax** | **`Lãi/(lỗ) thuần sau thuế`** |
| Minority interest | `Lợi ích của cổ đông thiểu số` |
| Profit attributable to parent-company shareholders | `Lợi nhuận của Cổ đông của Công ty mẹ` |
| Basic EPS | `Lãi cơ bản trên cổ phiếu` |
| Diluted EPS | `Lãi trên cổ phiếu pha loãng` |
| EBIT | `EBIT` |
| EBITDA | `EBITDA` |

### Recommended after-tax profit item for ordinary non-financial companies

For the ordinary corporate financial-statement template, the exact verified item name is:

```text
Lãi/(lỗ) thuần sau thuế
```

This item is populated for the example HSX companies:

```text
AAA
BTT
CCI
DGC
FPT
GMD
HPG
KDH
REE
VNM
```

for reporting years through 2025 in the reviewed source data.

---

# 9. Important: “Profit After Tax” Has Multiple Valid Names

The source Income Statement contains several distinct line items containing the concept “profit after tax”.

Verified examples include:

| Exact `item_name` | Typical context |
|---|---|
| `Lãi/(lỗ) thuần sau thuế` | Ordinary non-financial corporate template |
| `Lợi nhuận sau thuế` | Alternative / sector-specific template |
| `Lợi nhuận kế toán sau thuế` | Accounting-profit presentation in another template |
| `Lợi nhuận sau thuế phân bổ cho chủ sở hữu` | Profit attributable to owners |
| `Lợi nhuận sau thuế thu nhập doanh nghiệp` | Sector-specific profit after corporate income tax |
| `Lợi nhuận sau thuế của chủ sở hữu, tập đoàn` | Profit attributable to owners/group |

These lines are **not automatically interchangeable**.

For cross-company research, first decide what economic concept you need:

```text
Consolidated profit after tax?
Profit attributable to parent owners?
Sector-specific accounting profit?
Total post-tax profit including minority interests?
```

Then use the corresponding `item_code`.

---

## 9.1 Income Statement — Banking-Specific Examples

The source data include banking-style items such as:

```text
Thu nhập lãi và các khoản thu nhập tương tự
Chi phí lãi và các chi phí tương tự
Thu nhập lãi thuần
Thu nhập từ hoạt động dịch vụ
Lãi thuần từ hoạt động dịch vụ
Tổng thu nhập hoạt động
Chi phí hoạt động
Chi phí dự phòng rủi ro tín dụng
Tổng lợi nhuận trước thuế
Lợi nhuận sau thuế
```

Researchers should not apply ordinary industrial-company revenue/profit lines to banks without reviewing the banking template.

---

## 9.2 Income Statement — Securities-Specific Examples

The source data include securities-company lines such as:

```text
Doanh thu hoạt động
Lãi từ các tài sản tài chính ghi nhận thông qua lãi/lỗ ( FVTPL)
Lãi từ các khoản đầu tư nắm giữ đến ngày đáo hạn (HTM)
Lãi từ các khoản cho vay và phải thu
Doanh thu hoạt động môi giới chứng khoán
Chi phí môi giới chứng khoán
Chi phí quản lý công ty chứng khoán
Lợi nhuận kế toán sau thuế
```

---

## 9.3 Income Statement — Insurance-Specific Examples

The source data also contain insurance-specific lines such as:

```text
Doanh thu phí bảo hiểm
Doanh thu phí bảo hiểm thuần
Doanh thu thuần từ hoạt động kinh doanh bảo hiểm
Tổng chi bồi thường bảo hiểm
Lợi nhuận gộp hoạt động kinh doanh bảo hiểm
Lợi nhuận thuần hoạt động kinh doanh bảo hiểm
Lợi nhuận sau thuế thu nhập doanh nghiệp
Lợi nhuận sau thuế của chủ sở hữu, tập đoàn
```

---

# 10. Cash Flow Statement — Common Corporate Items

| Analytical concept | Exact source `item_name` |
|---|---|
| Net operating cash flow | `Lưu chuyển tiền thuần từ các hoạt động sản xuất kinh doanh` |
| Profit before working-capital changes | `Lãi/lỗ trước những thay đổi vốn lưu động` |
| Profit before tax | `Lãi trước thuế` |
| Depreciation | `Khấu hao TSCĐ` |
| Provision expense | `Chi phí dự phòng` |
| Interest expense | `Chi phí lãi vay` |
| Change in receivables | `(Tăng)/giảm các khoản phải thu` |
| Change in inventory | `(Tăng)/giảm hàng tồn kho` |
| Change in payables | `Tăng/(giảm) các khoản phải trả` |
| Interest paid | `Chi phí lãi vay đã trả` |
| Corporate income tax paid | `Thuế thu nhập doanh nghiệp đã trả` |
| Net investing cash flow | `Lưu chuyển tiền tệ ròng từ hoạt động đầu tư` |
| Purchase of fixed/long-term assets | `Tiền mua tài sản cố định và các tài sản dài hạn khác` |
| Proceeds from disposal of fixed assets | `Tiền thu được từ thanh lý tài sản cố định` |
| Dividends and interest received | `Cổ tức và tiền lãi nhận được` |
| Financing cash flow | `Lưu chuyển tiền tệ từ hoạt động tài chính` |
| Proceeds from issuing shares / capital contribution | `Tiền thu từ phát hành cổ phiếu và vốn góp` |
| Borrowing proceeds | `Tiền thu được các khoản đi vay` |
| Loan repayment | `Tiển trả các khoản đi vay` |
| Dividends paid | `Cổ tức đã trả` |
| Net change in cash | `Lưu chuyển tiền thuần trong kỳ` |
| Beginning cash and cash equivalents | `Tiền và tương đương tiền đầu kỳ` |
| FX effect on cash | `Ảnh hưởng của chênh lệch tỷ giá` |
| Ending cash and cash equivalents | `Tiền và tương đương tiền cuối kỳ` |

The Cash Flow source schema also contains banking-, securities-, and insurance-specific cash-flow items. Search `item_name` and verify the accounting context before constructing cross-sector variables.

---

# 11. Example 1 — Load a Complete Balance Sheet for AAA

This example loads AAA's Balance Sheet from HSX and extracts the five most recent available reporting years.

```python
import pandas as pd
import vnfinancialdata as vnf

TICKER = "AAA"

bs = vnf.load(
    exchange="HSX",
    statement="balance_sheet"
).copy()

bs["year"] = pd.to_numeric(
    bs["year"],
    errors="coerce"
).astype("Int64")

aaa_years = sorted(
    bs.loc[
        bs["ticker"].astype(str).str.upper().eq(TICKER),
        "year"
    ]
    .dropna()
    .astype(int)
    .unique()
)[-5:]

aaa_bs = (
    bs.loc[
        bs["ticker"].astype(str).str.upper().eq(TICKER)
        & bs["year"].isin(aaa_years),
        [
            "ticker",
            "year",
            "item_code",
            "item_name",
            "value",
        ]
    ]
    .reset_index(drop=True)
)

print("Years:", aaa_years)
print(aaa_bs.head(30))
```

## Convert AAA's Balance Sheet to year columns

```python
aaa_bs_wide = (
    aaa_bs.pivot_table(
        index=["item_code", "item_name"],
        columns="year",
        values="value",
        aggfunc="first"
    )
    .reset_index()
)

print(aaa_bs_wide)
```

Conceptual structure:

```text
item_code | item_name                  | 2021 | 2022 | 2023 | 2024 | 2025
----------|----------------------------|------|------|------|------|------
...       | TỔNG TÀI SẢN              | ...  | ...  | ...  | ...  | ...
...       | Tiền và tương đương tiền  | ...  | ...  | ...  | ...  | ...
...       | Hàng tồn kho              | ...  | ...  | ...  | ...  | ...
...       | NỢ PHẢI TRẢ               | ...  | ...  | ...  | ...  | ...
...       | VỐN CHỦ SỞ HỮU            | ...  | ...  | ...  | ...  | ...
```

> Note: a pivoted analytical table does not necessarily reproduce the visual indentation or section formatting of an original published financial statement. It preserves the standardized accounting observations for analysis.

---

# 12. Example 2 — Find the Correct Code for Profit After Tax

For ordinary non-financial companies, start with the exact verified source item:

```text
Lãi/(lỗ) thuần sau thuế
```

Retrieve its actual standardized `item_code`:

```python
import vnfinancialdata as vnf

income = vnf.load(
    exchange="HSX",
    statement="income_statement"
)

TARGET_NAME = "Lãi/(lỗ) thuần sau thuế"

target_item = (
    income.loc[
        income["item_name"].eq(TARGET_NAME),
        ["item_code", "item_name"]
    ]
    .drop_duplicates()
)

print(target_item.to_string(index=False))
```

Validate before continuing:

```python
if target_item.empty:
    raise ValueError(
        f"Item not found: {TARGET_NAME!r}. "
        "Search available item_name values before continuing."
    )

if target_item["item_code"].nunique() != 1:
    raise ValueError(
        "More than one item_code was found for this item_name. "
        "Inspect the mapping before analysis."
    )

PROFIT_AFTER_TAX_CODE = target_item["item_code"].iloc[0]

print(
    "Verified item:",
    PROFIT_AFTER_TAX_CODE,
    "—",
    TARGET_NAME
)
```

---

# 13. Example 3 — Profit After Tax for 10 Companies, Latest Five Years

The following example uses 10 HSX companies for which the reviewed source data contain the ordinary-company line `Lãi/(lỗ) thuần sau thuế` through reporting year 2025.

```python
import pandas as pd
import vnfinancialdata as vnf

TICKERS = [
    "AAA",
    "BTT",
    "CCI",
    "DGC",
    "FPT",
    "GMD",
    "HPG",
    "KDH",
    "REE",
    "VNM",
]

TARGET_NAME = "Lãi/(lỗ) thuần sau thuế"

income = vnf.load(
    exchange="HSX",
    statement="income_statement"
).copy()

income["year"] = pd.to_numeric(
    income["year"],
    errors="coerce"
).astype("Int64")

mapping = (
    income.loc[
        income["item_name"].eq(TARGET_NAME),
        ["item_code", "item_name"]
    ]
    .drop_duplicates()
)

if mapping.empty:
    raise ValueError(
        f"Cannot find item_name {TARGET_NAME!r}"
    )

if mapping["item_code"].nunique() != 1:
    raise ValueError(
        "Ambiguous item_code mapping. "
        "Inspect 'mapping' before continuing."
    )

profit_code = mapping["item_code"].iloc[0]

selected = income.loc[
    income["ticker"]
    .astype(str)
    .str.upper()
    .isin(TICKERS)
    & income["item_code"].eq(profit_code)
].copy()

recent_years = sorted(
    selected["year"]
    .dropna()
    .astype(int)
    .unique()
)[-5:]

profit = (
    selected.loc[
        selected["year"].isin(recent_years),
        [
            "ticker",
            "year",
            "item_code",
            "item_name",
            "value",
        ]
    ]
    .sort_values(["ticker", "year"])
    .reset_index(drop=True)
)

print("Selected item_code:", profit_code)
print("Selected item_name:", TARGET_NAME)
print("Years:", recent_years)
print(profit)
```

## Convert to a research-friendly company × year table

```python
profit_panel = (
    profit.pivot_table(
        index="ticker",
        columns="year",
        values="value",
        aggfunc="first"
    )
    .reindex(TICKERS)
)

print(profit_panel)
```

With the current reviewed source files, the five most recent reporting years are expected to be:

```text
2021
2022
2023
2024
2025
```

for the ten example companies above.

### Use only the latest three years

```python
recent_years = sorted(
    selected["year"].dropna().astype(int).unique()
)[-3:]
```

---

# 14. Example 4 — Search for All “Profit After Tax” Variants

This is strongly recommended before mixing financial and non-financial firms:

```python
profit_after_tax_candidates = (
    income.loc[
        income["item_name"]
        .astype(str)
        .str.contains(
            "sau thuế",
            case=False,
            na=False
        ),
        ["item_code", "item_name"]
    ]
    .drop_duplicates()
    .sort_values(["item_name", "item_code"])
)

print(
    profit_after_tax_candidates.to_string(
        index=False
    )
)
```

This allows the user to distinguish among concepts such as:

```text
Lãi/(lỗ) thuần sau thuế
Lợi nhuận sau thuế
Lợi nhuận kế toán sau thuế
Lợi nhuận sau thuế phân bổ cho chủ sở hữu
Lợi nhuận sau thuế thu nhập doanh nghiệp
Lợi nhuận sau thuế của chủ sở hữu, tập đoàn
```

---

# 15. Example 5 — Retrieve a Balance Sheet Indicator Across Companies

For example, retrieve **Tiền và tương đương tiền**:

```python
import pandas as pd
import vnfinancialdata as vnf

TICKERS = [
    "AAA",
    "DGC",
    "FPT",
    "GMD",
    "HPG",
    "KDH",
    "REE",
    "VNM",
]

TARGET_NAME = "Tiền và tương đương tiền"

bs = vnf.load(
    exchange="HSX",
    statement="balance_sheet"
).copy()

bs["year"] = pd.to_numeric(
    bs["year"],
    errors="coerce"
).astype("Int64")

mapping = (
    bs.loc[
        bs["item_name"].eq(TARGET_NAME),
        ["item_code", "item_name"]
    ]
    .drop_duplicates()
)

if mapping["item_code"].nunique() != 1:
    raise ValueError(
        "Inspect the item mapping before analysis."
    )

cash_code = mapping["item_code"].iloc[0]

cash = (
    bs.loc[
        bs["ticker"]
        .astype(str)
        .str.upper()
        .isin(TICKERS)
        & bs["item_code"].eq(cash_code),
        [
            "ticker",
            "year",
            "item_code",
            "item_name",
            "value",
        ]
    ]
    .sort_values(["ticker", "year"])
)

print(cash)
```

This is preferable to incorrectly writing:

```python
df["item_code"] == "Tiền"
```

because `Tiền` is an `item_name`, not an assumed standardized code.

---

# 16. Recommended Helper: Search the Item Dictionary

Users can define a reusable helper:

```python
def search_items(df, keyword):
    # Search standardized item_code-item_name pairs
    # by a case-insensitive keyword.
    dictionary = (
        df[["item_code", "item_name"]]
        .drop_duplicates()
    )

    return (
        dictionary.loc[
            dictionary["item_name"]
            .astype(str)
            .str.contains(
                keyword,
                case=False,
                na=False
            )
        ]
        .sort_values(["item_name", "item_code"])
        .reset_index(drop=True)
    )
```

Usage:

```python
print(search_items(income, "sau thuế"))
```

```python
print(search_items(bs, "tiền"))
```

---

# 17. Cross-Sector Research Warning

The dataset deliberately contains financial-statement templates for multiple sectors.

As a result, one economic concept can have different valid reporting lines.

For example:

```text
Industrial company
    ↓
Lãi/(lỗ) thuần sau thuế

Bank
    ↓
Lợi nhuận sau thuế

Securities company
    ↓
Lợi nhuận kế toán sau thuế

Insurance / group reporting
    ↓
Lợi nhuận sau thuế thu nhập doanh nghiệp
or
Lợi nhuận sau thuế của chủ sở hữu, tập đoàn
```

For cross-sector samples, researchers should construct a documented concept mapping rather than assuming one item applies to every sector.

---

# 18. Missing Data Are Not Zero

A missing financial statement observation should not automatically be converted to zero.

```python
print(
    profit[
        ["ticker", "year", "value"]
    ]
    .isna()
    .sum()
)
```

Check coverage:

```python
coverage = (
    profit.groupby("ticker")["year"]
    .nunique()
    .sort_values()
)

print(coverage)
```

Check expected company-year combinations:

```python
expected = (
    len(TICKERS)
    * len(recent_years)
)

observed = (
    profit[
        ["ticker", "year"]
    ]
    .drop_duplicates()
    .shape[0]
)

print("Expected:", expected)
print("Observed:", observed)
```

---

# 19. Check Duplicate Standardized Observations

Before econometric analysis:

```python
duplicates = (
    profit.groupby(
        ["ticker", "year", "item_code"]
    )
    .size()
    .reset_index(name="n")
    .query("n > 1")
)

print(duplicates)
```

If duplicates exist, investigate them before applying `first`, `sum`, or another aggregation rule.

---

# 20. Long-Format Design

The package presents standardized data in long format:

```text
ticker | year | exchange | statement | item_code | item_name | value
```

rather than maintaining hundreds of financial items as separate columns.

This design supports:

- firm-year panel construction;
- cross-sectional analysis;
- time-series analysis;
- accounting-ratio construction;
- econometrics;
- machine learning;
- visualization;
- reusable indicator extraction;
- scalable filtering across exchanges.

---

# 21. Recommended Production Workflow

For serious financial research:

```text
1. Choose statement type
       ↓
2. Load data
       ↓
3. Search exact item_name
       ↓
4. Inspect item_code–item_name candidates
       ↓
5. Confirm accounting interpretation
       ↓
6. Store verified item_code
       ↓
7. Filter tickers and years
       ↓
8. Check missing values
       ↓
9. Check duplicates
       ↓
10. Reshape to panel / wide form
       ↓
11. Record package + dataset + schema versions
       ↓
12. Record item_code + item_name in research documentation
```

---

# 22. Reproducibility

For reproducible research, record at least:

```text
Package:
vnfinancialdata 0.1.2

Dataset:
v1.0.0

Schema:
1.0

Exchange:
HSX / HNX

Statement:
balance_sheet / income_statement / cash_flow

Selected standardized variable:
item_code = <verified code>
item_name = <verified name>
```

Example research metadata:

```python
RESEARCH_METADATA = {
    "package": "vnfinancialdata",
    "package_version": "0.1.2",
    "dataset_version": "v1.0.0",
    "schema_version": "1.0",
    "exchange": "HSX",
    "statement": "income_statement",
    "item_code": profit_code,
    "item_name": "Lãi/(lỗ) thuần sau thuế",
}
```

---

# 23. Data Quality and Transformation Principles

The source files are spreadsheet-oriented wide tables containing:

```text
Mã chứng khoán
Năm
financial item 1
financial item 2
...
financial item n
```

The standardized package workflow transforms these records into long-format observations.

Conceptually:

```text
SOURCE

Mã chứng khoán | Năm | TỔNG TÀI SẢN | Tiền | ... | EBITDA
AAA            | 2025| ...           | ...  | ... | ...


                    ↓ standardization


PACKAGE

ticker | year | statement | item_code | item_name     | value
AAA    | 2025 | ...       | ...       | TỔNG TÀI SẢN | ...
AAA    | 2025 | ...       | ...       | Tiền          | ...
```

This enables consistent programmatic analysis without requiring users to manipulate hundreds of source spreadsheet columns manually.

---

# 24. Dataset Design Notes from the Reviewed Source Files

The reviewed source files reveal several important structural characteristics.

### Same financial-item universe across HSX and HNX

For each statement category, HSX and HNX contain the same item-name set:

```text
Balance Sheet:     311 items
Income Statement:  195 items
Cash Flow:         196 items
```

### Multi-sector schema

The dataset is not limited to a single industrial-company template.

It includes line items used by:

- ordinary non-financial corporations;
- banks and credit institutions;
- securities companies;
- insurance companies;
- consolidated/group reporting templates.

### Historical reporting changes

Some item names explicitly indicate historical reporting regimes, for example:

```text
(trước 2010)
(trước 2014)
(trước 2015)
(từ năm 2015)
(từ 2016)
```

Researchers conducting long historical analyses should consider whether a reporting-line definition changes across periods.

---

# 25. Citation

When using the dataset in academic work, report the dataset revision and package version.

Suggested dataset reference:

```text
Vietnamese Listed Companies Financial Data.
Dataset version v1.0.0.
```

For empirical reproducibility, also report:

```text
vnfinancialdata version 0.1.2
schema version 1.0
selected item_code(s)
selected item_name(s)
sample exchanges
sample years
```

---

# 26. Intended Use

`vnfinancialdata` is intended for:

- academic research;
- corporate finance;
- accounting research;
- financial econometrics;
- financial-statement analysis;
- panel-data construction;
- financial modeling;
- quantitative research;
- education;
- reproducible data-analysis workflows.

---

# 27. License

The package and underlying dataset should be used according to the license and source-rights information published with the corresponding release.

Users remain responsible for evaluating the suitability of the data and applicable source terms for their intended use.

---

# 28. Disclaimer

`vnfinancialdata` and its associated dataset are provided for **research, educational, analytical, and data-processing purposes**.

Although standardized transformation and validation procedures are applied, no guarantee is made that every observation is free from errors, omissions, reporting differences, restatements, or source-data issues.

Users should verify financially consequential observations against original financial statements, annual reports, stock-exchange disclosures, or official company publications.

**The package and dataset do not constitute investment advice.**

---

# 29. Version Summary

| Component | Version |
|---|---|
| Python package | `0.1.2` |
| Dataset | `v1.0.0` |
| Schema | `1.0` |
| Python requirement | `>=3.10` |
| Exchanges | `HSX`, `HNX` |
| Balance Sheet items | `311` |
| Income Statement items | `195` |
| Cash Flow items | `196` |

---

## Quick Start Summary

### Load one company's statement

```python
import vnfinancialdata as vnf

bs = vnf.load(
    exchange="HSX",
    statement="balance_sheet"
)

aaa = bs[
    bs["ticker"]
    .astype(str)
    .str.upper()
    .eq("AAA")
]
```

### Find an accounting item

```python
income = vnf.load(
    exchange="HSX",
    statement="income_statement"
)

income[
    income["item_name"]
    .astype(str)
    .str.contains(
        "sau thuế",
        case=False,
        na=False
    )
][["item_code", "item_name"]].drop_duplicates()
```

### Then filter with the verified `item_code`

```python
result = income[
    income["item_code"].eq(
        VERIFIED_ITEM_CODE
    )
]
```

---

**`vnfinancialdata` — standardized, reproducible, programmatic access to Vietnamese listed-company financial statements.**
