Vnstock Logo

Chuyển từ thế hệ 5

Thử nghiệm

Mục lục

Bản thử nghiệm, chưa phát hành chính thức

Trang này viết cho vnstock v6.0.0rc3, bản thử nghiệm. Tên hàm, tham số và cột dữ liệu có thể còn đổi trước ngày phát hành; khi cài, ghi rõ số phiên bản như ở trang Cài đặt. Bản đang phát hành chính thức là v5.0.1, xem tài liệu bản đó.

Nguồn của bạn

Chọn nguồn bạn có khoá, mã trên trang sẽ điền theo. Chưa chọn thì mã giữ chỗ trống <nguồn>. Nguồn xếp theo bảng chữ cái, không phải khuyến nghị.

Trang này dành cho mã đang dùng vnstock thế hệ 5. Các bước dưới đây giúp bạn xác định phần nào tiếp tục chạy, phần nào cần sửa và cách giữ tên cột cũ trong thời gian chuyển đổi.

Thứ tự nên làm

  1. Cài thế hệ 6 vào môi trường Python riêng, cạnh môi trường đang chạy.
  2. Đăng ký khoá ở nguồn bạn định dùng, kiểm bằng vnstock doctor và vnstock keys check (Cài đặt).
  3. Chọn nguồn: thêm source= vào lời gọi, hoặc đặt một lần bằng vnstock.sources.use(...).
  4. Chạy mã cũ. Hồ sơ mặc định v5 giữ tên cột, thứ tự cột, đơn vị, mốc giờ như thế hệ 5.
  5. Đọc các cảnh báo SchemaChangeWarning và df.attrs["schema_changes"] để biết bảng nào khác thế hệ 5.
  6. Đối chiếu vài bảng giữa hai thế hệ.

Phần giữ nguyên

  • Tên lớp, tên nhóm, tên hàm thế hệ 5: Market().equity("FPT").ohlcv(...), Reference().equity.list(), các tên khác như history, price_board, intraday; các hàm gọi thẳng trên Market() (Market().quote(...)), nhóm Market().future(...), chỉ số quốc tế Market().index(..., scope="global"), lớp Retail.
  • Tên, thứ tự cột, đơn vị giá (đồng ở bảng giá, nghìn đồng ở nến), tỷ lệ phần trăm, match_type, kiểu số.
  • Mốc giờ nến ngày 07:00+07:00; tài sản quốc tế theo UTC; ở hồ sơ v5, luồng tiền xếp mới nhất trước.
  • length, count_back, limit, floating của nến, ở mọi nhóm có nến: cổ phiếu, chỉ số, phái sinh, chứng quyền, tiền mã hoá, ngoại hối, hàng hoá, chỉ số quốc tế.
  • resolution, count của nến vẫn chạy, kèm CompatibilityWarning; đổi sang interval, count_back.
  • Tham số theo vị trí và tên tham số của thế hệ 5 (mục dưới).
  • Các khoá df.attrs của thế hệ 5: symbols, limit, exchange, group, language (None khi lời gọi không đặt).
  • Các lệnh vnstock trong terminal: login, status, doctor, version, update, language, telemetry; gõ vnstock không kèm lệnh vẫn mở giao diện tương tác (Dòng lệnh).

Những gì khác thế hệ 5

