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_sumop_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. 相关文档