Vnstock Logo

Giá điều chỉnh

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_quant v1.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à v0.5.0, xem tài liệu bản đó.

vnstock_quant.prices chuyển bảng giá gốc (chưa điều chỉnh) sang giá đã điều chỉnh theo sự kiện quyền. Hàm dùng danh sách sự kiện (events()) và kiểm từng sự kiện với giá tham chiếu, giá trần, giá sàn do sàn đặt, nên bạn biết sự kiện nào khớp với sàn và sự kiện nào cần xem lại. Cần cấp quyền sử dụng từ Bronze, cùng nhóm quyền risk (Quyền dùng và hạn mức).

HàmTrả về
prices.adjust(prices, events, ...)Bảng giá đầu vào với các cột giá đã nhân hệ số; bảng hệ số trong attrs["factors"]
prices.factors(prices, events, ...)Bảng hệ số: mỗi phiên giao dịch không hưởng quyền một dòng, kèm nhân chứng của sàn và trạng thái
prices.from_vnstock(symbol, start, end, ...)Tạm tắt trên dữ liệu vnstock 6, xem bên dưới

Chuỗi lợi suất cho risk, portfolio và backtest nên tính từ giá đã điều chỉnh: giá chưa điều chỉnh tạo ra phiên thua lỗ giả vào ngày giao dịch không hưởng quyền.

Tải qua vnstock 6: tạm tắt

Đo ngày 06/11/2026, các nguồn hiện đọc được qua vnstock 6 trả giá đã điều chỉnh cho mọi phiên trước sự kiện quyền gần nhất, cả ở trade_history() lẫn ohlcv(); chỉ các phiên sau sự kiện đó là giá gốc. Điều chỉnh thêm sẽ tính sự kiện hai lần. Vì vậy thư viện nhận ra bảng như vậy (giá đóng cửa lẻ bước giá 10 đồng, điều không xảy ra với giá giao dịch thật) và báo lỗi QUANT_INPUT_DATA thay vì trả kết quả sai.

Cần giá đã điều chỉnh: dùng thẳng ohlcv(). Cần kiểm từng sự kiện quyền: đưa bảng giá gốc bạn có (đúng bước giá) vào prices.adjust.


Dữ liệu mẫu

Ví dụ dùng bốn phiên giá gốc có giá tham chiếu, trần, sàn (dạng bảng phiên của thế hệ 5), chạy được không cần mạng. Phiên 12/06/2024 là ngày giao dịch không hưởng quyền của FPT: cổ tức tiền 1.000 đồng và cổ phiếu thưởng 15%.

Python
import pandas as pd
from vnstock_quant import prices

tz = "Asia/Ho_Chi_Minh"
sessions = pd.DataFrame({
    "trading_date": pd.to_datetime(["2024-06-10", "2024-06-11", "2024-06-12", "2024-06-13"]).tz_localize(tz),
    "reference_price": [144_000.0, 145_000.0, 126_517.0, 132_000.0],
    "ceiling_price": [154_000.0, 155_100.0, 135_300.0, 141_200.0],
    "floor_price": [134_000.0, 134_900.0, 117_700.0, 122_800.0],
    "open": [144_500.0, 145_500.0, 128_000.0, 132_500.0],
    "high": [146_000.0, 147_000.0, 133_000.0, 134_000.0],
    "low": [143_500.0, 145_000.0, 127_500.0, 131_500.0],
    "close": [145_000.0, 146_500.0, 132_000.0, 133_000.0],
    "matched_volume": [3.1e6, 2.8e6, 6.4e6, 4.0e6],
})
events = pd.DataFrame({
    "event_code": ["DIV", "ISS", "ISS"],
    "issue_type": [None, "bonus_share", "esop"],
    "event_title_vi": ["Cổ tức tiền 1.000đ", "Cổ phiếu thưởng 15%", "ESOP 0,5%"],
    "exright_date": pd.to_datetime(["2024-06-12", "2024-06-12", "2024-06-13"]).tz_localize(tz),
    "exercise_ratio": [0.1, 0.15, 0.005],
    "value_per_share": [1000.0, None, None],
})

Với dữ liệu thật, bảng phiên phải là giá gốc do bạn có sẵn (ví dụ bảng đã lưu từ trước, hoặc tệp xuất từ phần mềm giao dịch). Bảng sự kiện thì tải được qua vnstock 6:

Python
from vnstock import Reference

events = Reference().company("FPT").events(start="2024-01-01", end="2024-12-31", source="<nguồn sự kiện>")

Thư viện đọc trực tiếp các cột event_type, ex_right_date, ratio, dividend_percent, value của events() thế hệ 6. Giá phát hành của quyền mua (exercise_price) tính bằng nghìn đồng và được đổi về đồng. Bảng sự kiện đã lưu theo cột thế hệ 5 (event_code, exright_date, exercise_ratio, value_per_share) vẫn đọc được.


Điều chỉnh giá