Thế hệ 5Thế hệ 6Bạn làm gì
Thư viện tự chọn nguồnKhông có nguồn mặc định: báo VNSTOCK_INPUT_SOURCEsource=, Market("<nguồn>"), hoặc sources.use(...)
Tham số hàm không dùng tớiBáo VNSTOCK_INPUT_PARAMBỏ tham số hàm không nhận
Tham số không có tương đương ở thế hệ 6 (lang="en", last_id…)Chỉ nhận giá trị mặc định của thế hệ 5Bỏ tham số; xem mục dưới
interval="DAY", chữ hoa thường tuỳ ýNhận các cách viết đã liệt kê, phân biệt hoa thường1D, D hoặc day
Có cột mà nguồn chính thức không gửiCột đó không có trong bảngBỏ cột khỏi mã; danh sách theo từng hàm kèm cảnh báo
session_stats() 68 cộtMột dòng như cũ, 40 cột dựng được từ dữ liệu theo ngàyBỏ các cột khối ngoại tách khớp lệnh, thoả thuận và khối lượng đặt chưa khớp
id của khớp lệnh là mã lệnh của nguồnSố thứ tự dòng trong lần lấyKhông dùng id để ghép giữa hai lần lấy
Ngày, tỷ lệ dạng chuỗi ở danh sách chứng quyềnKiểu ngày, kiểu sốSo sánh với chuỗi ngày vẫn chạy; mã cắt chuỗi đổi sang .dt
Hàm thế hệ 5 chưa có nguồn đọc được ở thế hệ 6CompatibilityWarning rồi UnsupportedError (VNSTOCK_ROUTE_UNSUPPORTED)Đổi nguồn theo thông báo, hoặc chờ bản sau
trades() không truyền limit lấy 1.000 lệnh gần nhất (100.000 với phái sinh)Không truyền limit thì lấy cả phiênTruyền limit= nếu chỉ cần một phần
Một số cột thế hệ 5 hứa không trống (exchange của bảng giá TCBS, icb_code của danh sách mã)Có thể trống khi nguồn không gửidropna() trước khi lọc theo cột đó

Tên gọi theo cách khác của thế hệ 5

Mọi tên của thế hệ 5 vẫn gọi được. Hàm có dữ liệu thì chạy; hàm chưa có dữ liệu báo UnsupportedError có mã, không báo AttributeError. Vài tên chạy qua hàm của nhóm, bảng trả về là bảng của hàm đó:

Thế hệ 5Chạy như
Market().quote(symbols), Market().price_board(symbols)Market().equity.quote(symbols)
Market().put_through(), put_through("FPT,VNM")Market().equity.block_trades(exchange="HOSE"); truyền mã thì giữ dòng của các mã đó
Market().future("VN30F1M")...Market().futures("VN30F1M")...
Macro().world...Macro().global_macro... (chưa có nguồn)

Tên đã báo ngừng ở thế hệ 5 (Market().pe(), Macro().cpi(), Reference().derivatives()…) báo lỗi có mã, kèm lời gọi thay thế mà thế hệ 5 đã ghi trong exc.action.

Tham số của thế hệ 5

Lời gọi viết cho thế hệ 5 được đọc theo cách của thế hệ 5. Không lời gọi nào ra kết quả khác mà không báo: hoặc chạy như thế hệ 5, hoặc báo VNSTOCK_INPUT_PARAM nói rõ vì sao.

  • Theo vị trí. Ở chỗ thế hệ 5 đặt tham số khác, giá trị đọc theo thứ tự thế hệ 5: trades(1000) là limit=1000, foreign_flow(30) là limit=30, Reference().fund.profile("DCDS") là symbol="DCDS", Reference().index.members("VN30") là rổ VN30. Giá trị là ngày (trades("2026-10-01")) vẫn là start.
  • Tên cũ. page_size của intraday() là limit; symbols_list là symbols.
  • Làm tại máy khi nguồn không làm được. Kết quả ghi ở df.attrs["filtered_locally"]:
    • lọc theo cột: event_type của events.calendar(), fund_type của fund.list(), icb_code của list_by_industry(), side của trades(), mã của put_through("FPT,VNM");
    • cắt khoảng thời gian: start, end của events.market();
    • giới hạn số dòng: limit của block_trades(), put_through(), insider_deal() (giữ các dòng mới nhất).
  • Chỉ nhận giá trị mặc định. Tham số không có tương đương ở thế hệ 6 (lang, mode, locale, last_id, last_time, page, window_size, bond_type, resolution của trade_history()) nhận giá trị mặc định của thế hệ 5 hoặc None. Giá trị khác, ví dụ lang="en", báo VNSTOCK_INPUT_PARAM kèm các tham số hàm nhận.

help(), gợi ý của IDE và vnstock doc <hàm> chỉ hiện tham số của thế hệ 6. Mã mới nên viết theo đó.

Cột không còn

Open API chính thức không gửi một số trường mà thế hệ 5 lấy từ nguồn khác, nên các cột đó không có trong bảng (SCH-A01). Mã đọc các cột này báo KeyError.

