可复现性:一次回测的 Provenance(输入快照、哈希、成本模型)

量化团队最常见的“内耗对话”之一是:

“同一个策略,我这里能跑出收益,你那里怎么就不行?”
“我昨天回测是盈利的,今天怎么回撤很大?”

如果系统无法回答“这次运行的关键输入到底是什么”,讨论就会退化为记忆与猜测。
结论先行:EasyQuant 把“可复现”做成平台能力——每次 backtest/paper 运行都生成一份 Provenance(运行快照),让结果有出处、差异可对比、复盘可追溯。


一、可复现不是“再跑一遍”,而是“能对齐同一套事实”

很多人把可复现理解成:把同一段代码再跑一次,得到同一条曲线。
但在真实系统里,你会遇到大量“看不见的变量”:

  • 你用的是草稿还是激活版本?是否回退模板?
  • bars 的区间/时区是否一致?是否有缺口?
  • 交易时段过滤是否打开?不同市场会话规则是否影响数据数量?
  • 手续费/滑点/税率口径是否变更?
  • 数据源是实时回填、还是演示数据/模拟数据?

因此,可复现的核心不是“能跑”,而是:
把这些关键变量以平台可核对的方式记录下来,让任何人都能复用同一套输入,再去讨论策略本身。


二、Provenance 要解决的三个问题

一份好的运行快照,至少要回答三个问题:

1)这次运行“用的是什么策略”?

  • 策略实例 ID(instanceId)
  • 激活版本 ID(versionId)与版本内容摘要(模板 key、DSL、参数)
  • 风控画像(riskProfile)与执行配置(如果是 paper)

2)这次运行“用的是什么数据”?

  • 市场(marketId)、标的列表(codes)或 Universe 绑定信息
  • 时间窗口(fromTs/toTs)与时区口径
  • bars/ticks 的数据源(回填/实时/演示/模拟)
  • 数据完整性摘要(例如 bars 条数、缺口统计、最后更新时间)

3)这次运行“用的是什么成本与假设”?

回测里最容易被忽略、但最容易导致“同策略不同结果”的变量就是成本模型:

  • 手续费(commission)
  • 滑点(slippage)
  • 税费(tax)
  • 撮合假设(成交价取 open/close/vwap?是否允许同 bar 成交?)

这些不记录,讨论收益与回撤基本都是空谈。


三、为什么要“哈希”:让差异对比变成 10 秒钟的事

Provenance 的关键不只是“把 JSON 存下来”,而是要能快速判断两次运行是否在同一套输入上。

一个实用方法是:对关键输入做稳定序列化后计算哈希(hash),例如:

  • strategy_config_hash:版本 + 参数 + 风控画像
  • data_window_hash:marketId + codes + from/to + session/filter 配置
  • cost_model_hash:commission/slippage/tax + 撮合假设

这样你可以在 UI 上直接看到:

  • “两次运行为什么不同?”
    • 如果 data_window_hash 不同:先别吵策略,先对齐数据区间与口径
    • 如果 cost_model_hash 不同:收益差异很可能来自成本口径
    • 如果 strategy_config_hash 不同:版本/参数根本不是同一个策略

一句话:哈希把“对齐事实”从 30 分钟沟通变成 10 秒钟确认。


四、成本模型:为什么它决定了“可复现”的含金量?

在很多团队里,成本模型经常被“默认值”带过。
但在更接近真实交易时,成本模型的微小差异会显著影响结论:

  • 高频/短线策略:滑点和手续费可能直接把盈利变成亏损
  • 换手高的策略:税费与成交价假设影响非常大
  • 多标的组合:不同标的成本结构差异会改变资金曲线形态

所以在 EasyQuant 的口径里:
成本模型属于策略运行输入的一部分,必须进入 provenance,且应该可被对比、可被审计。


五、团队如何使用 Provenance:三种常见工作流

工作流 1:策略评审(Review)

评审不是看一条曲线,而是看“这条曲线来自什么输入”:

  • 版本是否正确(是否激活版本?)
  • 数据窗口是否合理(是否缺 bars?是否只覆盖单边行情?)
  • 成本口径是否符合团队标准

工作流 2:复盘(Post-mortem)

当出现异常回撤或成交行为不符合预期时:

  • 先对比 provenance 哈希,确认是否“同一套输入”
  • 再按 03 的 Blocking Reasons 路径定位“没发生”的原因

工作流 3:回归(Regression)

当你升级指标实现/DSL 引擎/执行链路:

  • 选择一组典型策略与时间窗,固定 provenance 输入
  • 新旧版本跑同一输入,差异就是可控的回归结果

这会把平台演进从“改完祈祷”变成“可验证的工程变更”。


六、你可以立刻做的一个验收

用同一策略做两次回测,只改一个变量,看系统能不能把差异讲清楚:

  1. 第一次:默认成本模型跑一遍
  2. 第二次:只提高滑点(或手续费)跑一遍
  3. 对比两次运行的 provenance:
    • cost_model_hash 变化
    • 其他哈希保持一致
    • 收益/回撤差异符合预期

如果这条验收能稳定通过,说明“可复现性”已经不是口号,而是可交付能力。


结语:没有 provenance 的回测,谈不上“团队协作”

当你的策略从个人研究走向团队交付,可复现性会成为硬门槛:
你需要的不是“再跑一次”,而是“任何人都能在同一套输入上复现同一结论”。

下一篇(05)我们会进入数据层:行情接入与入库(tick + K 线回填 + 演示数据降级),因为 provenance 记录的是输入,而数据管线决定输入是否可信