Vnstock Logo

Giá điều chỉnh

Mở rộng

Mục lục

Tính năng đang thử nghiệm

Tính năng trên trang này đang trong giai đoạn phát triển thử nghiệm và chưa ổn định. Bạn dùng được để tìm hiểu và chạy thử, nhưng tên hàm hay công cụ, tham số và cấu trúc kết quả có thể còn đổi giữa các bản phát hành, cách tính và cách xử lý cũng có thể còn được hiệu chỉnh.

Hãy đối chiếu kết quả với một cách tính độc lập trước khi đưa vào quy trình nghiên cứu, và ghim phiên bản thư viện trong dự án để mã đang chạy không tự đổi theo bản mới.

vnstock_quant.prices chuyển bảng giá chưa điều chỉnh (dạng trade_history() của vnstock) 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, ...)open, high, low, close, volume đã điều chỉnh, đơn vị đồng, tải qua vnstock

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.


Dữ liệu mẫu

Ví dụ dùng bốn phiên có dạng của trade_history(), 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:

Python
from vnstock import Market, Reference

sessions = Market().equity("FPT").trade_history(start="2024-01-01", end="2024-12-31")
events = Reference().company("FPT").events()

trade_history() trả tối đa 1.000 phiên mỗi lần gọi. Cần chuỗi dài thì dùng prices.from_vnstock, hàm này tự tải theo từng cửa sổ ba năm.


Đ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.
  • status = "confirmed": sự kiện khớp với sàn.

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

Python
bars = prices.from_vnstock("FPT", start="2019-01-01")
bars.tail()
pd.DataFrame(bars.attrs["factors"])     # bảng hệ số

Bảng trả về có dạng như Market().equity(s).ohlcv() (open, high, low, close, volume, chỉ mục time) nhưng đơn vị là đồng. Dùng thẳng được cho vnstock_quant.ta, risk.returns và portfolio.


Đọc tiếp