Danh sách theo hàm
Hàm thế hệ 5Cột không còn
Market().equity(...).session_stats(), trading_stats()28 cột tách khớp lệnh và thoả thuận của khối ngoại (fr_*_matched*, fr_*_deal*) và khối lượng đặt chưa khớp (total_*_unmatched_volume*)
Market().equity(...).summary()high_52w, low_52w, dividend, beta, bvps, market_cap, change_1m, change_1y, foreign_ownership_pct
Market().equity(...).block_trades(), put_through()change, change_percent, accumulated_volume, exchange, trading_date, reference_price, floor_price, ceiling_price
Market().index(...).quote(), summary()open_price, previous_close
Market().futures(...).summary()first_trading_date, underlying_symbol
Market().warrant(...).summary()intrinsic_value
Market().crypto(...).quote()Các cột bảng giá kiểu cổ phiếu: exchange, ceiling_price, floor_price, match_price, match_vol, total_volume, bậc giá 2 và 3, basis, open_interest, khối ngoại
Market().crypto(...).trades()match_type
Reference().company(...).info()short_name, listing_date, issued_share, founded_date, charter_capital, num_employees, exchange, address, phone, email, website, history, tax_id
Reference().company(...).events()Các cột song ngữ và mã sự kiện của nguồn cũ (event_name_vi, event_code, display_date1…); dùng các cột của events.calendar()
Reference().company(...).ownership()update_date
Reference().events.calendar()event_name, organ_name, public_date
Reference().events.market()event_type, duration
Reference().equity.list(), list_by_exchange(), list_by_industry(), industry.sectors()org_name, icb_code_lv2, com_type_code, icb_level
Reference().fund.list()organ_short_name, management_fee, inception_date, nav, nav_update_at
Reference().fund.profile()organ_short_name, description, inception_date, min_investment, trading_frequency, transfer_agent, benchmark, website
Reference().futures.info()Các cột giá trong phiên (reference_price, open_price…, open_interest, basis, khối ngoại), full_name, exchange, first_trading_date
Reference().warrant.info()Các cột giá trong phiên (reference_price, match_price…, foreign_room, khối ngoại), issue_date, underlying_price, break_even_point, break_even_point_diff, intrinsic_value
Reference().industry.list()en_icb_name
Reference().market.status()asset_type
Reference().search.symbol(), search.info()short_name, description, name_en, name_local, symbol_id

Giá trong phiên của chứng quyền và hợp đồng tương lai có ở Market().warrant(...).quote(), Market().futures(...).quote().

Báo cáo tài chính

Ba hàm balance_sheet(), income_statement(), cash_flow() giữ tên, giữ hai cách gọi và giữ mã chỉ tiêu của thế hệ 5. Phần lớn mã cũ chỉ cần thêm nguồn:

Python
from vnstock import Fundamental

# Thế hệ 5
Fundamental().equity("FPT").income_statement(period="year")

# Thế hệ 6: thêm nguồn, phần còn lại giữ nguyên
Fundamental().equity("FPT").income_statement(period="year", source="fhsc")
Fundamental().equity.balance_sheet("VCB", period="year", source="fhsc")

Đặt nguồn một lần cho cả nhóm thì không phải sửa từng lời gọi:

Python
import vnstock
vnstock.sources.use("fhsc", route="fundamental.equity.*")
vnstock.sources.save()

Phần giữ nguyên

  • Tham số period, lang, drop_empty, format và các cách viết cũ của chúng ("yearly", "Q"…). com_type vẫn nhận, tên mới là company_type, cùng các giá trị "bank", "tctd", "ctck", "dnpnt"…
  • period=None lấy cả năm và quý trong một bảng.
  • Mã chỉ tiêu (BS_TOTAL_ASSETS, IS_NET_REVENUE, CF_NET_CASH_FLOWS_FROM_OPERATING_ACTIVITIES…), cấp chỉ tiêu, thứ tự trình bày.
  • Ở hồ sơ v5: tên cột period, id, name, order, level, off_balance, unit, value; đơn vị "VNĐ"; dạng rộng có cột item.
  • Chi phí mang dấu âm.
  • Quy tắc bộ chỉ tiêu: khoá có Gói quyền sử dụng còn hiệu lực nhận bộ đầy đủ, các trường hợp khác nhận bộ rút gọn chỉ gồm chỉ tiêu cấp 1.

Những gì khác thế hệ 5

