Vnstock Logo

Phương pháp chuẩn hoá dữ liệu

Mở rộng

Mục lục

Trang này mô tả thư viện làm gì với phản hồi của nguồn trước khi trả cho bạn một DataFrame.

Nguồn trả dữ liệu theo định dạng riêng, dựng cho trang web của chính họ: tên trường viết tắt, đơn vị mỗi nơi một kiểu, mốc thời gian dạng số, một bảng chia thành nhiều trang. Nếu thư viện chỉ chuyển tiếp phản hồi đó, bạn sẽ nhận một khối JSON thô. Thư viện đọc phản hồi rồi tái tạo nó thành một bảng có cột, kiểu và đơn vị cố định để lập trình. Việc này không chỉ là đổi tên cột: có bước phải suy ra ý nghĩa của trường, đối chiếu giữa các dòng, và có bước tự tính thêm.

Kết quả có thể sai lệch

Vì có suy diễn và đối chiếu, bảng thư viện trả về không phải lúc nào cũng khớp hoàn toàn với dữ liệu gốc. Khi phát hiện sai lệch, vnstock xác thực rồi sửa trong bản cập nhật thư viện gần nhất. Với số liệu dùng cho quyết định quan trọng, hãy đối chiếu với tài liệu do doanh nghiệp hoặc sở giao dịch công bố.

Tóm tắt các bước

BướcThư viện làm gìChỗ có thể sai lệch
1. Gửi truy vấnTruy vấn đi từ máy bạn tới nguồn, sau khi kiểm cấp quyềnNguồn đổi định dạng hoặc gián đoạn
2. Đọc phản hồiGiải mã phản hồi, đọc nối các trangChạm trần số truy vấn một lần gọi thì dừng sớm và ghi rõ trong df.attrs
3. Đặt tênĐổi tên trường của nguồn sang tên cột hoặc mã chỉ tiêu chungMột trường được hiểu sai nghĩa
4. Đơn vị và kiểuQuy về nghìn đồng, đồng, tỷ lệ; ép kiểu số, ngày, chuỗiQuy đổi đơn vị
5. Thời gianGắn múi giờ, đổi mốc dạng số sang ngày giờMốc của nến khung lớn
6. Tính thêmGộp nến khung lớn, cộng các thành phần, đọc số từ câu chữPhép tính hoặc cách đọc
7. Kiểm bảngĐối chiếu với bộ cột, kiểu và giá trị cố định của từng hàm—
8. Cắt theo cấpCắt số dòng, số kỳ theo cấp tài khoản—
9. Ghi nguồn gốcGhi nguồn, thời điểm, cách xử lý vào df.attrs—

Bước 1 tới 7 chạy trong lõi xử lý, giống nhau cho mọi lối gọi. Lớp Python chỉ đổi bảng sang pandas.DataFrame.

Bốn kiểu xử lý: algorithm_role

Mỗi kết quả ghi trong df.attrs["algorithm_role"] thư viện đã làm gì để có nó. Giá trị chọn theo việc lời gọi thực sự làm, không theo tên hàm.

algorithm_roleKhi nàoNghĩa
retrieve_normalizeCó gửi truy vấn, không có cột tự tínhĐọc phản hồi của nguồn rồi tái tạo thành bảng chuẩn
retrieve_deriveCó gửi truy vấn và có cột tự tínhNhư trên, cộng thêm các cột nguồn không trả sẵn
bundled_referenceKhông gửi truy vấn nàoBảng lấy từ dữ liệu có sẵn trong thư viện (danh mục chỉ số, lịch nghỉ giao dịch), hoặc tính từ dữ liệu đó và đồng hồ máy bạn
normalize_suppliedBạn tự đưa dữ liệu vào qua ConnectorĐọc dữ liệu bạn lấy bằng tài khoản của mình, tái tạo thành bảng chuẩn; thư viện không gửi truy vấn

Khi thư viện tự tính một cột, tên cột đó nằm trong df.attrs["derived_fields"]. Phần mô tả đầy đủ nằm trong df.attrs["algorithm_participation"].

Python
from vnstock import Market, provenance

df = Market().equity("VIC").ohlcv(start="2026-01-01", end="2026-03-01", interval="1W")
print(df.attrs["algorithm_role"])     # retrieve_derive
print(df.attrs["derived_fields"])     # ['time', 'open', 'high', 'low', 'close', 'volume', 'value']
print(provenance.summary(df))         # mô tả đủ các trường, tiếng Việt

Cùng lệnh đó ở khung 1D cho retrieve_normalize và không có derived_fields: nến ngày lấy thẳng từ nguồn.

Giá và nến

Đơn vị. Giá cổ phiếu, chứng chỉ quỹ, chứng quyền tính bằng nghìn đồng (63.0 là 63.000 đồng). Chỉ số và hợp đồng tương lai tính bằng điểm. Khối lượng tính bằng cổ phiếu hoặc hợp đồng.

