Vnstock Logo

Dữ liệu và tín hiệu

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.

Thư viện tách phần sinh tín hiệu khỏi phần khớp lệnh. Bạn quyết định khi nào vào và khi nào thoát; thư viện quyết định lệnh khớp ở giá nào, có khớp được không, và phí bao nhiêu.

Dữ liệu đầu vào

data là một pandas.DataFrame hoặc danh sách dict, mỗi dòng một phiên, xếp từ cũ tới mới.

CộtBắt buộcGhi chú
time / date / datetimecóNgày phiên, dạng YYYY-MM-DD hoặc kiểu ngày giờ. Nếu ngày nằm ở chỉ mục của DataFrame thì thư viện tự lấy ra
open, high, low, closecóGiá. Kết quả của vnstock (Market().equity(...).ohlcv(...)) dùng được ngay
volumekhôngMặc định 0
reference_pricekhôngGiá tham chiếu của phiên. Không có thì lấy giá đóng cửa phiên trước để tính biên độ

Thiếu cột ngày là lỗi QUANT_INPUT_DATA: thư viện không tự sinh ngày.


Ba cách đưa tín hiệu vào

1. Mảng [-1, 0, 1]

Python
sigs = [0] * len(df)
sigs[20], sigs[45] = 1, -1          # vào ở tín hiệu phiên 20, thoát ở tín hiệu phiên 45
res = bt.run(df, sigs, symbol="FPT")

1 là vào vị thế mua, -1 là thoát. Trên hồ sơ cho phép bán khống (vn_futures, crypto_perp), -1 còn mở vị thế bán và 1 đóng nó.

2. Cặp entries / exits

Python
ma20 = df["close"].rolling(20).mean()
res = bt.run(
    df,
    entries=(df["close"] > ma20).tolist(),
    exits=(df["close"] < ma20).tolist(),
    symbol="FPT",
)

Có thêm short_entries, short_exits cho hồ sơ cho phép bán khống. tags là danh sách nhãn theo phiên; nhãn được chép sang lệnh mở ở phiên đó. Khi đang giữ nhiều lô cùng mã (pyramiding > 1), exit_tags cho biết tín hiệu thoát ở một phiên chỉ nhắm vào lô mang nhãn nào — xem mục nhiều lô ở trang Chạy backtest và đọc kết quả.

Ba cách trên quyết định khi nào. Mức giá của lệnh giới hạn, lệnh dừng và mức dừng lỗ đổi theo từng phiên lại là tín hiệu riêng, theo phiên: entry_limit, entry_stop, exit_stop. Chi tiết ở trang Chạy backtest và đọc kết quả.

3. Bảng quy tắc rule_dsl

Bảng quy tắc là một dict phẳng, được tính trong lõi Rust với các chỉ báo của vnstock_quant. Đây là cách nên dùng khi bạn hay trợ lý AI mô tả chiến lược bằng lời.

Python
dsl = {
    "entry_logic": "all",
    "entry_rules": [
        {"left": {"ind": "rsi", "params": {"length": 14}}, "op": "cross_above", "right": 30},
        {"left": "close", "op": "gt", "right": {"ind": "sma", "params": {"length": 200}}},
    ],
    "exit_logic": "any",
    "exit_rules": [
        {"left": {"ind": "rsi", "params": {"length": 14}}, "op": "gt", "right": 70},
        {"left": {"ind": "macd", "output": "MACDh"}, "op": "cross_below", "right": 0},
    ],
}
res = bt.run(df, rule_dsl=dsl, symbol="FPT")

Toán hạng (left, right):

DạngVí dụÝ nghĩa
Số30Hằng số, theo đúng đơn vị dữ liệu bạn đưa vào (nghìn đồng nếu dữ liệu từ vnstock)
Tên cột"close", "volume"Một cột của dữ liệu, hoặc cột bạn thêm qua feature_columns
Cột lùi phiên{"col": "close", "shift": 1}Giá trị của cột ở shift phiên trước. shift không nhận số âm
Chỉ báo{"ind": "sma", "params": {"length": 50}}Một chỉ báo trong bt.list_indicators()
Chỉ báo nhiều cột{"ind": "bbands", "params": {"length": 20}, "output": "BBU"}Chọn một cột đầu ra theo tên hoặc tiền tố
Chỉ báo trên cột khác{"ind": "sma", "params": {"length": 20}, "source": "volume"}Tính chỉ báo trên volume thay cho close

