Vnstock Logo

Cấu hình và lưu trữ

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_pipeline v6.0.0rc1, 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à v3.1.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ị.

Mọi thứ pipeline ghi ra đều nằm dưới một thư mục gốc trên máy bạn, mặc định ~/stock_db. Một tệp cấu hình duy nhất quyết định thư mục đó, nguồn ưu tiên cho từng bộ dữ liệu và các danh sách mã bạn hay dùng.

Tệp pipeline.toml

Tệp nằm ở ~/.vnstock/config/pipeline.toml, dùng chung với bản 3.x. Đổi đường dẫn bằng biến môi trường VNSTOCK_PIPELINE_CONFIG hoặc tham số --config của mọi lệnh. Tham số --base ghi đè thư mục gốc cho một lần chạy.

Shell
vnstock-pipeline config init                       # tạo tệp mẫu (thêm --force để ghi đè)
vnstock-pipeline config init --base D:/stock_db    # tạo tệp mẫu với thư mục gốc chọn sẵn
vnstock-pipeline config show                       # cấu hình đang có hiệu lực, dạng JSON
vnstock-pipeline store init                        # tạo thư mục gốc và mục lục

Tệp mẫu:

TOML
[store]
base_path = "~/stock_db"
compression = "zstd"           # zstd | snappy | gzip
keep_raw = false               # giữ nguyên văn thông điệp stream dưới raw/
catalog = true                 # duy trì mục lục _catalog/
history = true                 # ghi nhật ký mỗi lần ghi vào _catalog/history.jsonl
schema_guard = true            # cách ly tệp có cấu trúc cột lệch
quarantine_retention_days = 14   # khai sẵn, bản này chưa tự xoá tệp cách ly
overlap_days = 10              # số nến đọc lại để phát hiện lịch sử giá bị điều chỉnh
inception = "2000-01-01"       # ngày bắt đầu khi tải toàn bộ lịch sử

[sources]  # nguồn ưu tiên theo bộ dữ liệu, theo thứ tự dự phòng
ohlcv = ["dnse", "ssi", "tcbs"]
trades = ["dnse", "tcbs"]
order_book = ["dnse", "tcbs"]
quote = ["tcbs", "fhsc"]
foreign_flow = ["ssi", "dnse"]
session_stats = ["ssi"]
index_quote = ["dnse", "ssi"]
block_trades = ["tcbs"]
equity_list = ["ssi", "dnse"]
index_members = ["ssi", "dnse"]
price_limits = ["ssi", "dnse"]
events_calendar = ["ssi", "fhsc"]
trading_days = ["dnse"]
company_info = ["fhsc"]

[reference]
indexes = ["VN30", "VN100", "HNX30"]   # rổ chỉ số nạp thành phần, và nhóm INDEX

[calendar]
holidays = []                  # ngày nghỉ ngoài thứ bảy, chủ nhật, dạng "2026-09-02"

[watchlists]
ngan_hang = ["VCB", "BID", "CTG", "TCB", "MBB"]

[export]
# amibroker_db_path = "C:/AmiBroker/Data"
BảngÝ nghĩa
[store]Thư mục gốc, nén, bản thô, mục lục, kiểm cấu trúc, số nến đọc lại
[sources]Với mỗi bộ dữ liệu, các nguồn theo thứ tự thử. Nguồn đầu lỗi thì tác vụ thử nguồn kế tiếp. Chỉ ghi nguồn bạn có khoá. Tham số --source của lệnh run ghi đè bảng này cho một lần chạy
[reference]Rổ chỉ số mà run reference nạp thành phần
[calendar]Ngày nghỉ lễ. Pipeline dùng thêm ngày giao dịch đã nạp bằng run reference để biết hôm nào có phiên
[watchlists]Danh sách mã đặt tên, dùng với --watchlist ngan_hang
[stream] fields(Tuỳ chọn) chọn cột lưu cho từng loại sự kiện stream (Sự kiện chuẩn)