Thế hệ 5Thế hệ 6Bạn làm gì
Nguồn mặc định vci; có thêm kbs, masNguồn fhsc, không có nguồn mặc địnhsource="<nguồn>" hoặc sources.use(...)
Cắt còn 4 kỳ (Khách) hoặc 8 kỳ (Cộng đồng) gần nhấtKhông cắt số kỳ; với nhiều mã, kỳ năm có từ giữa thập niên 2000Lọc kỳ trên bảng nếu chỉ cần một đoạn
orient=Báo VNSTOCK_INPUT_PARAMDùng format="wide" hoặc format="time_series"
ratio() (bảng chỉ số do nguồn tính)UnsupportedError mã VNSTOCK_ROUTE_UNSUPPORTEDTính bằng vnstock_quant.fa.ratios() từ ba báo cáo, xem mục dưới
note(), financial_health(), filing()UnsupportedError mã VNSTOCK_ROUTE_UNSUPPORTEDChưa có ở thế hệ 6
Không có cột mã số chỉ tiêuThêm cột line_code (mã số trên mẫu biểu, như "270") ở cuối bảngMã chọn cột theo tên không bị ảnh hưởng
com_type sai thì có thể vẫn ra bảngcompany_type khác mẫu biểu nguồn trả thì báo VNSTOCK_INPUT_COMPANY_TYPEBỏ company_type để thư viện tự nhận
Không kiểm sốMỗi lời gọi kiểm đẳng thức của mẫu biểu, kết quả ở df.attrs["identities"]Xem Kiểm tra số liệu
Lợi ích cổ đông không kiểm soát luôn dương ở một số kỳGiữ dấu như báo cáo: âm khi phần của cổ đông không kiểm soát là lỗBỏ đoạn mã tự đổi dấu nếu có

Mã chỉ tiêu đổi

Một số mã chỉ tiêu chỉ có ở thế hệ 5, vì thế hệ 6 chỉ giữ các dòng có trên mẫu biểu mà nguồn gửi số:

  • Chỉ tiêu ngoài bảng của ngân hàng và công ty chứng khoán (bảo lãnh, cam kết ngoại tệ, thư tín dụng, tài sản tài chính nhận giữ hộ…): nguồn chưa gửi.
  • Lưu chuyển tiền của khách hàng ở báo cáo công ty chứng khoán (CF_CUSTOMER_*, CF_BROKER*, CF_CLEARING_*): nguồn chưa gửi.
  • Mã có hậu tố _LEGACY và các dòng tổng trung gian riêng của cách trình bày cũ: thế hệ 6 dùng mã theo mẫu biểu.
  • Hai dòng ánh xạ lại theo mẫu biểu, đã đối chiếu với báo cáo tài chính đã kiểm toán:
Báo cáoThế hệ 5Thế hệ 6
Lưu chuyển tiền công ty chứng khoán, dòng 11 và 19 (đánh giá lại tài sản tài chính FVTPL và phải trả chứng quyền)CF_FVTPL_LOSSES, CF_FVTPL_GAINS, cùng CF_FVTPL_LIABILITIES_LOSSES, CF_FVTPL_LIABILITIES_GAINSChỉ CF_FVTPL_LOSSES, CF_FVTPL_GAINS: mẫu biểu không có dòng nợ phải trả FVTPL
Lưu chuyển tiền ngân hàng, dòng 04 (chênh lệch thực thu, thực chi từ kinh doanh ngoại tệ, vàng bạc, chứng khoán)CF_NET_RECEIPTS_FROM_FOREIGN_EXCHANGE_AND_GOLD_TRADING, CF_NET_RECEIPTS_FROM_SECURITIES_TRADINGMột dòng CF_NET_DIFFERENCE_FROM_OPERATING_CASH_FLOWS, như mẫu biểu

Muốn biết mã nào có trong bảng, xem cột id của chính bảng trả về, hoặc gọi với drop_empty=False để thấy đủ cây chỉ tiêu của mẫu biểu.

Đối chiếu giữa hai thế hệ

Hai thế hệ đọc từ hai nguồn khác nhau. Mỗi nguồn có cách xếp một số khoản vào dòng chỉ tiêu riêng, và có lúc dùng số đã trình bày lại, có lúc dùng số gốc. Vì vậy cùng một kỳ, cùng một mã chỉ tiêu có thể ra số khác nhau. Khi đối chiếu:

  1. Ghép hai bảng theo period và id, chỉ so những ô hai bên đều có số.
  2. Bắt đầu từ các dòng tổng: tổng cộng tài sản, doanh thu thuần, lợi nhuận sau thuế, lưu chuyển tiền thuần.
  3. Chỗ nào lệch thì mở báo cáo gốc mà doanh nghiệp đã công bố để xem dòng đó thuộc mã số nào.

