组合回测内核:复用信号引擎与成本模型

当策略从“单标的回测”走向“多标的组合运行”,很多系统会出现两类问题:

  • 回测结果看起来不错,但无法解释每笔交易为什么发生
  • 多标的时间线合并后,状态与成本口径变得混乱,导致不可复现

结论先行:EasyQuant 的组合回测(portfolio backtest)强调两点:

  1. 复用同一套信号引擎(DSL → 规则 编译后的策略对象),保证策略逻辑口径一致
  2. 用统一的成本模型与运行快照(provenance) 固定假设,让结果可对比、可复盘

一、组合回测到底在解决什么问题?

单标的回测回答的是:这套规则在一个标的上是否有效。
组合回测回答的是:当策略面对一个 Universe(多标的集合)时,整体权益曲线与风险如何?

组合回测的产品价值主要来自:

  • 更接近真实研究流程:策略往往不会只交易一只标的
  • 更真实的风险结构:集中度、相关性、回撤形态都与单标的不同
  • 更真实的执行约束:资金与仓位会被多个标的共享

二、为什么必须复用信号引擎?

很多团队会在回测里“另写一套信号逻辑”,理由是快。
但这会直接破坏交付能力:

  • 回测与 paper 行为不一致(同策略不同结果)
  • 指标实现漂移(同名指标在不同模块口径不同)
  • 排障困难:你很难判断问题在策略还是在回测实现

因此 EasyQuant 的原则是:
策略逻辑只写一次——用 DSL 编译成可执行的规则/指标图,回测与 paper 都复用。

这会让 03(可解释)与 04(可复现)在回测里同样成立。


三、组合回测的三个核心工程难点(也是产品解释点)

1)时间线合并(Timeline Merge)

多标的 bars 的时间戳并不总能完全对齐:缺口、停牌、数据源差异都会存在。
组合回测需要定义“时间线口径”:

  • 是以全体标的时间戳并集为主,还是以基准时间线为主?
  • 缺 bars 时如何处理?跳过、补齐、还是冻结状态?

这直接影响:

  • 信号触发频率
  • 持仓与资金更新节奏
  • 最大回撤与收益的形态

因此,时间线口径必须被记录进 provenance,避免不可复现。

2)状态管理(Per-code State + Portfolio State)

组合回测至少有两类状态:

  • 标的级状态:每个 code 的持仓、入场价、止损线、冷却期等
  • 组合级状态:总资金、总敞口、风控阈值、净值曲线

如果状态混在一起,策略会出现“互相污染”的现象:
A 标的的交易影响 B 标的的信号与仓位,这是研究里最难排查的 bug 之一。

3)成本模型(Cost Model)

组合回测更容易暴露成本模型的重要性:

  • 多标的换手会放大手续费与滑点影响
  • 集中度变化会改变税费与成交假设的影响

因此成本模型必须统一入口、可配置、可记录(见 04)。


四、回测结果为什么要“可解释”?

很多回测系统只输出一条权益曲线。
但平台交付需要的是“证据链”:

  • 权益/回撤:整体表现
  • 成交明细:每笔交易的时间、标的、方向、数量、价格
  • K 线买卖点标记:信号触发点是否符合预期

当组合回测交易多个标的时,图表层必须允许按标的切换展示,否则会产生“把多标的成交画在一条 K 线上”的误读。


五、一个验收:同一策略在单标的与组合回测中行为一致

用一个很实用的验收,判断组合回测是否真的“复用信号引擎”:

  1. 选择一个策略与时间窗
  2. 对其中一只标的做单标的回测
  3. 用同一策略对同一时间窗做组合回测(包含该标的)
  4. 对比该标的在两种回测中的:
    • 信号触发点(买卖点时间)
    • 成交方向与大致价格区间

如果一致性很好,说明策略逻辑口径被真正复用;
如果差异巨大,通常是时间线/会话过滤/成本模型口径未对齐。


结语:组合回测不是“多跑几只”,而是平台能力的试金石

组合回测会把平台的关键能力全部拉出来验收:

  • 数据口径是否一致(05/06)
  • 信号引擎是否可复用(07/08)
  • 成本模型是否统一(04)
  • 结果是否可解释(03)

下一篇(11)我们会讲可观测性:Prometheus/Grafana 在量化平台里到底该监控什么,以及如何把“阻塞原因/拒单原因/链路健康”变成可告警对象。