⚙️ 回测框架设计:事件驱动与向量化

两种回测范式的取舍与两级流水、回测引擎五个核心模块的设计要点(数据/信号/组合/撮合/账户)、撮合诚实原则的四层阶梯、引擎可信度的四项验收测试。

回测引擎是量化的「时光机」,而时光机的诚实度决定了你看到的历史是否可信。本篇讲两类引擎的架构取舍与五个核心模块的设计要点——无论用开源框架(见框架概览 )还是自建,都需要理解这些内部机制。

两种范式:向量化 vs 事件驱动

向量化回测:整列运算——信号矩阵 × 收益矩阵 = 净值。1000 组参数秒级完成。它的隐含假设极其简化:下一 bar 收盘价成交、无资金约束冲突、无盘中状态。适合:因子海选、参数扫描、快速迭代(VectorBT 的定位,见框架概览 )。

事件驱动回测:按时间逐事件推进——每个 bar/tick 依次经过「数据 → 信号 → 组合 → 订单 → 撮合 → 账户」的状态机。慢 2–3 个数量级,但可以诚实建模:信号在 T 日收盘后生成、T+1 开盘下单、部分成交、停牌冻结、现金不足拒单。适合:策略的最终验证与实盘前置仿真。

正确的分工是两级流水:向量化做「快而糙」的探索(初筛 200 组参数),事件驱动做入围者的「慢而诚实」的终审。只用向量化做最终结论是最常见的自欺;只用事件驱动做探索则是算力的无底洞。

回测引擎的五个核心模块

① 数据层:统一接口与 PIT 门禁

数据层对上提供唯一接口 get(code, field, dt)——语义必须是「dt 时刻可知的最新值」(PIT 语义,见数据清洗 )。设计要点:行情(复权口径)、财务(公告日对齐)、股票池(动态成分)三类数据分表管理;引擎不信任任何「顺手处理过」的数据——复权与对齐的显式配置在引擎层强制声明(A 股细节见A 股数据特有问题 )。

② 信号层:与执行的时间协议

信号层最容易藏前视偏差。时间协议要写成铁律:T 日收盘后可得的数据 → T+1 的委托价成交(或 T 日收盘价成交但信号只用 T-1 及以前数据,全引擎统一一种并单元测试锁定)。信号层输出的是「目标组合」(每个标的的目标权重),而非「买卖指令」——把「想持有什么」与「怎么从当前仓位变过去」解耦,换手计算与执行优化才有清晰的输入(见执行算法 )。

③ 组合层:约束与优化的落点

目标组合 → 受约束的目标组合:预算约束、行业/风格暴露上限、单票上下限、换手上限、禁交易名单(停牌、涨停买/跌停卖)。这层是约束优化 的实现处;个人简版可只做「等权 TopN + 缓冲带」,但禁交易名单的处理不能省——停牌股进不了也出不去,是 A 股回测与实盘差异的稳定来源。

④ 撮合层:模拟成交的诚实原则

撮合模型从糙到诚的阶梯:

  1. 下一 bar 收盘价成交(向量化默认):最乐观,只有粗筛资格;
  2. 下一 bar 开盘价成交 + 成本函数:日频策略的务实下限——成本 = 佣金 + 印花税 + half-spread + 冲击模型(σ×√(Q/ADV),见交易成本分解 );
  3. 穿越原则的限价撮合:限价单只有当 bar 内价格穿越挂价才成交(日内高频必须);
  4. 订单簿撮合(tick 级 + L2 深度):排队位置、部分成交、撤单——微观结构研究的形态(见订单簿 )。

不可成交状态的显式建模(A 股三件套):跌停封死的卖单不成交(顺延)、涨停封死的买单不成交、停牌冻结。这三条是 A 股回测可信度的试金石——框架默认没处理的,自己写进撮合层。

⑤ 账户层:现金流与净值会计

现金、持仓、成本、保证金(有杠杆时)的账本。两个易错点:分红送转的账户处理(现金分红进现金、送转改股数与成本价——不能靠复权价隐含,见A 股数据 );日终净值 = 现金 + Σ持仓 × 收盘价,净值曲线的每一点都要能从账本重算(审计性)。杠杆/期货场景要加:保证金占用、追保线、强平逻辑(见杠杆与保证金 )。

引擎的可信度验证

自建引擎(或评估框架)的验收测试:

  1. 回归测试:同一数据集 + 同一策略,引擎任何改动前后净值曲线必须逐点一致(引擎本身的 CI,见DevOps );
  2. 解析解对照:构造有精确答案的场景(恒定权重持有指数、固定利率现金)验证账户会计无误;
  3. 偏差注入测试:故意在信号里加一行「未来函数」,引擎应产生不同结果——如果结果不变,说明你的前视防线形同虚设;
  4. 成本敏感性:成本参数从 0 扫到 3 倍,净值应平滑单调变化——跳变说明撮合层有结构性错误。

关联阅读:本篇的对立面回测偏差大全 ——引擎设计就是为了消灭它们;框架选型量化常用开源框架 ;引擎产出物的正确读法绩效指标 。