Thay ratio() bằng vnstock_quant

Thế hệ 5 đã báo ratio() sắp ngừng (tới 15/01/2027): mỗi nguồn tự tính bảng chỉ số theo công thức riêng mà bạn không kiểm được. Ở thế hệ 6, bạn tính các chỉ số đó trên máy bằng vnstock_quant.fa, từ ba báo cáo đã chuẩn hoá, với công thức tra được bằng fa.describe("<mã>"). Mã chỉ số giữ như cũ: 52 trong 55 mã của bảng ratio() có trong fa.catalog().

Python
# Thế hệ 5
Fundamental().equity("FPT").ratio(period="year")

# Thế hệ 6 + vnstock_quant
from vnstock import Fundamental
from vnstock_quant import fa

eq = Fundamental().equity("FPT")
frames = [
    getattr(eq, report)(period=period, source="fhsc", compat="v5")
    for report in ("income_statement", "balance_sheet", "cash_flow")
    for period in ("year", "quarter")
]
ds = fa.Dataset.from_frames({"FPT": frames})
fa.ratios(ds, period="year")                      # dạng long: symbol, period, id, value, unit, reason
fa.ratios(ds, period="year", format="wide")       # mỗi kỳ một cột, gần dạng rộng của ratio()

Cách cài, các điểm cần lưu ý (bộ chỉ tiêu đầy đủ, công ty chứng khoán, chỉ số định giá) xem ở Tính chỉ số tài chính.

Đối chiếu với thế hệ 5. Phép so dưới đây đặt ratio(period="year") của thế hệ 5 cạnh fa.ratios(period="year") tính từ báo cáo thế hệ 6 (nguồn fhsc, bộ chỉ tiêu đầy đủ) trên FPT, HPG (doanh nghiệp), VCB (ngân hàng), SSI (công ty chứng khoán), các năm 2023 tới 2025, ngày 06/11/2026. Ở 32 mã chỉ số mà hai bên cùng có số và cùng định nghĩa, 173 trên 177 ô lệch không quá 0,1%. Ví dụ năm 2025:

MãChỉ sốratio() thế hệ 5fa.ratios() trên thế hệ 6
FPTRT_PRT_ROE0,28290,2829
FPTRT_PRT_GROSS_MARGIN0,36920,3692
FPTRT_EFF_DSO60,5760,57
HPGRT_PRT_NET_MARGIN0,09940,0994
HPGRT_LQD_CR1,10061,1006
VCBRT_BANK_NIM0,02640,0264
VCBRT_BANK_CIR−0,3484−0,3484
VCBRT_BANK_LDR1,00061,0006
SSIRT_PRT_ROE0,14010,1401
SSIRT_PRT_GROSS_MARGIN0,60500,6050 (sau khi thêm IS_NET_REVENUE)

Những chỗ khác nhau, và việc bạn cần làm:

Chỉ sốKhác thế nàoBạn làm gì
RT_LEV_FINANCIAL_LEVERAGEThế hệ 5 ghi bằng nợ / vốn chủ (FPT: 1,01). vnstock_quant tính tài sản / vốn chủ (FPT: 2,01)Cần nợ / vốn chủ thì dùng RT_LEV_DE
RT_EFF_CASH_CYCLEThế hệ 5 dùng công thức khác (FPT 2025: 117,9 ngày). vnstock_quant tính DSO + DIO − DPO (44,1 ngày)Kiểm lại ngưỡng lọc nếu có
RT_VALUE_EQUITYThế hệ 5 ghi một tỷ lệ. vnstock_quant ghi vốn chủ sở hữu theo đồngĐổi cách đọc cột
RT_LEV_EQUITY_TO_ASSETS, RT_LEV_EQUITY_TO_LIABILITIES…Thế hệ 5 ghi 0 ở nhiều ô không có số; vnstock_quant tính ra số, hoặc để trống kèm reasonBỏ đoạn lọc value != 0
Biên lợi nhuận, DSO, hệ số thanh toán của ngân hàngThế hệ 5 có số. vnstock_quant trả NOT_APPLICABLEDùng các chỉ số RT_BANK_*
RT_BANK_NPL, RT_BANK_NPL_COVERAGE, RT_BANK_CAR, RT_BANK_CASACần thuyết minh, thế hệ 6 chưa có note()Chưa thay được
P/E, P/B, vốn hoá, EV/EBITDAHai bên lấy giá ở ngày khác nhau. Kỳ năm của vnstock_quant (hồ sơ vn) dùng giá phiên cuối, trước hoặc đúng ngày cuối quý 1 năm sau cộng 14 ngàyTruyền prices= có total_shares, đọc ngày định giá ở Chỉ số tài chính
RT_PRT_ROIC, RT_VALUE_BETA, RT_VALUE_DIVIDEND_YIELDKhông có trong vnstock_quant.faBeta: vnstock_quant.risk; còn lại tự tính