Thời gian. Thị trường Việt Nam theo giờ Asia/Ho_Chi_Minh. Nến ngày mang mốc 07:00 giờ Việt Nam, tức 00:00 UTC của ngày giao dịch, như nguồn gửi. Tài sản quốc tế (ngoại hối, hàng hoá, chỉ số thế giới, tiền mã hoá) theo UTC.

Gộp nến. Khi nguồn không phục vụ một khung, thư viện dựng nến khung đó từ nến khung nhỏ hơn:

CộtCách lấy
openGiá mở của nến nhỏ đầu tiên
closeGiá đóng của nến nhỏ cuối cùng
high, lowCao nhất, thấp nhất trong các nến nhỏ
volume, valueTổng các nến nhỏ
timeNến phút: đầu khoảng (nến 5 phút 09:15–09:19 mang mốc 09:15). Nến tuần, tháng trong nước: phiên cuối của tuần hoặc tháng. Nến tuần, tháng quốc tế: đầu tuần (Chủ nhật) hoặc ngày đầu tháng, giờ UTC
NguồnKhung tự gộpGộp từ
vci5m, 15m, 30m1m
vci1W, 1M1D
kbs5m, 15m, 30m1m
dukascopy1H, 4H1m
dukascopy1W, 1M1D

length và limit đếm nến sau khi gộp. Nếu số nến nhỏ cần đọc vượt trần truy vấn một lần gọi, kết quả dừng ở phần mới nhất và df.attrs có request_cap_rows; thư viện cũng in một cảnh báo.

Khớp lệnh

Chiều lệnh. Cột match_type ghi Buy, Sell theo nhãn nguồn gửi. Nguồn kbs ghi chữ thường buy, sell để giống bản 4.x. Lệnh khớp trong phiên định kỳ không có bên chủ động; nếu nguồn không ghi chiều, thư viện gắn ATO hoặc ATC theo lịch phiên của sở (cổ phiếu: 09:00–09:15 và 14:30–14:45; hợp đồng tương lai: 08:45–09:00 và 14:30–14:45). Đây là bước suy diễn theo giờ khớp.

Mã lệnh. Nguồn nào không gửi mã lệnh thì cột id ghép từ ngày giao dịch và khối lượng luỹ kế của phiên (ví dụ 20261019_7276900). Khối lượng luỹ kế chỉ tăng nên mỗi lệnh có một mã riêng.

Danh sách chưa đủ phiên. Nguồn thường trả N lệnh mới nhất. Khi danh sách không phủ từ đầu phiên, df.attrs có session_missing và session_covered, kèm một cảnh báo nêu limit nên thử.

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

Mỗi nguồn đặt tên dòng báo cáo theo cách riêng. Thư viện quy tất cả về một bộ mã chỉ tiêu chung, nên cùng một dòng có cùng mã dù lấy từ vci, kbs hay mas.

Tiền tố mãBáo cáo
IS_Kết quả kinh doanh
BS_Cân đối kế toán
CF_Lưu chuyển tiền tệ
RT_Chỉ số tài chính

Mẫu báo cáo theo loại hình. Doanh nghiệp thường, ngân hàng, công ty chứng khoán và công ty bảo hiểm dùng bốn mẫu khác nhau. Mặc định thư viện tự nhận loại hình, từ danh mục chỉ tiêu nguồn công bố cho mã đó hoặc từ tên các dòng. Bạn chỉ định được bằng com_type= (regular, bank, securities, insurance).

Từ dòng của nguồn tới mã chung. Một bảng ánh xạ cho biết mỗi tên dòng của nguồn thuộc mã nào. Các quy tắc sau áp dụng khi dựng bảng:

Quy tắcVí dụ
Mỗi tên dòng của nguồn thuộc đúng một mãnet_cash_flows_during_the_period → CF_NET_CASH_FLOWS_DURING_THE_PERIOD
Một mã nhận được nhiều tên dòng, vì mỗi mẫu báo cáo đặt tên khác nhau. Cùng một kỳ mà có hai giá trị khác nhau thì cộng lại; hai giá trị bằng nhau thì lấy một"Lợi nhuận trước thuế" của mẫu doanh nghiệp và của mẫu ngân hàng
Trên báo cáo lưu chuyển tiền tệ, một tên dòng lặp lại trong cùng bảng thì lấy dòng đầu tiên có sốPhần tiền của khách hàng ở công ty chứng khoán; khối dòng tổng thứ hai ở công ty bảo hiểm
Chi phí, khấu hao luỹ kế và các khoản dự phòng luôn mang dấu âmGiá vốn hàng bán, chi phí lãi vay
Lợi ích cổ đông không kiểm soát trên kết quả kinh doanh mang dấu dương—
Một vài tỷ lệ của ngân hàng nguồn gửi dạng phần trăm được nhân 0,01 thành tỷ lệBiên lãi thuần 3.2 → 0.032
Công ty bảo hiểm: "phải trả dài hạn khác" đọc là dự phòng nghiệp vụ bảo hiểm—
Ngân hàng: kỳ có khoản đầu tư liên doanh bằng đúng khoản đầu tư liên kết thì bỏ kỳ đó ở dòng liên doanh, vì đó là một khoản ghi hai lần—

