Chế độ khớp lệnh và đối chứng
Mục lục
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.
Hai thư viện backtest chạy cùng một chiến lược trên cùng dữ liệu vẫn có thể ra hai kết quả khác nhau. Lý do không phải một bên tính sai, mà là mỗi bên chọn một giả định khác nhau cho những câu hỏi như: lệnh khớp ở giá nào, cắt lỗ xét theo giá thấp nhất hay giá đóng cửa, khối lượng tính theo giá nào.
vnstock_quant.backtest gom mọi lựa chọn đó vào tham số execution. Mỗi chế độ là một bộ lựa chọn có tên.
Các chế độ có sẵn
execution | Dùng khi | Luật thị trường VN |
|---|---|---|
vn_realistic (mặc định) | Backtest cổ phiếu Việt Nam | có |
frictionless | Thử nhanh ý tưởng, không lô, không biên độ, không T+ | không |
backtesting_py | So kết quả với backtesting.py | không |
backtrader | So kết quả với backtrader | không |
vectorbt | So kết quả với vectorbt (Portfolio.from_signals) | không |
zipline | So kết quả với zipline-reloaded | không |
lean | Gần với QuantConnect Lean, chưa đối chứng | không |
bt.list_presets() trả đủ các lựa chọn của từng chế độ. Truyền execution dạng dict để sửa một lựa chọn:
res = bt.run(df, sigs, execution={"preset": "vn_realistic", "stop_trigger": "close"})Các lựa chọn
| Khoá | Giá trị | Ý nghĩa |
|---|---|---|
timing | next_open, next_close, same_close | Tín hiệu phiên t khớp ở giá mở cửa phiên t+1, giá đóng cửa phiên t+1, hay giá đóng cửa chính phiên t. same_close có cảnh báo nhìn trước tương lai |
market_rules | true, false | Áp lô, bước giá, biên độ, khóa trần/sàn, chu kỳ thanh toán |
stop_trigger | intrabar, close | Cắt lỗ kích hoạt khi giá thấp nhất chạm mức, hay khi giá đóng cửa vượt mức |
stop_fill | gap_aware, at_level | Giá khớp của cắt lỗ: tại mức đặt, hoặc tại giá mở cửa nếu phiên mở cửa đã vượt qua mức đó; hay luôn tại mức đặt |
same_bar_priority | stop_first, target_first, ohlc_path | Phiên chạm cả mức cắt lỗ và mức chốt lời thì giả định cái nào xảy ra trước. ohlc_path suy ra thứ tự từ khoảng cách giá mở cửa tới giá cao/thấp trong phiên (cách TradingView giả định), chỉ nên dùng để so sánh |
stops_on_entry_bar | true, false | Xét cắt lỗ ngay trong phiên vào lệnh |
trail_reference | prior_highs, include_current_high, prior_closes | Đỉnh dùng cho cắt lỗ đuổi. include_current_high lạc quan: lấy cả giá cao của chính phiên đang xét |
sizing_price | fill_price, signal_close | Tính khối lượng theo giá khớp, hay theo giá đóng cửa phiên phát tín hiệu |
reserve_fees | true, false | Chừa tiền cho phí khi tính khối lượng |
enforce_cash | true, false | Không cho mua vượt tiền mặt |
check_cash_at_signal | true, false | Kiểm tiền cả lúc phát tín hiệu, không chỉ lúc khớp |
signal_conflict | exit_wins, ignore_both | Phiên có cả tín hiệu vào và thoát |
cash_buffer_pct | số | Tỷ lệ tiền mặt luôn để dành |
use_unsettled_proceeds | true, false | Dùng tiền bán chưa về để mua |
vn_realistic chọn hướng thận trọng ở mọi chỗ có thể chọn: khớp ở giá mở cửa phiên sau, cắt lỗ xét theo giá thấp nhất, giá khớp tính cả khoảng trống giá, ưu tiên cắt lỗ khi một phiên chạm cả hai mức, đỉnh của cắt lỗ đuổi chỉ lấy từ các phiên trước, chừa tiền cho phí, không dùng tiền chưa về.
Những khác biệt đáng biết giữa các thư viện
Ba khác biệt dưới đây chỉ lộ ra khi chạy song song các thư viện trên cùng kịch bản:
- zipline xét cắt lỗ theo giá đóng cửa và khớp ở giá đóng cửa phiên sau. Chiến lược có cắt lỗ chặt thường ra kết quả khác hẳn so với thư viện xét theo giá thấp nhất.
- vectorbt (
from_signals) bỏ cả tín hiệu vào lẫn tín hiệu thoát khi hai tín hiệu rơi vào cùng một phiên. Các thư viện khác thường cho tín hiệu thoát thắng. - backtrader kiểm tiền hai lần: lúc tạo lệnh theo giá đóng cửa phiên phát tín hiệu, và lúc khớp. Phiên sau mở cửa cao hơn thì lệnh có thể bị từ chối dù lúc phát tín hiệu vẫn đủ tiền.
Đối chứng
Mỗi chế độ đối chứng được kiểm bằng 11 kịch bản chung:
- khối lượng cố định, không phí và có phí;
- khoảng trống giá xuyên qua mức cắt lỗ, và xuyên qua mức chốt lời;
- một phiên chạm cả mức cắt lỗ lẫn mức chốt lời;
- cắt lỗ ngay trong phiên vào lệnh;
- khối lượng theo tỷ lệ tài sản, có phí và không phí;
- tín hiệu vào khi đang giữ vị thế;
- cắt lỗ đuổi;
- giao cắt đường trung bình trên một chuỗi giá ngẫu nhiên.
Mỗi kịch bản chạy trên thư viện gốc, rồi chạy lại bằng vnstock_quant.backtest ở chế độ tương ứng với profile="frictionless" và cùng mức phí.
Kết quả ngày 14/10/2026:
| Thư viện tham chiếu | Bản | Kết quả |
|---|---|---|
| backtesting.py | 0.6.6 | khớp 11/11 |
| backtrader | 1.9.78.123 | khớp 11/11 |
| vectorbt | 1.1.2 | khớp 11/11 |
| zipline-reloaded | 3.1.1 | khớp 11/11 |
"Khớp" nghĩa là cùng số lệnh, cùng ngày và giá vào/ra, và đường vốn từng phiên lệch không quá 0,000001. QuantConnect Lean chưa đối chứng, nên chế độ lean chỉ là xấp xỉ.
Để so với thư viện bạn đang dùng:
res = bt.run(df, sigs, profile="frictionless", fee=0.001, execution="backtrader")TradingView và Amibroker chưa có chế độ đối chứng. Kết quả của hai công cụ này phụ thuộc cài đặt trong Strategy Tester và Analysis, không tự động tái tạo được. Gọi execution="tradingview" hay "amibroker" sẽ báo lỗi QUANT_INVALID_PARAMETER kèm danh sách chế độ đã đối chứng.
