bqb18wzv的知识库

为什么同一个策略,在不同数据源上的回测结果差异巨大?

由bqb18wzv创建,最终由bqb18wzv 被浏览 2 用户

在量化研究中,很多人都遇到过类似的情况:

同一套策略逻辑,参数完全一致,只是换了一个行情数据源,回测结果却出现了明显差异。有时是收益曲线变得更平滑,有时是胜率下降,有时甚至连交易次数都对不上。

这类问题经常会被简单地归因为“数据质量不一样”。但在实际研究中,真正展开对比之后会发现,差异并不总是来自明显的脏数据,而是隐藏在一些更基础、也更容易被忽略的地方。

这篇文章尝试从研究视角,讨论几个在回测中经常影响结果、却不太容易被第一时间注意到的数据层细节:字段定义、时间戳处理,以及复权逻辑。

回测并不是“策略 + 数据”的简单拼接

在刚开始做回测时,很多人会下意识地把它理解为一件很直接的事情:

给策略一份历史行情,看它在过去赚不赚钱。

但在实践中,更接近事实的说法是:

策略并不是运行在“原始行情”上,而是运行在一套被解释、被加工过的数据之上。

从交易所的撮合信息,到研究环境中可直接使用的 K 线或 Tick 数据,中间往往经历了多层处理。不同数据源在这些处理环节中的选择,并不总是完全一致。

策略代码本身没有变,但策略“看到的市场”,可能已经发生了变化。

字段定义:看起来一样,其实并不完全一样

最容易被忽视的,是字段本身的定义差异。

以最常见的 OHLC 为例,在不同数据源中:

  • open 可能是该周期内第一笔成交价,也可能是上一根 K 线的收盘价
  • close 有的取最后一笔成交,有的使用加权成交价
  • volume 有时表示成交量,有时是成交额,有时只统计主动成交

这些差异在日线级别策略中未必明显,但在一些场景下会被明显放大,例如:

  • 高频或准高频策略
  • 使用影线、价差、成交量变化作为信号
  • 依赖“第一笔 / 最后一笔”价格判断进出场的策略

在这类策略中,回测结果的差异往往并不是“数据错了”,而是策略对字段语义的隐含假设,与数据源的实际定义并不完全一致。

时间戳:一秒的偏差,可能就是一笔交易

当回测中出现“交易次数对不上”的情况时,时间戳往往是一个被低估的因素。

在不同数据源中,时间戳的处理方式可能存在多种差异:

  • 使用撮合完成时间,还是行情广播时间
  • 使用交易所本地时间,还是统一换算后的时间
  • K 线的时间标记在周期开始,还是周期结束

当策略逻辑涉及以下条件时,这些差异会变得非常敏感:

  • 在固定时间点触发信号
  • 使用跨周期数据(例如用 1 分钟信号去交易 Tick)
  • 对开盘、收盘、换日点高度敏感的策略

在回测中,看似“同一根 K 线”,在不同数据源下,可能对应的是略有错位的市场片段。这种错位在单次交易中并不显著,但在长期累计后,往往会反映为收益曲线的分歧。

复权逻辑:价格连续性的“人为选择”

复权问题并不只存在于股票市场。

在任何存在分红、换月、合约切换或制度调整的品种中,都绕不开“价格是否连续”的处理方式。而即便在股票市场,不同数据源对复权的处理方式也可能存在差异,例如:

  • 前复权与后复权
  • 是否计入现金分红
  • 复权因子的精度与更新时间

如果策略直接基于价格水平、均线位置或历史极值来判断信号,复权方式的不同,会直接改变信号出现的时点。

更容易被忽略的一点是: 有些数据源在展示层面使用的是复权价格,但在底层字段中,策略计算使用的却是未复权数据。

这种“表面一致、内部不一致”的情况,往往也是回测结果难以复现的原因之一。

差异并不等于“谁对谁错”

当回测结果不一致时,很多人的第一反应是去寻找“更准的数据”。

但从研究角度看,更值得追问的问题可能是:

  • 策略假设的是逐笔成交,还是聚合后的价格?
  • 它假设时间是连续的,还是存在边界效应?
  • 它假设价格序列是平滑可比的,还是允许结构性跳变?

不同数据源,只是以不同方式对这些问题给出了答案。

如果一套策略对这些假设高度敏感,那么结果的差异本身,其实也是一种重要的研究信号。

一点来自回测对比中的经验

在实际研究中,与其纠结“哪个数据源更好”,不如尝试做两件事:

  • 明确策略对数据细节的依赖程度
  • 在关键字段上做最小化对齐,而不是直接比较最终收益

当一套策略在不同数据解释下表现差异巨大时,问题往往不在数据本身,而在策略对市场结构的假设是否足够稳健。

回测结果的差异,并不是量化研究中的意外,而是研究过程的一部分。 理解这些差异,往往比得到一条看起来更漂亮的收益曲线,更有价值。

如果你正在经历“同一策略,不同结果”的困惑,也许可以从这些数据层的基础选择开始,重新审视一次自己的策略假设。

{link}