Nâng cấp mảng Quỹ mở từ vnstock 4.x
Mục lục
Nội dung trang này giữ nguyên từ bản v5.0.0, chưa viết riêng cho free: ví dụ chạy được nếu tên hàm không đổi. Bản gốc: /docs/vnstock/chuyen-doi/nang-cap-quy-mo-fund.
Trang này dành riêng cho việc chuyển đổi mã nguồn xử lý dữ liệu quỹ mở (Fund) viết cho vnstock 4.x (hoặc vnstock_data 3.x) sang vnstock thế hệ 5.
Bước sang thế hệ 5, mảng dữ liệu quỹ mở có sự thay đổi căn bản về nguồn dữ liệu, cơ chế định danh, quy mô dữ liệu, phương thức truy xuất và cấp quyền truy cập.
1. Bối cảnh tuân thủ và chính sách cấp quyền
- Loại bỏ hoàn toàn nguồn Fmarket: Thư viện đã chủ động gỡ bỏ nguồn Fmarket nhằm tuân thủ "Điều khoản sử dụng" được công bố trên website của đơn vị này (địa chỉ tham chiếu:
fmarket.vn/legal?tab=terms). Người dùng đang sử dụng mã nguồn ở các phiên bản cũ hoặc kịch bản còn kết nối tới nguồn này cần chủ động rà soát và gỡ bỏ để đảm bảo tuân thủ đầy đủ quy định. Nếu gọisource="fmarket"trên thế hệ 5, thư viện trả về lỗiUnsupportedError(mãVNSTOCK_FEATURE_REMOVED) kèm hướng dẫn đổi sangsource="cafef"hoặcsource="digiinvest". - Chính sách cấp quyền từ Bronze trở lên: Bản 4.x từng mở
Fund()tự do cho mọi người dùng. Ở thế hệ 5, dữ liệu quỹ mở được chuyển sang hai nguồn công khai là CafeF và DigiInvest, và chỉ mở cho tài khoản từ cấp tài trợ Bronze trở lên. Việc giới hạn này nhằm bảo vệ hạ tầng máy chủ công khai khỏi nguy cơ quá tải khi lượng người dùng bản Cộng đồng tăng cao. Tài khoản cấp Khách hoặc Cộng đồng khi gọi sẽ nhận lỗiEntitlementError(mãVNSTOCK_TIER_SOURCEhoặcVNSTOCK_TIER_ROUTE) ngay trên máy khách mà không gửi truy vấn ra ngoài. - Thời hạn tương thích chuyển tiếp: Nhằm giúp mã nguồn cũ không bị gãy đột ngột, lớp
Fund()tại gốc gói và các phương thức cũ trênReference().fund/Market().fundvẫn được duy trì hoạt động đến hết ngày 06/04/2027 (kèm cảnh báoFutureWarning). Sau mốc thời gian này, các tên cũ sẽ chính thức ngừng hoạt động.
2. So sánh quy mô và đặc tính nguồn dữ liệu
Sự thay đổi nguồn dẫn tới những khác biệt đáng chú ý về số lượng quỹ, cách định danh và độ sâu dữ liệu:
| Tiêu chí | Fmarket (bản 4.x cũ) | CafeF (thế hệ 5, mặc định) | DigiInvest (thế hệ 5, bổ sung) |
|---|---|---|---|
| Quy mô danh mục | ~68–69 quỹ | 43 quỹ (24 cổ phiếu, 15 trái phiếu, 4 cân bằng) | 33 quỹ |
| Định danh quỹ | Mã số nguyên fundId (ví dụ 23) | Mã ticker chuỗi (ví dụ "DCDS") | Mã ticker chuỗi (ví dụ "DCDS") |
| Quy ước mã ticker | Viết liền (ví dụ SSISCA) | Một số mã có dấu gạch ngang (ví dụ SSI-SCA) | Viết liền hoặc theo đăng ký quỹ |
| Độ sâu lịch sử NAV | Ngắn hơn hoặc ngắt quãng | Rất sâu (DCDS từ 11/03/2005, hơn 2.800 điểm) | Sâu nhất (DCDS từ 01/06/2004, hơn 3.300 điểm) |
| Độ chính xác NAV | Làm tròn tới đồng | Chi tiết tới 0,01 đồng | Làm tròn tới đồng |
| Danh mục nắm giữ | Top 10 + trái phiếu, có ngày cụ thể | Top 10 (báo cáo tháng, lấy ngày cuối tháng) | Không có qua API công khai |
| Phân bổ tài sản & ngành | Có, nhãn tiếng Việt | Có, chuẩn hoá mã tiếng Anh | Không có qua API công khai |
| Cổ tức tiền mặt | Không hỗ trợ | Không có | Có (Market().fund(s).dividends()) |
| Hồ sơ & biểu phí | Không có hàm chuẩn | Có (profile(), fee_structure(), reports()) | Có tên quỹ, phí quản lý trong danh mục |
- Số lượng quỹ ít hơn: Một số quỹ nhỏ trước đây có mặt trên Fmarket nhưng không có trên CafeF hoặc DigiInvest sẽ không còn truy xuất được. Bạn cần kiểm tra danh sách quỹ hiện hành bằng
Reference().fund.list(). - Tuyệt đối không dùng mã số
fundId: CafeF và DigiInvest không sử dụng mã số nội bộ của Fmarket. Nếu truyền số nguyên (nhưfundId=23), thư viện sẽ báo lỗiInputErrormãVNSTOCK_INPUT_SYMBOL. - Cách viết mã quỹ: Danh mục CafeF định danh quỹ SSI là
SSI-SCA(có gạch ngang), thay vìSSISCAnhư bản cũ. Nếu gọiMarket().fund("SSISCA")bị lỗi không tìm thấy, hãy kiểm tra mã chuẩn trong bảng danh mục.
3. Bảng đối chiếu phương thức 4.x vs 5.x
Bảng dưới đây tổng hợp chi tiết việc chuyển đổi từ các phương thức cũ sang giao diện hợp nhất thế hệ 5:
| Tính năng | Phương thức 4.x | Tên mới chuẩn (5.x) | Tên cũ chuyển tiếp (hạn 06/04/2027) | Ghi chú chuyển đổi |
|---|---|---|---|---|
| Danh mục quỹ | Fund().listing(fund_type="") | Reference().fund.list(fund_type, symbol=..., source=...) | Fund().listing(fund_type) | Tên cũ trả đủ 21 cột (10 cột đặc thù Fmarket để trống). Tên mới trả 8 cột chuẩn |
| Lọc tìm mã quỹ | Fund().filter(symbol="") | Reference().fund.list(symbol=...) | Fund().filter(symbol) | Bản 4.x trả cột id là số nguyên; thế hệ 5 trả id là mã ticker chuỗi để tương thích |
| Lịch sử NAV | Fund().nav_report(fundId) | Market().fund(symbol).history(source=...) | Fund().nav_report(symbol) hoặc Market().fund(s).nav() | Bản 4.x nhận fundId số (bỏ trống tự lấy 23); thế hệ 5 bắt buộc truyền mã ticker chuỗi |
| Top khoản nắm giữ | Fund().top_holding(fundId) | Market().fund(symbol).holdings() | Fund().top_holding(symbol) hoặc Market().fund(s).top_holding() | Tên cũ trả cột stock_code, type_asset, update_at, fundId (cột fundId để trống) |
| Phân bổ ngành | Fund().industry_holding(fundId) | Market().fund(symbol).industry_allocation() | Fund().industry_holding(symbol) hoặc Market().fund(s).industry_holding() | Giữ nguyên ý nghĩa tỷ trọng ngành |
| Phân bổ tài sản | Fund().asset_holding(fundId) | Market().fund(symbol).asset_allocation() | Fund().asset_holding(symbol) hoặc Market().fund(s).asset_holding() | Bản 4.x trả tiếng Việt; thế hệ 5 trả mã chuẩn (equity, bond, cash_and_equivalents, others) |
| Chi tiết quỹ | Fund().details (thuộc tính) | Reference().fund(symbol).profile() | Bị LOẠI BỎ hoàn toàn | Gọi thuộc tính cũ nhận AttributeError |
| Danh sách quỹ | Fund().fund_list (thuộc tính) | Reference().fund.list() | Bị LOẠI BỎ hoàn toàn | Gọi thuộc tính cũ nhận AttributeError |
| Mặc định quỹ 23 | Gọi hàm không truyền mã | Bị LOẠI BỎ hoàn toàn | Bị LOẠI BỎ hoàn toàn | Bắt buộc truyền rõ mã quỹ, ví dụ Market().fund("DCDS") |
Các tính năng mới chỉ có ở thế hệ 5
Bên cạnh việc thay thế các hàm cũ, thế hệ 5 bổ sung nhiều năng lực chuyên sâu mà bản 4.x trước đây chưa từng hỗ trợ:
Market().fund(symbol).performance(): Lợi nhuận qua các giai đoạn (ytd,3y,5y), kèm cờannualizedxác định lợi nhuận kép bình quân năm.Market().fund(symbol).dividends(): Lịch sử chi trả cổ tức bằng tiền mặt trên mỗi chứng chỉ quỹ (nguồn DigiInvest).Reference().fund(symbol).profile(): Hồ sơ chi tiết (tổng tài sản, mức đầu tư tối thiểu, ngày giao dịch, đại lý phân phối, chỉ số tham chiếu, website).Reference().fund(symbol).fee_structure(): Biểu phí chi tiết chia theo từng bậc (phí mua, phí bán lại theo thời gian nắm giữ, phí chuyển đổi).Reference().fund(symbol).reports(): Danh sách liên kết tải bản cáo bạch, điều lệ quỹ và các báo cáo định kỳ chính thức.
4. Đối chiếu Schema và thay đổi cột dữ liệu
Nếu mã nguồn của bạn đang xử lý kết quả trả về bằng cách truy cập tên cột cụ thể, hãy lưu ý bảng chuyển đổi cấu trúc cột sau:
| Nghiệp vụ | Cột ở bản 4.x (Fmarket) | Cột ở thế hệ 5 (Chuẩn hoá) | Lưu ý chuyển đổi |
|---|---|---|---|
| Danh mục quỹ | short_name, name, fund_type, fund_owner_name, management_fee, inception_date, nav, nav_update_at + 10 cột nav_change_*, fund_id_fmarket, fund_code, vsd_fee_id | ticker, organ_name, organ_short_name, fund_type, management_fee, inception_date, nav, nav_update_at | Cột short_name đổi thành ticker. Cột fund_owner_name đổi thành organ_short_name. 10 cột đặc thù của Fmarket bị loại bỏ ở tên mới (để trống ở tên cũ) |
| Lịch sử NAV | date (chuỗi "YYYY-MM-DD"), nav_per_unit, short_name | time (datetime64[ns, Asia/Ho_Chi_Minh]), nav | Cột date đổi thành time và đã có sẵn kiểu thời gian có múi giờ, không cần pd.to_datetime(). Cột nav_per_unit đổi thành nav |
| Nắm giữ lớn nhất | stock_code, industry, net_asset_percent, type_asset, update_at, fundId | update_at, ticker, industry, net_asset_percent, asset_type | Cột stock_code đổi thành ticker. Cột type_asset (STOCK/BOND) đổi thành asset_type (equity/bond). Cột update_at đổi sang datetime64. Cột fundId bị loại bỏ |
| Phân bổ tài sản | asset_percent, asset_type, short_name (giá trị: "Cổ phiếu", "Trái phiếu"…) | asset_type, asset_percent (giá trị: equity, bond, cash_and_equivalents, others) | Giá trị phân loại chuyển từ chuỗi tiếng Việt sang mã chuẩn tiếng Anh |
| Phân bổ ngành | industry, net_asset_percent, short_name | industry, net_asset_percent | Bỏ cột phụ short_name ở tên mới |
5. Hướng dẫn chuyển đổi mã nguồn thực tế
Dưới đây là 4 tình huống nâng cấp mã nguồn phổ biến nhất:
Tình huống 1: Lấy danh mục quỹ và tra cứu theo loại quỹ
# ==========================================
# CÁCH CŨ (vnstock 4.x)
# ==========================================
from vnstock import Fund
fund = Fund()
# Lấy danh sách quỹ cổ phiếu (21 cột Fmarket)
df_funds = fund.listing(fund_type="STOCK")
# Tìm mã số nội bộ của quỹ
dcds_id = fund.filter("DCDS")["id"].iloc[0] # trả về số nguyên, ví dụ 23
# ==========================================
# CÁCH MỚI (vnstock thế hệ 5)
# ==========================================
from vnstock import Reference
ref = Reference()
# Lấy danh sách quỹ cổ phiếu chuẩn hoá (8 cột)
df_funds = ref.fund.list("equity_fund") # nhận cả "STOCK" để tương thích
# Tra cứu quỹ trực tiếp theo mã hoặc từ khoá
dcds_info = ref.fund.list(symbol="DCDS")
ticker = dcds_info["ticker"].iloc[0] # mã ticker dạng chuỗi "DCDS"Tình huống 2: Truy xuất lịch sử NAV và xử lý chuỗi thời gian
# ==========================================
# CÁCH CŨ (vnstock 4.x)
# ==========================================
from vnstock import Fund
import pandas as pd
fund = Fund()
# Bắt buộc truyền fundId dạng số; ngày là chuỗi text
df_nav = fund.nav_report(fundId=23)
df_nav["date"] = pd.to_datetime(df_nav["date"])
latest_nav = df_nav["nav_per_unit"].iloc[-1]
# ==========================================
# CÁCH MỚI (vnstock thế hệ 5)
# ==========================================
from vnstock import Market
mkt = Market()
# Truyền mã ticker chuỗi; cột time đã có sẵn kiểu datetime có múi giờ
df_nav = mkt.fund("DCDS").history()
latest_nav = df_nav["nav"].iloc[-1]
# Lọc dữ liệu theo thời gian chuẩn xác
recent_nav = df_nav[df_nav["time"] >= "2026-01-01"]Tình huống 3: Phân tích danh mục nắm giữ và cơ cấu phân bổ
# ==========================================
# CÁCH CŨ (vnstock 4.x)
# ==========================================
from vnstock import Fund
fund = Fund()
# Gọi qua fundId số nguyên
top10 = fund.top_holding(fundId=23)
# Đọc cột stock_code và type_asset ("STOCK"/"BOND")
top_stocks = top10[top10["type_asset"] == "STOCK"]
# Phân bổ tài sản bằng nhãn tiếng Việt
assets = fund.asset_holding(fundId=23)
equity_pct = assets[assets["asset_type"] == "Cổ phiếu"]["asset_percent"].iloc[0]
# ==========================================
# CÁCH MỚI (vnstock thế hệ 5)
# ==========================================
from vnstock import Market
dcds = Market().fund("DCDS")
# Đọc danh mục nắm giữ với cột ticker và asset_type chuẩn ("equity"/"bond")
top10 = dcds.holdings()
top_stocks = top10[top10["asset_type"] == "equity"]
# Phân bổ tài sản với mã chuẩn tiếng Anh
assets = dcds.asset_allocation()
equity_pct = assets[assets["asset_type"] == "equity"]["asset_percent"].iloc[0]Tình huống 4: Khai thác các tính năng mới chuyên sâu
from vnstock import Market, Reference
symbol = "DCDS"
# 1. Xem hiệu suất lợi nhuận qua các giai đoạn (YTD, 3 năm, 5 năm)
perf = Market().fund(symbol).performance()
print(perf[["period", "period_label", "return_percent", "annualized"]])
# 2. Xem lịch sử chia cổ tức tiền mặt (đối với quỹ có chi trả, nguồn DigiInvest)
divs = Market().fund("DCDE").dividends()
print(divs.head())
# 3. Tra cứu biểu phí mua, bán lại theo bậc thời gian nắm giữ
fees = Reference().fund(symbol).fee_structure()
print(fees[["fee_type", "range", "fee", "unit"]])
# 4. Lấy link tải tài liệu, bản cáo bạch chính thức của quỹ
docs = Reference().fund(symbol).reports()
print(docs[["title", "period", "url"]])6. Xử lý các sự cố và lỗi thường gặp khi nâng cấp
| Ngoại lệ | Mã lỗi (code) | Nguyên nhân | Cách xử lý |
|---|---|---|---|
EntitlementError | VNSTOCK_TIER_SOURCE hoặc VNSTOCK_TIER_ROUTE | Đang chạy ở cấp Khách (chưa đăng nhập) hoặc cấp Cộng đồng | Nhóm hàm quỹ mở yêu cầu khoá API từ cấp tài trợ Bronze trở lên. Đăng nhập bằng vnstock login <API_KEY> |
InputError | VNSTOCK_INPUT_SYMBOL | Truyền fundId dạng số nguyên (như 23) hoặc không truyền mã quỹ | Thay số nguyên bằng mã ticker chuỗi, ví dụ symbol="DCDS" |
InputError | VNSTOCK_PROVIDER_NOT_FOUND | Quỹ không có trên nguồn hoặc viết sai định dạng mã | Kiểm tra lại danh mục bằng Reference().fund.list(). Lưu ý một số mã có gạch nối như SSI-SCA |
UnsupportedError | VNSTOCK_FEATURE_REMOVED | Gọi tham số source="fmarket" | Bỏ tham số source để dùng mặc định "cafef", hoặc chuyển sang source="digiinvest" |
AttributeError | N/A | Truy cập thuộc tính cũ Fund().details hoặc Fund().fund_list | Đổi sang dùng Reference().fund(symbol).profile() hoặc Reference().fund.list() |
Trong trường hợp bạn đang vận hành hệ thống lớn và cần thời gian để tái cấu trúc mã nguồn, bạn có thể tạm thời lọc bỏ cảnh báo FutureWarning bằng cấu hình sau:
import warnings
# Chỉ tắt cảnh báo của các tên quỹ cũ chuyển tiếp (hạn 06/04/2027)
warnings.filterwarnings("ignore", category=FutureWarning, message=".*06/04/2027")