Số liệu ghi bằng đồng (unit = "VNĐ"). Báo cáo tài chính vẫn ghi algorithm_role là retrieve_normalize: các con số là của nguồn, thư viện sắp lại theo mã chung và áp các quy tắc trên. Dòng nào chịu quy tắc cộng, đổi dấu hay nhân hệ số là do bảng ánh xạ quyết định.

Đối chiếu với báo cáo đã công bố. Bảng ánh xạ được kiểm bằng cách đặt số thư viện trả về cạnh báo cáo tài chính doanh nghiệp công bố, tải qua Fundamental().equity(symbol).filing(). Ví dụ: báo cáo lưu chuyển tiền tệ quý 1/2026 của FPT (doanh nghiệp), VCB (ngân hàng), HCM (chứng khoán) và BVH (bảo hiểm) khớp tới 1.000 đồng ở cả ba nguồn vci, kbs, mas. Số do nguồn trình bày có thể đã gộp hoặc làm tròn khác bản công bố; thư viện giữ số của nguồn, không tự sửa.

Python
from vnstock import Fundamental

cf = Fundamental().equity("FPT").cash_flow(period="quarter")
q1 = cf[cf["period"] == "2026-Q1"].set_index("id")["value"]
print(q1["CF_CASH_AND_CASH_EQUIVALENTS_AT_END_OF_PERIOD"])

files = Fundamental().equity("FPT").filing()   # danh sách tài liệu đã công bố để đối chiếu

Sự kiện đọc từ tin công bố

Company(source="cafef", symbol=...).events() (trong vnstock.api) lấy tin công bố thông tin của doanh nghiệp từ CafeF. Nguồn chỉ có tiêu đề tin, nên các cột hành động doanh nghiệp được đọc ra từ câu chữ của tiêu đề:

  • loại sự kiện (event_code, issue_type);
  • ngày đăng ký cuối cùng, ngày giao dịch không hưởng quyền, với năm suy từ ngày đăng tin;
  • tỷ lệ thực hiện và giá phát hành.

Cổ tức tiền mặt ghi theo phần trăm được quy ra đồng trên mệnh giá 10.000 đồng. Một tiêu đề nêu hai hành động thì thành hai dòng. Các cột này nằm trong derived_fields.

Dữ liệu có sẵn và dữ liệu bạn tự đưa vào

Danh mục chỉ số, lịch nghỉ giao dịch và trạng thái phiên (Reference().market.status()) dùng bảng đóng gói trong thư viện, không gửi truy vấn. Bảng này chỉ cập nhật tới bản thư viện bạn đang cài, nên có thể thiếu thay đổi xảy ra sau đó.

Connector đọc dữ liệu bạn tự lấy từ nguồn bằng tài khoản của mình. Thư viện chỉ tái tạo dữ liệu đó thành bảng chuẩn; nếu có cột tự tính, ví dụ khối lượng ròng bằng mua trừ bán, cột đó cũng nằm trong derived_fields.

Giới hạn

  • Suy diễn có thể sai. Ý nghĩa một trường, loại hình doanh nghiệp, nhãn phiên định kỳ, sự kiện đọc từ tiêu đề đều là bước suy luận.
  • Nguồn đổi định dạng. Khi nguồn đổi tên trường hoặc cấu trúc, bảng có thể thiếu dòng hoặc báo lỗi cho tới bản cập nhật kế tiếp.
  • Số của nguồn. Thư viện không sửa số nguồn gửi. Số đó có thể gộp, làm tròn hoặc cập nhật muộn so với bản công bố.
  • Dữ liệu đóng gói chỉ mới tới bản thư viện đang cài.

Báo sai lệch

Khi thấy số không khớp tài liệu công bố, báo tại GitHub Issues kèm:

  1. Lệnh đã gọi, gồm source= và kỳ.
  2. Kết quả provenance.summary(df).
  3. Dòng và con số đúng, kèm tài liệu công bố (tên tài liệu, trang).

vnstock xác thực sai lệch rồi sửa trong bản cập nhật thư viện gần nhất.

Xem thêm: Kiến trúc thư viện cho df.attrs và trích dẫn nguồn gốc, Nguồn dữ liệu cho nguồn mặc định của từng hàm.