2026年八月23日 · 研究

即使每个时间戳都正确,你的回测仍有时钟问题

即使每个时间戳都正确,你的回测仍有时钟问题

回测中最危险的时序错误,即使经过完美的时间戳审计也可能漏网。两个事件都可能标记为 10:00:00.000,但它们实际发生的先后顺序,仍可能是模拟器猜出来的。

只要策略的反应对象不止是已完成的 K 线,这一点就很重要:报价更新、成交、资金费率通知、交易所状态变更,或是自己的订单确认。时间戳告诉你事件被标记在何时,却未必能说明策略何时能够据此采取行动。

事件排序会带来什么变化?

设想一个策略:当最优卖价跌破 $100.00 时买入。同一毫秒内,行情源记录了一条卖价更新至 $99.99 的消息,也记录了一笔 $99.99 的成交。如果回测先处理成交,再处理报价,策略就会看到新卖价并提交订单。如果先处理报价,也可能没问题,前提是该事件当时确实已经可用。但如果这笔成交在订单到达前就消耗了显示出来的流动性,那么以 $99.99 成交就是虚构的。

仅按时间戳对记录排序,会让模拟器自行决定时间相同事件的处理顺序。文件顺序、交易对顺序或数据库查询计划,都可能意外变成执行规则。即便底层数据没有变化,权益曲线也可能随之改变。

有一种直观的办法可以看出这种排序有多随意:按交易对名称而不是到达顺序排列同一时刻的事件。这样一来,多资产策略可能仅仅因为一个代码排在另一个之前,表现就有所不同。

回测应该保留哪些时钟?

行情数据和订单处理通常涉及几个不同的时间。保留数据源提供的字段,并准确说明每个字段的含义。对许多行情源来说,交易所时间戳和本地接收时间戳都很有用;但它们都不能代表所有参与者所见的统一真相。

时钟记录内容单凭它无法证明什么
交易所事件时间交易场所标记的事件发生时间其他行情源或你的进程观察到事件的顺序
接收时间采集器收到消息的时间策略完成处理消息的时间
决策时间代码评估信号的时间报价价格当时仍然可用
订单到达时间交易场所可以处理订单的时间不能单凭此时间证明成交,除非撮合规则和流动性支持成交

如果历史数据没有接收时间,就明确说明你的假设。回测可以按顺序处理交易所事件,并假设从决策到订单到达需要固定的 5 ms 延迟。这是一个模型,并非还原出来的历史。如果同一交易所时间戳下没有序列号,你采用的事件排序规则同样属于假设。

如何建模时间相同的事件?

首先,保留数据源提供的序列号。与时间戳相比,序列号能更可靠地确定同一行情流内的顺序,不过不同频道或产品的序列号可能各自独立。

然后,明确写出模拟器的处理规则。对于每个事件,都要决定它是否能更新策略掌握的信息、改变可用流动性、触发订单或确认订单。这些操作各不相同;把它们统统简化成“处理一行”,就会让不可能发生的成交混进结果。

  1. 只应用在策略决策时间之前已经到达的市场信息。
  2. 生成订单,然后将时间推进到模型设定的订单到达交易场所时间。
  3. 订单到达后,只允许按该订单类型的成交假设,与符合条件的流动性进行撮合。
  4. 记录每笔模拟成交所用的输入、事件顺序和延迟。

对于基于 K 线的策略,这套机制可能比研究问题所需的更复杂。如果信号使用已完成的 1-minute K 线,订单按保守的成本模型在下一根 K 线开盘时成交,那么亚毫秒级的事件排序可能不会改变研究结论。关键是,时序细节要与回测所作的结论相匹配。

没有到达时间数据,我还能相信回测吗?

仍然可以使用,但要清楚标明它的适用边界。如果策略交易速度较慢、风险限制较宽,几毫秒的差异可能无关紧要。如果策略追逐转瞬即逝的报价、争抢队列位置,或依赖跨交易所的领先滞后信号,那么缺少到达时间可能会直接影响结果。

批评者指出,追求精确的事件时序可能造成虚假的精确感,这一点没错。历史行情源并不完整,时钟会漂移,交易所时间戳也无法揭示网络传输中的每一跳。即使模拟器提供纳秒级字段,成交假设仍可能很粗略。

因此,与其声称结果确定,不如测试它对假设的敏感度:采用合理的事件排序规则和订单延迟进行重放,然后比较交易次数、成交价格,以及哪些信号经得住检验。如果结果依赖于数据无法确定的事件顺序,就应在研究报告中说明这种依赖。时钟不完美,回测仍然有用;关键是如实说明它实际掌握了哪些时间信息。

事件驱动回测执行建模市场数据策略研究
← 全部文章