Tệp của bản 3.x vẫn đọc được. Pipeline đọc bảng [store] của thế hệ 6 trước, thiếu khoá nào thì lấy ở bảng [storage] và [metadata] của bản 3.x.

Bố cục thư mục

~/stock_db/
  _catalog/      contract.json, <bộ dữ liệu>.json, history.jsonl, .lock
  _schema/       cấu trúc cột chuẩn của từng bộ dữ liệu
  _quarantine/   tệp bị cách ly vì lệch cấu trúc
  raw/           thông điệp stream nguyên văn (khi bật keep_raw)
  market/        dữ liệu giao dịch nạp theo lịch
  reference/     danh mục, thành phần chỉ số, trần sàn, ngày giao dịch, sự kiện, doanh nghiệp
  stream/        dữ liệu trong phiên, chia theo nguồn và ngày

Bản 3.x ghi ohlcv/, intraday/… ngay dưới thư mục gốc; thế hệ 6 ghi dưới market/, reference/, stream/. Hai thế hệ dùng chung một thư mục gốc được.

Các bộ dữ liệu

Dữ liệu nạp theo lịch (lệnh run …):

Bộ dữ liệuĐường dẫnLuật gộpLệnh nạp
ohlcvmarket/ohlcv/<khung>/<MÃ>.parquetthay dòng cùng mốc giờrun ohlcv
tradesmarket/trades/<ngày>/<MÃ>.parquetghi lại cả tệprun trades
quotemarket/quote/<ngày>/<MÃ>.parquetthay dòng cùng mốc giờrun quote
order_bookmarket/order_book/<ngày>/<MÃ>.parquetthay dòng cùng mốc giờrun quote
index_quotemarket/index_quote/<ngày>/<CHỈ SỐ>.parquetthay dòng cùng mốc giờrun index
foreign_flowmarket/foreign_flow/<MÃ>.parquetthay dòng cùng mốc giờrun foreign
session_statsmarket/session_stats/<MÃ>.parquetthay dòng cùng mốc giờrun session-stats
block_tradesmarket/block_trades/<ngày>.parquetghi lại cả tệprun block-trades
equity_listreference/equity_list/<ngày>.parquetghi lại cả tệprun reference
index_membersreference/index_members/<ngày>.parquetghi lại cả tệprun reference
price_limitsreference/price_limits/<ngày>.parquetghi lại cả tệprun reference
trading_daysreference/trading_days.parquetthay dòng cùng ngàyrun reference
events_calendarreference/events_calendar.parquetthay dòng cùng mã, loại sự kiện, ngày GDKHQrun reference
company_info, company_shareholders, company_ownership, company_insiderreference/<bộ>/<MÃ>.parquetghi lại cả tệprun company

Bộ dữ liệu tham chiếu chia theo ngày giữ được ảnh chụp từng ngày, ví dụ thành phần VN30 trước và sau kỳ cơ cấu.

Dữ liệu trong phiên (lệnh stream run), mỗi loại sự kiện một bộ:

Bộ dữ liệuĐường dẫnLoại sự kiện
stream_tradesstream/trades/source=<nguồn>/date=<ngày>/part-<n>.parquettrade
stream_quotesstream/quotes/…quote
stream_bookstream/book/…book_delta
stream_indexstream/index/…index_tick
stream_index_estimatesstream/index_estimates/…index_estimate
stream_foreignstream/foreign/…foreign_flow
stream_statsstream/stats/…stats
stream_price_limitsstream/price_limits/…price_limits
stream_auctionstream/auction/…auction
stream_put_through_offersstream/put_through_offers/…put_through_offer
stream_flowstream/flow/…flow
stream_statusstream/status/…status
stream_index_contributionstream/index_contribution/…index_contribution
stream_barsstream/bars/<khung>/source=<nguồn>/date=<ngày>/part-<n>.parquetbar: nến pipeline dựng và nến nguồn phát

Trong phiên, pipeline ghi một tệp phần mỗi vài giây để dữ liệu không mất khi máy tắt đột ngột. Khi phiên kết thúc, hoặc khi phiên chạy qua nửa đêm, các tệp phần của mỗi nguồn trong ngày được gộp lại thành part-00000.parquet. Lệnh store compact gộp các ngày cũ hơn hôm nay, phòng khi một phiên bị ngắt giữa chừng.

