Chỉ số tài chính
Mục lục
Tính năng trên trang này đang trong giai đoạn phát triển thử nghiệm và chưa ổn định. Bạn dùng được để tìm hiểu và chạy thử, nhưng tên hàm hay công cụ, tham số và cấu trúc kết quả có thể còn đổi giữa các bản phát hành, cách tính và cách xử lý cũng có thể còn được hiệu chỉnh.
Hãy đối chiếu kết quả với một cách tính độc lập trước khi đưa vào quy trình nghiên cứu, và ghim phiên bản thư viện trong dự án để mã đang chạy không tự đổi theo bản mới.
Tổng quan
vnstock_quant.fa tính 100 chỉ số từ báo cáo tài chính theo bốn mẫu ngành: doanh nghiệp phi tài chính (dn), ngân hàng (tctd), công ty chứng khoán (ctck) và bảo hiểm (dnpnt). Mỗi chỉ số chỉ áp dụng cho một số mẫu ngành; chỉ số không áp dụng trả NaN kèm lý do NOT_APPLICABLE. Bạn có thể tra công thức của từng chỉ số, chọn kỳ quý (TTM) hay kỳ năm, và xem vì sao một ô không có số.
Bản Cộng đồng tính được 10 chỉ số cơ bản: RT_VALUE_PE, RT_VALUE_PB, RT_VALUE_EPS, RT_VALUE_BVPS, RT_PRT_ROE, RT_PRT_ROA, RT_PRT_GROSS_MARGIN, RT_PRT_NET_MARGIN, RT_LQD_CR, RT_LEV_DE. Các chỉ số còn lại cần gói Bronze trở lên (cột access của fa.catalog()).
Cách tính kỳ quý (TTM)
Với period="quarter", mỗi dòng quý là số liệu 12 tháng gần nhất tính đến cuối quý đó:
- Chỉ tiêu thời kỳ (doanh thu, lợi nhuận, dòng tiền): cộng 4 quý gần nhất.
- Chỉ tiêu thời điểm dùng làm mẫu số bình quân (tài sản, vốn chủ, phải thu...): trung bình 4 điểm cuối quý gần nhất với hồ sơ
vn, 5 điểm với hồ sơcfa. - Dòng quý 4 lấy số liệu từ BCTC năm của năm đó (đã kiểm toán): chỉ tiêu thời kỳ là số cả năm, giá trị cuối kỳ là số cuối năm. Mẫu số bình quân vẫn là 4 (hoặc 5) điểm cuối quý như các quý khác, với điểm cuối là số cuối năm đã kiểm toán, nên chuỗi quý không bị nhảy ở quý 4.
- Các quý đầu tiên của dữ liệu trả
NaNvới lý doINSUFFICIENT_HISTORY: ba quý đầu chưa đủ 4 quý để cộng dồn, và quý 4 của năm đầu tiên chưa có cuối năm trước để tính bình quân.
Chuẩn bị dữ liệu đầu vào với Dataset
Lớp Dataset gom báo cáo tài chính, giá đóng cửa và số cổ phiếu lưu hành của các mã bạn chọn vào một đối tượng để các hàm tính toán dùng tiếp.
Cách 1: Tải trực tiếp qua vnstock
from vnstock_quant import fa
# Tải BCTC năm và quý, giá và số cổ phiếu của FPT và VCB
ds = fa.Dataset.load(["FPT", "VCB"])
print(ds)
# Dataset(FPT:DN, VCB:TCTD)Mặc định Dataset.load() tải cả BCTC năm và quý (period="both"). Nên giữ mặc định này: dòng quý 4 cần BCTC năm, và fa.ratios(..., period="year") chỉ có số khi đã tải BCTC năm. Mẫu ngành được nhận diện tự động (DN, TCTD...); bạn có thể chỉ định bằng com_type.
Dataset.load() truy xuất nhiều bảng cho mỗi mã, nên có thể dùng nhiều lượt trong hạn mức chung. Bản Cộng đồng cho phép tối đa 3 mã trong một lần gọi và cần prices=False, vì giá chưa điều chỉnh cần cấp quyền sử dụng (xem trang bản Cộng đồng). Nếu cần xử lý nhiều mã, hãy chuẩn bị dữ liệu theo từng nhóm và cân nhắc lưu dữ liệu trên máy để dùng lại.
Cách 2: Tự nạp từ DataFrame cá nhân
Nếu bạn đã có sẵn dữ liệu BCTC, hãy nạp vào Dataset ở dạng long (các cột period, id, value), dùng mã chỉ tiêu của vnstock. Chỉ số dùng mẫu số bình quân (ROE, ROA...) cần ít nhất hai kỳ:
import pandas as pd
from vnstock_quant import fa
# Dữ liệu BCTC năm mẫu dạng long, hai năm liên tiếp
rows = []
for period, revenue, npat, np_parent, equity, assets in [
("2023", 1000e9, 150e9, 140e9, 1000e9, 1800e9),
("2024", 1200e9, 190e9, 180e9, 1200e9, 2000e9),
]:
rows += [
{"period": period, "id": "IS_NET_REVENUE", "value": revenue},
{"period": period, "id": "IS_NET_PROFIT_AFTER_TAX", "value": npat},
{"period": period, "id": "IS_PROFIT_AFTER_TAX_FOR_SHAREHOLDERS_OF_PARENT_COMPANY", "value": np_parent},
{"period": period, "id": "BS_EQUITY", "value": equity},
{"period": period, "id": "BS_TOTAL_ASSETS", "value": assets},
]
ds_own = fa.Dataset.from_frames({"AAA": [pd.DataFrame(rows)]}, com_type="dn")
# Dữ liệu chỉ có kỳ năm nên phải tính với period="year"
print(fa.ratios(ds_own, ids=["RT_PRT_ROE", "RT_PRT_ROA", "RT_PRT_NET_MARGIN"], period="year")) symbol period id value unit reason
0 AAA 2023 RT_PRT_ROE NaN ratio INSUFFICIENT_HISTORY
1 AAA 2024 RT_PRT_ROE 0.163636 ratio NaN
2 AAA 2023 RT_PRT_ROA NaN ratio INSUFFICIENT_HISTORY
3 AAA 2024 RT_PRT_ROA 0.094737 ratio NaN
4 AAA 2023 RT_PRT_NET_MARGIN 0.150000 ratio NaN
5 AAA 2024 RT_PRT_NET_MARGIN 0.158333 ratio NaNROE năm 2024 = 180 / ((1.000 + 1.200) / 2) = 16,36%. Năm 2023 không có năm trước để tính vốn chủ bình quân nên trả INSUFFICIENT_HISTORY. Nếu gọi với period="quarter" (mặc định) trên dữ liệu chỉ có kỳ năm, kết quả là bảng rỗng.
Để tính chỉ số định giá (P/E, P/B, EV/EBITDA...), truyền thêm prices={"AAA": df_gia} với các cột time, close, total_shares.
Tính toán chỉ số với fa.ratios()
# Tính ROE, ROA và biên lợi nhuận ròng theo kỳ quý (TTM)
ratios = fa.ratios(ds, ids=["RT_PRT_ROE", "RT_PRT_ROA", "RT_PRT_NET_MARGIN"])
# Xoay các chỉ số thành cột để đọc theo thời gian
ts = fa.ratios(ds, ids=["RT_PRT_ROE", "RT_PRT_ROA", "RT_PRT_NET_MARGIN"], format="time_series")
print(ts.loc["FPT"].tail(4))id RT_PRT_NET_MARGIN RT_PRT_ROA RT_PRT_ROE
period
2025-Q3 0.1591 0.1156 0.2737
2025-Q4 0.1602 0.1150 0.2725
2026-Q1 0.1670 0.1208 0.2682
2026-Q2 0.1718 0.1278 0.2647Kết quả dạng long được sắp theo mã, rồi theo chỉ số, rồi theo kỳ. Vì vậy print(ratios) thường chỉ hiện vài dòng đầu và cuối, đúng những ô NaN: các quý đầu chưa đủ lịch sử để tính TTM, và với VCB thì RT_PRT_NET_MARGIN không áp dụng cho ngân hàng (NOT_APPLICABLE). Bảng vẫn có số ở các kỳ khác. Để xem nhanh ô nào trống và vì sao:
# Đếm số ô trống theo mã, chỉ số và lý do
print(ratios[ratios["value"].isna()].groupby(["symbol", "id", "reason"], observed=True).size())Các tham số quan trọng
| Tham số | Giá trị lựa chọn | Ý nghĩa |
|---|---|---|
ids | ["RT_..."] hoặc None | Danh sách mã chỉ số cần tính. None: tính mọi chỉ số áp dụng được cho mẫu ngành của từng mã và cấp quyền của bạn; chỉ số cần cấp cao hơn bị bỏ qua kèm cảnh báo. |
period | "quarter" (mặc định) hoặc "year" | "quarter": mỗi dòng là 12 tháng gần nhất (TTM), xem mục Cách tính kỳ quý. "year": tính trên BCTC năm. |
profile | "vn" (mặc định) hoặc "cfa" | Hồ sơ phương pháp luận. "vn" theo cách thị trường Việt Nam công bố số liệu; "cfa" theo định nghĩa của giáo trình CFA. Xem fa.profiles(). |
overrides | {"tên_nút": giá_trị} | Thay một nút của hồ sơ, ví dụ {"quarter_avg_points": 5}. |
format | "long" (mặc định), "wide", "time_series" | Định dạng kết quả. |
Hai hồ sơ khác nhau ở các nút sau:
| Nút | vn | cfa |
|---|---|---|
quarter_avg_points | 4 điểm cuối quý | 5 điểm cuối quý (thêm cuối quý ngay trước cửa sổ 12 tháng) |
| Ngày định giá | Phiên cuối cùng trước hoặc bằng ngày cuối quý kế tiếp + 14 ngày | Phiên cuối cùng trước hoặc bằng ngày cuối kỳ |
Giá đóng cửa và số cổ phiếu luôn lấy trong cùng một phiên, nên P/E = giá / EPS và P/B = giá / BVPS trong cùng một dòng. Kỳ năm dùng ngày định giá của quý 4 năm đó, nên dòng năm trùng dòng quý 4.
Một số chỉ số có công thức riêng cho từng hồ sơ (ví dụ RT_EFF_DIO dùng tồn kho theo giá gốc với vn, giá trị thuần với cfa); fa.describe() ghi rõ.
Định dạng đầu ra
format="long"(mặc định): các cộtsymbol,period,id,value,unit,reason. Phù hợp để lưu trữ hoặc lọc:Pythonratios.query('symbol == "VCB" and id == "RT_PRT_ROE"').tail(4)format="wide": chỉ mục là (symbol,id), mỗi kỳ là một cột, dễ đọc xu hướng qua các kỳ.format="time_series": chỉ mục là (symbol,period), mỗi chỉ số là một cột, thuận tiện đưa vào mô hình hồi quy hoặc học máy.
Kết quả của fa.ratios() mang từ điển mô tả ở attrs["dictionary"], nên bạn tra được ngay các mã viết tắt như COF, CIR, DIO, NIM.
info = ratios.attrs["dictionary"]["RT_BANK_COF"]
print(info)
# {'name': 'Chi phí vốn', 'name_en': 'Cost of funds',
# 'describe': 'Chi phí lãi và tương tự (TTM, mang dấu âm) / nợ chịu lãi bình quân (nợ NHNN, tiền gửi và vay TCTD, tiền gửi khách hàng, giấy tờ có giá).',
# 'unit': 'ratio', 'category': 'banking'}Cột reason: vì sao một ô không có số
vnstock_quant không tự điền số 0 khi thiếu dữ liệu đầu vào. Khi một ô mang giá trị NaN, cột reason cho biết nguyên nhân:
Mã reason | Giải thích |
|---|---|
MISSING_INPUT:<mã_chỉ_tiêu> | BCTC thiếu chỉ tiêu <mã_chỉ_tiêu> mà công thức cần. Chỉ tiêu bắt đầu bằng NT_ nằm trong thuyết minh BCTC (ví dụ nợ xấu, CASA của ngân hàng). |
INSUFFICIENT_HISTORY | Chưa đủ kỳ trước đó để cộng dồn TTM, tính bình quân hoặc so sánh với kỳ trước. |
ZERO_DENOMINATOR | Mẫu số bằng 0. Mẫu số âm (ví dụ vốn chủ âm) vẫn cho ra số âm, không trả NaN. |
NOT_APPLICABLE | Chỉ số không áp dụng cho mẫu ngành này (ví dụ biên lợi nhuận ròng với ngân hàng, NIM với doanh nghiệp phi tài chính). |
MISSING_MARKET | Chỉ số định giá nhưng không có giá đóng cửa hoặc số cổ phiếu tại ngày định giá. |
Quy ước dấu và đơn vị
- Tỷ lệ là phân số thập phân (
0.18là 18%). Cộtunitcho biết đơn vị:ratio,times(lần),days(ngày),VND,VND/share,shares. - Bốn chỉ số ngân hàng giữ dấu âm của chi phí và dự phòng, như cách số liệu thị trường thường hiển thị:
RT_BANK_COF,RT_BANK_CIR,RT_BANK_NPL_COVERAGE,RT_BANK_PROVISION_TO_LOANS. Ví dụ VCB năm 2025 cóRT_BANK_CIR = -0.348, tức chi phí hoạt động bằng 34,8% tổng thu nhập hoạt động. Dùngabs()nếu bạn cần độ lớn. - EPS, BVPS, doanh thu và dòng tiền mỗi cổ phiếu chia cho số cổ phiếu lưu hành tại ngày định giá của từng kỳ, chưa điều chỉnh theo cổ tức bằng cổ phiếu hay phát hành thêm. Khi so sánh EPS qua nhiều năm, hãy lưu ý các đợt chia cổ phiếu.
- Dòng quý 4 và dòng năm: các chỉ số dùng mẫu số bình quân (ROE, ROA, NIM, số ngày thu tiền...) ở dòng quý 4 tính theo bình quân 4 điểm cuối quý, còn dòng năm tính theo bình quân đầu năm và cuối năm, nên hai dòng có thể chênh nhẹ. Các chỉ số khác của dòng quý 4 trùng dòng năm.
- Tăng trưởng tín dụng và huy động (
RT_BANK_LOAN_GROWTH,RT_BANK_DEPOSIT_GROWTH): kỳ quý là tăng trưởng một quý so với cuối quý trước (kể cả quý 4), kỳ năm là tăng trưởng so với cuối năm trước. - CIR và thu nhập ngoài lãi (
RT_BANK_CIR,RT_BANK_NOII) tính trên số riêng của quý, không phải TTM, kể cả quý 4; dòng năm là số cả năm. Ngân hàng thường dồn chi phí vào quý 4, nên CIR quý 4 hay cao hơn các quý khác (VCB quý 4/2025: −0,391, cả năm 2025: −0,348). - Chỉ số định giá dùng giá tại ngày định giá của hồ sơ (bảng hồ sơ ở trên), không dùng ngày BCTC được công bố. Với hồ sơ
vn, giá đó có thể nằm sau ngày công bố BCTC vài tháng; kỳ gần nhất dùng giá mới nhất cho tới ngày định giá. Nếu dùng chỉ số định giá cho kiểm định chiến lược, hãy tự ghép giá theo ngày công bố BCTC.
Các nhóm chỉ số tiêu biểu
Danh sách đầy đủ 100 chỉ số, kèm công thức và mẫu ngành áp dụng, có trong fa.catalog(). Dưới đây là các chỉ số hay dùng.
1. Khả năng sinh lợi
RT_PRT_ROE: Lợi nhuận cổ đông công ty mẹ (TTM) / vốn chủ của cổ đông công ty mẹ bình quân. Ngân hàng chia cho tổng vốn chủ bình quân; kỳ năm của ngân hàng dùng lợi nhuận sau thuế toàn bộ.RT_PRT_ROA: Lợi nhuận cổ đông công ty mẹ (TTM) / tổng tài sản bình quân.RT_PRT_ROCE: EBIT / (tổng tài sản − nợ ngắn hạn) bình quân.RT_PRT_GROSS_MARGIN: Lợi nhuận gộp / doanh thu thuần.RT_PRT_NET_MARGIN: Lợi nhuận sau thuế toàn bộ (gồm cổ đông không kiểm soát) / doanh thu thuần. Không áp dụng cho ngân hàng.RT_PRT_EBITDA_MARGIN: EBITDA / doanh thu thuần.
EBIT trong thư viện là lợi nhuận hoạt động cốt lõi: lợi nhuận gộp − chi phí bán hàng − chi phí quản lý, không gồm thu nhập và chi phí tài chính hay thu nhập khác. EBITDA = EBIT + khấu hao trên báo cáo lưu chuyển tiền tệ.
2. Đòn bẩy và khả năng thanh toán
RT_LEV_DE: Tổng nợ phải trả / vốn chủ sở hữu. Tỷ lệ nợ vay / vốn chủ làRT_LEV_LOAN_EQUITY.RT_LEV_NET_DEBT: Vay ngắn và dài hạn − tiền và tương đương tiền − đầu tư tài chính ngắn hạn (VND).RT_LEV_NET_DEBT_EBITDA: Nợ vay ròng / EBITDA (TTM).RT_LEV_INTEREST_COVERAGE: EBIT / chi phí lãi vay (TTM).RT_LQD_CR: Tài sản ngắn hạn / nợ ngắn hạn.RT_LQD_QR: Với hồ sơvn, kỳ quý dùng (tài sản ngắn hạn − tồn kho) / nợ ngắn hạn, kỳ năm dùng (tiền + phải thu ngắn hạn) / nợ ngắn hạn. Hồ sơcfadùng (tiền + đầu tư ngắn hạn + phải thu ngắn hạn) / nợ ngắn hạn.RT_LQD_CASH_RATIO: Tiền và tương đương tiền / nợ ngắn hạn.
3. Hiệu quả hoạt động
RT_EFF_ATR: Doanh thu thuần / tổng tài sản bình quân.RT_EFF_INVENTORY_TURNOVER: Giá vốn hàng bán / tồn kho bình quân (hồ sơvndùng tồn kho theo giá gốc, trước dự phòng).RT_EFF_RECEIVABLE_TURNOVER: Doanh thu thuần / phải thu khách hàng bình quân.RT_EFF_DIO,RT_EFF_DSO,RT_EFF_DPO: Số ngày tồn kho, thu tiền, thanh toán (365 ngày).RT_EFF_CASH_CYCLE: DSO + DIO − DPO.
4. Ngân hàng (mẫu TCTD)
RT_BANK_NIM: Thu nhập lãi thuần (TTM) / tài sản sinh lãi bình quân (tiền gửi NHNN, tiền gửi và cho vay TCTD khác, chứng khoán đầu tư, dư nợ gộp).RT_BANK_YIEA: Thu nhập lãi và tương tự (TTM) / tài sản sinh lãi bình quân.RT_BANK_COF: Chi phí lãi (TTM, dấu âm) / nợ chịu lãi bình quân.RT_BANK_CIR: Chi phí hoạt động (dấu âm) / tổng thu nhập hoạt động, số riêng của quý.RT_BANK_CASA: (Tiền gửi không kỳ hạn + ký quỹ + vốn chuyên dùng) / tiền gửi khách hàng. Cần thuyết minh BCTC.RT_BANK_LDR: Dư nợ gộp / tiền gửi khách hàng (tỷ lệ phân tích, không phải tỷ lệ theo quy định của NHNN).RT_BANK_NPL: Nợ nhóm 3–5 / dư nợ gộp. Cần thuyết minh BCTC.RT_BANK_NPL_COVERAGE: Dự phòng rủi ro cho vay (dấu âm) / nợ nhóm 3–5.RT_BANK_PROVISION_TO_LOANS: Chi phí dự phòng rủi ro tín dụng (TTM, dấu âm) / dư nợ gộp bình quân.RT_BANK_CAR: Hệ số an toàn vốn chép từ thuyết minh, không tính lại.
Dataset.load() tự tải thuyết minh cho ngân hàng (cần gói quyền sử dụng). Nếu không tải được, các chỉ số cần chỉ tiêu NT_ trả MISSING_INPUT.
5. Dòng tiền tự do theo CFA
RT_CF_FCFF: Lưu chuyển tiền kinh doanh + lãi vay đã trả × (1 − thuế suất hiệu dụng) − (chi mua TSCĐ − thu thanh lý TSCĐ). Theo VAS, lãi vay đã trả nằm trong dòng tiền kinh doanh nên được cộng lại sau thuế.RT_CF_FCFE: Lưu chuyển tiền kinh doanh − đầu tư TSCĐ thuần + vay mới − trả nợ gốc.
Các chỉ số dựa trên lưu chuyển tiền thuần từ hoạt động kinh doanh (RT_VALUE_P_CF, RT_VALUE_CFPS, RT_CF_CROA, RT_CF_CROE, RT_CF_INCOME_QUALITY, RT_CF_DEBT_COVERAGE, RT_CF_DIVIDEND_PAYMENT, RT_CF_TO_REVENUE) không áp dụng cho ngân hàng và công ty chứng khoán (NOT_APPLICABLE). Dòng tiền kinh doanh của hai loại hình này chủ yếu là tiền gửi, cho vay và mua bán chứng khoán, nên không đo được khả năng tạo tiền.
6. Phân rã DuPont và các điểm số
- DuPont 3 nhân tố:
RT_DUPONT_NET_MARGIN×RT_DUPONT_ASSET_TURNOVER×RT_DUPONT_LEVERAGE= ROE (cùng dùng lợi nhuận và vốn chủ của cổ đông công ty mẹ). - DuPont 5 nhân tố theo CFA:
RT_DUPONT_TAX_BURDEN(lợi nhuận sau thuế / lợi nhuận trước thuế) ×RT_DUPONT_INTEREST_BURDEN(lợi nhuận trước thuế / EBIT, có thể lớn hơn 1 vì gồm thu nhập tài chính) ×RT_DUPONT_EBIT_MARGIN× vòng quay tài sản × đòn bẩy. Vì ROE tính trên lợi nhuận của cổ đông công ty mẹ, nhân thêmRT_DUPONT_PARENT_SHARE(lợi nhuận cổ đông công ty mẹ / lợi nhuận sau thuế) thì tích sáu thành phần bằng đúng ROE. Ví dụ FPT năm 2025: 0,835 × 0,861 × 1,187 × 0,157 × 0,876 × 2,416 = 0,283. - Altman Z'' (
RT_SCORE_ALTMAN_Z2): 6,56·X1 + 3,26·X2 + 6,72·X3 + 1,05·X4, chỉ dùng số liệu BCTC; dưới 1,1 là vùng nguy cơ, trên 2,6 là vùng an toàn. - Piotroski F-score (
RT_SCORE_PIOTROSKI_F): tổng 9 tín hiệu 0/1 so với cùng kỳ năm trước, từ 0 đến 9. - Beneish M-score (
RT_SCORE_BENEISH_M): mô hình 8 biến; trên −1,78 là dấu hiệu có thể điều chỉnh lợi nhuận. Ngưỡng được đề xuất cho mẫu doanh nghiệp Mỹ, chỉ nên dùng để sàng lọc. - Tỷ lệ dồn tích (
RT_QUALITY_ACCRUALS_BS,RT_QUALITY_ACCRUALS_CF): theo bảng cân đối và theo lưu chuyển tiền tệ, đo chất lượng lợi nhuận kế toán. Tài sản hoạt động thuần (NOA) loại tiền và đầu tư ngắn hạn; tương ứng, bản theo lưu chuyển tiền tệ loại tiền chi cho vay, gửi có kỳ hạn và tiền thu hồi khỏi dòng tiền đầu tư, nên hai bản đo cùng một khái niệm.
Các chỉ số nhóm 5 và 6 cần gói Bronze trở lên (fa_advanced).
Tra cứu công thức và catalog
# Xem cách tính, công thức theo mẫu ngành và theo hồ sơ của ROE
print(fa.describe("RT_PRT_ROE"))
# Xem toàn bộ danh mục chỉ số và nhóm quyền
catalog_df = fa.catalog()
print(catalog_df[["id", "name", "category", "access"]].head(15))
# Lọc các chỉ số áp dụng cho ngân hàng
print(catalog_df[catalog_df["templates"].str.contains("TCTD")][["id", "name"]])
# Xem các nút của hồ sơ 'vn' và 'cfa'
print(fa.profiles())Đọc tiếp
- Đo lường rủi ro và hiệu suất — Đo lường Sharpe, Sortino, VaR và thanh khoản Amihud.
- Quản lý danh mục đầu tư — Tối ưu danh mục và mô phỏng chi phí giao dịch Việt Nam.
- Mô hình định giá — Định giá cổ phiếu dựa trên dòng cổ tức và chỉ số P/E.
