Giá điều chỉnh
Mục lụ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àm | Trả 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.
Đ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%.
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:
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á
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
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ướcdate.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
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 |
|---|---|---|
mode | full (mặc định) | Lợi suất, rủi ro, backtest: cổ tức tiền được tính như đã tái đầu tư |
split | Chỉ báo kỹ thuật, so đồ thị giá không tính cổ tức tiền | |
basis | event (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á) | |
infer | True (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ó |
unit | auto, 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:
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)
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
- Quy ước dữ liệu và lỗi — Vì sao chuỗi lợi suất cần giá đã điều chỉnh.
- Rủi ro và hiệu suất — Tính lợi suất và các thước đo từ giá đã điều chỉnh.
- Luật thị trường, phí và sự kiện trong backtest — Cách mô-đun backtest xử lý cổ tức và quyền mua khi mô phỏng.