Nguồn gốc trong từng tệp

Mỗi tệp Parquet mang trong metadata các thông tin sau:

  • source: nguồn;
  • route: tuyến dữ liệu của vnstock 6;
  • producer: phiên bản phần mềm đã ghi;
  • terms_url: liên kết tới điều khoản của nguồn;
  • envelope_sha256: dấu kiểm của phản hồi gốc;
  • retrieved_at, written_at: giờ lấy và giờ ghi;
  • price_unit, interval khi có.

Đọc lại bằng Store().read, các khoá này nằm trong df.attrs. Nhờ vậy mỗi con số lần ngược được về nguồn và lúc lấy.

Tệp chuyển từ bản 3.x mang source = "legacy_v5".

Mục lục

Thư mục _catalog/ có các tệp sau:

TệpNội dung
<bộ dữ liệu>.jsonMỗi tệp một mục: số dòng, ngày đầu, ngày cuối, nguồn, giờ cập nhật. Riêng dữ liệu trong phiên, mỗi nguồn mỗi ngày một mục, ghi tổng số dòng và số tệp phần
history.jsonlMột dòng cho mỗi lần ghi: tạo mới, nối thêm, thay thế, số dòng mới
contract.jsonPhiên bản bố cục và phiên bản sự kiện chuẩn của thư mục này

Mục lục được cập nhật dưới khoá chung, nên nhiều tiến trình ghi cùng thư mục gốc vẫn an toàn, ví dụ mỗi nguồn stream một tiến trình. Mục lục hỏng hay bị xoá thì dựng lại từ tệp trên đĩa:

Shell
vnstock-pipeline store catalog ohlcv            # xem mục lục một bộ dữ liệu
vnstock-pipeline store catalog --rebuild        # quét tệp, viết lại mục lục mọi bộ dữ liệu

Lệnh quản lý thư mục lưu trữ

LệnhViệc
store initTạo thư mục gốc, mục lục, hợp đồng phiên bản
store tree [--depth N]In cây thư mục
store reportSố tệp, dung lượng, số dòng, lần cập nhật cuối của từng bộ dữ liệu
store catalog [bộ] [--rebuild]Xem hoặc dựng lại mục lục
store audit [--interval 1D] [--stale-days 5]Kiểm nến đã lưu: độ tươi, khoảng hở, giá bất thường (Chất lượng dữ liệu)
store compact [--date YYYY-MM-DD]Gộp tệp phần stream của mỗi nguồn mỗi ngày thành một tệp; mặc định mọi ngày trước hôm nay

Đọc lại bằng Python

Python
from vnstock_pipeline import Store

store = Store()                                   # theo pipeline.toml; Store("D:/stock_db") nếu muốn khác

daily = store.read("ohlcv", "FPT", interval="1D", start="2026-01-01", end="2026-10-31")
ticks = store.read("trades", "FPT", date="2026-11-03")
vn30 = store.read("index_members", date="2026-11-03")

# dữ liệu trong phiên: theo nguồn và ngày, hoặc gộp mọi nguồn
live = store.read("stream_trades", source="<nguồn>", date="2026-11-04")
bars = store.read("stream_bars", interval="1m", source="<nguồn>", date="2026-11-04")

store.symbols("ohlcv", interval="1D")             # các mã đã có
store.dates("stream_trades", source="<nguồn>")     # các ngày đã có

read nhận symbol, interval, date hoặc dates, source, start, end, columns. Khi lấy nhiều phân vùng, các tệp được nối theo thứ tự đường dẫn.

Tệp Parquet đọc được bằng mọi công cụ quen dùng như pandas, polars, DuckDB, Excel Power Query. Nhờ thư mục source=…/date=…, các công cụ hiểu kiểu phân vùng Hive nhận ra nguồn và ngày như cột.

Bước tiếp theo

Tác vụ nạp dữ liệu.