Chỉ báo cũng nhận shift, ví dụ {"ind": "rsi", "params": {"length": 14}, "shift": 1}.

Phép so sánh (op): gt, gte, lt, lte, eq, cross_above, cross_below. cross_above đúng ở phiên left vượt lên trên right, tức phiên trước left <= right và phiên này left > right.

Cách gộp điều kiện:

KhoáMặc địnhGiá trị
entry_logic, short_entry_logic"all""all", "any", hoặc {"vote_at_least": k} (ít nhất k điều kiện đúng)
exit_logic, short_exit_logic"any"Như trên

Bảng quy tắc cần ít nhất một điều kiện vào lệnh. short_entry_rules, short_exit_rules chỉ dùng trên hồ sơ cho phép bán khống. Trong giai đoạn chỉ báo chưa đủ dữ liệu khởi động, điều kiện được tính là sai.

Xem trước tín hiệu mà không chạy backtest:

Python
sig = bt.eval_rule_dsl(dsl, df)
print(sum(sig["entries"]), sum(sig["exits"]))

Danh sách chỉ báo

bt.list_indicators() trả 56 chỉ báo, mỗi mục có name, group, inputs, params (tên, kiểu, mặc định), title và access:

  • access: "bt_basic": dùng được ở mọi cấp, gồm 10 chỉ báo sma, ema, rsi, macd, stoch, bbands, atr, obv, vwap, pivots;
  • access: "bt": cần cấp Bronze trở lên.

Bảng quy tắc dùng một chỉ báo chưa mở cho cấp của bạn thì bị từ chối (QUANT_TIER_REQUIRED) trước khi chạy, không bị trừ lượt.

NhómChỉ báo
Xu hướngsma, ema, wma, hma, smma, alma, vwma, adx, psar, supertrend, dm, linreg, aroon
Động lượngrsi, stoch, stochrsi, mom, roc, ao, cci, willr, tsi, cmo, uo, fisher, cg, kst, macd
Biến độngbbands, kc, atr, stdev, donchian, massi, ui, squeeze, squeeze_pro, true_range
Khối lượngobv, cmf, ad, vwap, pvo, efi, eom, nvi, mfi
Thống kêpivots, mad, variance, hl2, hlc3, ohlc4, midprice, decreasing, increasing

Hai chỉ báo của vnstock_quant không dùng được trong bảng quy tắc:

  • ichimoku dịch đường mây về phía trước, nên giá trị tại phiên t đọc dữ liệu sau t;
  • vp không trả một giá trị cho mỗi phiên.

Gọi chúng thì báo QUANT_CAUSALITY_VIOLATION.


Kiểm tra thiên lệch nhìn trước tương lai

Một tín hiệu tại phiên t chỉ được dùng dữ liệu tới hết phiên t. Cách kiểm của thư viện: tính tín hiệu trên toàn bộ dữ liệu, rồi tính lại trên dữ liệu đã cắt ở 5 điểm (50%, 62%, 75%, 87%, 95% số phiên). Nếu tín hiệu ở một phiên trước điểm cắt thay đổi, hàm tín hiệu đã đọc dữ liệu tương lai.

Hàm tín hiệu Python của bạn:

Python
def signal_fn(d):
    up_tomorrow = d["close"].shift(-1) > d["close"]      # đọc giá ngày mai
    return up_tomorrow.astype(int).where(up_tomorrow, -1).tolist()

report = bt.check_causality(signal_fn, df)
print(report["passed"], report["mismatch_bars"])

signal_fn(data) trả mảng [-1, 0, 1], tuple (entries, exits) hoặc dict. Kết quả gồm passed, mismatch_bars (vị trí phiên bị đổi tín hiệu), cuts và message. Ví dụ trên báo không đạt. Lỗi hay gặp:

  • shift(-1);
  • cửa sổ trượt đặt giữa (center=True);
  • chuẩn hoá trên toàn mẫu (trừ trung bình, chia độ lệch chuẩn của cả chuỗi).

Bảng quy tắc:

Python
report = bt.check_rule_dsl_causality(dsl, df)

Mặc định execution="vn_realistic": tín hiệu tính ở giá đóng cửa phiên t khớp ở giá mở cửa phiên t+1. Đổi sang khớp ở giá đóng cửa của chính phiên t (execution_timing="same_close") là giả định lạc quan; chỉ dùng khi bạn biết rõ mình đang mô phỏng điều gì.