8. 回測引擎與性能(設計視角)
本章從架構與實現角度說明 qteasy 回測引擎的向量化與 Numba 使用方式,以及與 VectorBT 等框架的差異,供需要深入理解或做技術選型的讀者參考。使用層面的說明見《回測並評價交易策略》中的 6. 回測引擎與性能。
8.1. 1. 回测引擎在整体中的位置
回測模式(mode=1)的流程在 回測、實盤與優化 中已概括:準備歷史數據 → 構建 Backtester → 按 group_timing_table 逐步運行 Operator 生成信號 → 解析信號並模擬成交 → 評價與輸出。其中,“解析信號並模擬成交”由 backtest 模塊中的 Numba 函數完成,實現“時間維順序、標的維向量化”。
8.2. 2. Numba 使用点与向量化结构
2.1 核心函數
在 qteasy/backtest.py 中:
backtest_step:
@njit(nogil=True, cache=True)。單步內根據信號與當前持倉、現金、交割隊列,計算買賣量、費用、持倉更新與交割隊列更新;對整批標的做數組運算。calculate_trade_results:
@njit,用於交易結果與資金變動計算。backtest_batch_steps:
@njit(nogil=True, cache=True)。在 Numba 內按signal_count(時間步數)循環,每步調用backtest_step,完成整段回測,實現“時間維順序、標的維向量化”。backtest_flash_steps:
@njit(nogil=True, cache=True)。與backtest_batch_steps類似,但不保留中間資金與持倉序列,僅保留最終狀態,用於優化階段多組參數回測時節省內存。
在 qteasy/blender.py 中,信號混合用的部分算子(如 op_sum、op_floor 等)也使用 @njit 加速。
2.2 時間維順序與標的維向量化
時間維必須順序:因爲存在交割隊列、T+1、MOQ 等狀態,下一筆交易依賴當前持倉與交割狀態,無法在時間軸上完全並行或一次性矩陣化。
標的維向量化:在每一個時間步內,對所有標的的 signal、持倉、買賣量、費用等用 NumPy 數組與 Numba 內聯運算,避免 Python 層循環。
因此,單次回測可以理解爲:一層 Numba 內的時間步循環 + 每步內的向量化計算。
2.3 優化階段
在 qteasy/optimization.py 中,多組參數通過多進程(如 ProcessPoolExecutor)並行執行回測;每組內部使用 backtest_flash_steps 等路徑,只保留最終資金/持倉,以降低內存佔用並提高吞吐。
8.3. 3. 与 VectorBT 的架构差异
維度 |
qteasy |
VectorBT |
|---|---|---|
時間維度 |
順序步進(for 步),每步內向量化 |
全時間軸一次性矩陣運算,無顯式時間循環 |
標的維度 |
每步對全部標的做數組運算(1D 數組) |
標的與時間一起參與廣播,多策略/多參數可一併廣播 |
核心加速 |
backtest_step、backtest_batch_steps、backtest_flash_steps 等爲 @njit;信號解析、交割隊列等也用 Numba |
NumPy + Numba,策略表達爲純數組運算 |
狀態與約束 |
顯式維護現金、持倉、交割隊列(T+1 等),狀態依賴下一筆,故時間維必須順序 |
多爲簡化資金曲線,不強調 T+1/交割/MOQ,易做全矩陣 |
結論:qteasy 並非“缺乏向量化/Numba”,而是在保證狀態正確性(T+1、交割、MOQ、多策略合併等)的前提下,選擇了“時間順序 + 標的維向量化 + Numba 單步”的折中;與 VectorBT 的“全矩陣廣播”各有適用場景(qteasy 偏規則嚴謹與實盤一致,VectorBT 偏海量參數快速篩選)。
8.4. 4. 相关文档
統一入口與模式:回測、實盤與優化。
使用側說明:回測並評價交易策略 - 回測引擎與性能。
設計初衷與數據隔離:設計初衷與獨特優勢。