Python
adjusted = prices.adjust(sessions, events)
adjusted[["trading_date", "close", "reference_price"]]

Giá các phiên trước 12/06/2024 được nhân với (146.500 − 1.000) / (1,15 × 146.500) ≈ 0,8636. Phiên cuối giữ nguyên. ESOP không làm đổi giá tham chiếu nên không được điều chỉnh. Khối lượng và các cột *_adjusted của bảng đầu vào giữ nguyên.


Bảng hệ số và nhân chứng của sàn

Python
table = prices.factors(sessions, events)
table[["date", "kinds", "cash", "stock", "exchange_factor", "witness", "factor", "status"]]
  • factor: hệ số nhân cho mọi giá trước date.
  • exchange_factor: hệ số suy từ giá tham chiếu của sàn (126.517 / 146.500).
  • witness = "reference": giá tham chiếu và trung điểm trần, sàn cùng xác nhận sự kiện.
  • witness = "reference_only": bảng không có giá trần, giá sàn; sự kiện chỉ được kiểm bằng giá tham chiếu với dung sai rộng hơn.
  • status = "confirmed": sự kiện khớp với sàn.

Bảng không có giá trần, giá sàn thì thư viện không tự suy sự kiện thiếu trong danh sách và báo cảnh báo: chỉ riêng giá tham chiếu không phân biệt được sự kiện thật với biến động thường của UPCoM. Đo trên 72 mã lịch sử dài với giá gốc đã lưu từ thế hệ 5: trong 805 sự kiện có ở cả hai cách kiểm, 3 sự kiện lệch trên 1% (đều có quyền mua); 13 sự kiện danh sách thiếu không được phát hiện; 11/72 mã có hệ số tích luỹ lệch trên 2%. Bảng có trần, sàn thì kiểm đầy đủ như bản 0.5.

Trạng thái khác cho biết mức tin cậy thấp hơn: implied khi chỉ suy được từ giá sàn đặt, inferred khi danh sách sự kiện không có nhưng giá tham chiếu và biên độ cùng đổi, unresolved khi sự kiện và giá sàn không khớp nhau. Trạng thái cần bạn chú ý đều kèm cảnh báo VnstockQuantWarning.


Tuỳ chọn

Python
split = prices.factors(sessions, events, mode="split")          # chỉ sự kiện cổ phiếu
exchange = prices.factors(sessions, events, basis="exchange")   # theo giá tham chiếu đã làm tròn của sàn
split["factor"].iloc[0], exchange["factor"].iloc[0]
Tham sốGiá trịDùng khi
modefull (mặc định)Lợi suất, rủi ro, backtest: cổ tức tiền được tính như đã tái đầu tư
splitChỉ báo kỹ thuật, so đồ thị giá không tính cổ tức tiền
basisevent (mặc định)Giá lý thuyết từ sự kiện, không phụ thuộc cách làm tròn của sàn
exchangeĐúng giá tham chiếu sàn đã đặt (đã làm tròn bước giá)
inferTrue (mặc định)Điều chỉnh cả lần giá tham chiếu và biên độ cùng đổi mà danh sách sự kiện không có
unitauto, dong, thousandĐơn vị của bảng giá; auto nhận ra bảng nghìn đồng của ohlcv()

Quyền mua không có giá phát hành trong events(). Thư viện suy giá từ giá tham chiếu. Nếu biết giá chính xác, điền vào cột value_per_share của dòng quyền mua:

Python
rights = pd.DataFrame({
    "event_code": ["ISS"], "issue_type": ["rights_issue"], "event_title_vi": ["Quyền mua 20%"],
    "exright_date": pd.to_datetime(["2024-06-12"]).tz_localize(tz),
    "exercise_ratio": [0.2], "value_per_share": [10_000.0],
})
prices.factors(sessions[["trading_date", "close"]], rights)[["rights_price", "rights_price_source", "factor"]]

Tải trực tiếp qua vnstock (tạm tắt)

Python
bars = prices.from_vnstock("FPT", start="2023-01-01", source="<nguồn phiên>", events_source="<nguồn sự kiện>")
# InputDataError: [QUANT_INPUT_DATA] 922/956 phiên có giá đóng cửa lẻ bước giá 10 đồng, phiên cuối 2026-09-18:
# bảng giá đã được nguồn điều chỉnh, điều chỉnh thêm sẽ tính sự kiện hai lần. ...

Hàm vẫn có trong thư viện, thêm hai tham số source (nguồn của bảng phiên) và events_source (nguồn của lịch sự kiện), vì hai loại dữ liệu này có thể đến từ hai nguồn khác nhau. Trên dữ liệu hiện có, hàm báo lỗi như trên khi khoảng ngày chứa một sự kiện quyền; khoảng ngày sau sự kiện gần nhất thì chạy, nhưng khi đó không có gì để điều chỉnh. Khi vnstock có loại dữ liệu giá gốc, hàm sẽ chạy lại mà không cần đổi mã.


Đọc tiếp