Ở kỳ quý, chênh lệch đến từ số liệu đầu vào, không đến từ công thức. Ví dụ lợi nhuận của cổ đông công ty mẹ SSI quý 4/2024 là 296,9 tỷ đồng ở nguồn thế hệ 5 và 427,7 tỷ đồng ở fhsc, trong khi lợi nhuận sau thuế hai bên cùng là 438,4 tỷ đồng. Lệch như vậy làm ROE theo 12 tháng gần nhất của SSI chênh tới 11% ở vài quý. Khi gặp, hãy mở báo cáo gốc để đối chiếu.

Cảnh báo thay đổi

Khi một bảng khác thế hệ 5 theo cách làm hỏng mã cũ hoặc đổi nghĩa con số, thư viện cảnh báo một lần bằng SchemaChangeWarning. Cảnh báo ghi mã thay đổi (SCH-A03…), mức độ và hàm. Mọi bảng còn ghi:

Python
df.attrs["profile"]          # 'v5' hoặc 'v6'
df.attrs["schema_changes"]   # mã các thay đổi so với thế hệ 5 mà bảng này mang

Trợ lý AI và mã kiểm tra đọc hai trường này để biết bảng nào cần đối chiếu.

Chuyển sang chuẩn v6

Hồ sơ v6 đặt một tên, một đơn vị cho mỗi đại lượng trên mọi bảng (Bộ cột và chuẩn hoá):

Python
import vnstock
vnstock.compat.use("v6")                              # mọi kết quả trong tiến trình
Market("<nguồn>").equity("FPT").quote(compat="v6")       # hoặc một lời gọi
# hoặc biến môi trường VNSTOCK_COMPAT=v6 trước khi import
Hồ sơ v5Hồ sơ v6
open_price, close_price, bid_vol_1open, close, bid_volume_1
buy_vol, sell_val (khối ngoại)foreign_buy_volume, foreign_sell_value
Bảng giá theo đồng (66400)Nghìn đồng (66.4)
percent_price_change = -0.0302price_change_percent = -3.02
match_type = Buy, ATCside = buy, session = atc
int64Int64
foreign_flow(), proprietary_flow(), trade_history() mới nhất trướcTăng dần: df.iloc[0] đổi thành df.iloc[-1], df.head(n) đổi thành df.tail(n)
Mốc ngày của các hàm trên 00:00+07:0007:00+07:00, như nến: nối theo time chạy thẳng; so giờ thì đổi sang so ngày (df.time.dt.date)

Hai dòng cuối áp dụng từ bản sau 6.0.0rc3.

Danh sách kiểm

  • Mọi lời gọi có nguồn, hoặc đã đặt sources.use(...) và lưu bằng sources.save().
  • Tham số truyền theo tên ở các hàm trong mục Tham số của thế hệ 5.
  • Không còn resolution, count.
  • Đã xem các SchemaChangeWarning và bỏ những cột không còn.
  • Không dùng id khớp lệnh để ghép giữa hai lần lấy.
  • Đã đối chiếu vài bảng giữa hai thế hệ.
  • Bỏ mọi đoạn tự hoán đổi total_buy_trade, total_buy_trade_volume và cặp bán của trade_history() (nguồn ssi).
  • Báo cáo tài chính: có nguồn fhsc, không còn orient=, đã xem các mã chỉ tiêu đổi.
  • ratio() đã đổi sang vnstock_quant.fa.ratios(), đã xem các chỉ số khác định nghĩa ở mục trên.