EA回测陷阱盘点:前视偏差与点差建模的常见错误
EA回测陷阱盘点:前视偏差与点差建模的常见错误
同一个EA,同一个品种,同一段历史数据,两次回测结果差了将近一倍——这种事你遇到过吗?

我上个月帮一个做黄金的朋友排查策略,他的MQL5 EA在策略测试器里跑出来盈利因子1.62,实盘跑了三周却是0.91。不是滑点问题,不是服务器延迟,问题出在回测本身。他用的测试数据是「每根K线四个价格」模式,也就是只用OHLC四个点来模拟价格路径,而他的策略依赖日内15分钟级别的止损触发。这种模式下,测试器根本看不到K线内部的真实波动顺序。
回测陷阱这东西,踩过一次就够记一辈子。下面挑几个高频问题拆开讲。
开盘价成交,真的能成交吗
最典型的前视偏差来自「下一根K线开盘价成交」这个设定。逻辑上没问题,信号在当根K线收盘确认,下一根开盘进场。但很多人忽略了一件事:测试器里的开盘价是理想化的。
假设你在MQL5里写了这样一段逻辑:
- 信号条件:收盘价突破前20根K线高点
- 执行逻辑:在下一根K线开盘价买入
- 止损设置:入场价减去1.5倍ATR
看起来没毛病。但测试器在处理「下一根开盘价」时,如果数据源本身是分钟级聚合的,这个开盘价可能已经是跳空后的价格。你回测里买在2000.00,实盘可能开盘直接跳到2000.80。黄金在亚盘转欧盘的时段,这种跳空很常见。历史统计表明,伦敦开盘前后15分钟的波动率通常是亚洲时段的2到3倍,跳空概率显著上升。
解决办法不是改逻辑,而是改数据精度。在MT5策略测试器里,把「模型」选项从「每根K线开盘价」换成「每笔订单」或至少「1分钟OHLC」。代价是回测速度慢很多,但结果可信度完全不一样。我在测试一个欧元兑美元的日内策略时,用「每根K线开盘价」跑出来最大回撤8.3%,换成「1分钟OHLC」后回撤变成14.7%。差距来自哪里?就是那些被忽略的K线内部波动。
注意:MT5的「每笔订单」模式需要真实的tick数据,很多经纪商的服务器并不提供完整的历史tick。如果测试器提示「tick数据不足」,回测结果会自动降级到1分钟模式,但你未必会注意到这个提示。
点差建模:固定点差是最大的谎言
策略测试器默认用固定点差,这几乎是所有回测失真的根源。
固定点差意味着什么?意味着你认为黄金在任何时候的点差都是30美分,欧元兑美元永远是1.2个点。但真实情况是:非农数据公布后的前30秒,黄金点差可能从30美分瞬间拉到1.5美元甚至更宽。你的止损单在回测里以30美分点差成交,实盘可能因为点差扩大被扫出去,然后价格又回到你的方向。
MT5允许自定义点差,有两种做法。一种是在策略测试器的「设置」标签里手动输入固定点差,但这对波动率敏感的策略没意义。另一种是用自定义品种功能,导入带真实点差的历史tick数据。具体步骤:
- 在MT5里打开「品种」窗口,右键选择「创建自定义品种」
- 基于你交易的品种复制一份,比如XAUUSD.custom
- 在「设置」里把「点差」改为「浮动」,并导入tick数据文件
- 回到策略测试器,选择这个自定义品种进行回测
这个过程有点繁琐,但值得做。我自己的经验是,一个剥头皮策略在固定点差下盈利因子1.4,换成浮动点差后直接掉到0.7。不是策略不行,是固定点差给了它虚假的利润空间。
常见错误:有些人用「当前点差」来近似历史点差,这完全不可靠。凌晨三点的点差和晚上九点的点差能差三倍,而你的策略可能大部分交易都发生在流动性差的时段。
指标重绘:你以为的信号,其实还没出现
前视偏差的另一个重灾区是指标计算方式。很多自定义指标在代码里用了当前K线的收盘价来计算,但回测时测试器是按K线逐根推进的。如果你在指标里写了类似 iClose(_Symbol, PERIOD_CURRENT, 0) 这样的调用,在K线还没走完的时候,这个值是不稳定的。
举个例子。假设你写了一个均线交叉策略,用当前K线的收盘价计算快线。在回测里,测试器会在每根K线结束时认为收盘价已经确定,然后触发信号。但实盘中,K线还在形成的时候,收盘价一直在变。可能K线走到一半时快线已经上穿慢线,你手动进场了,结果K线收盘时价格回落,交叉信号消失。回测里没有这笔交易,实盘里你亏了。
判断指标是否重绘,有个简单方法:在策略测试器里开启「可视化模式」,观察信号出现的时机。如果信号出现在K线中间而不是收盘后,那就是重绘。修正方式是用 iClose(_Symbol, PERIOD_CURRENT, 1) 来引用上一根K线的收盘价,确保信号只在K线完全走完后才确认。
经纪商差异:XM和Exness的品种命名不是小事
回测时用的品种名称和实盘不一致,会导致EA直接报错或者交易到错误的品种上。XM的黄金代码通常是GOLD,Exness用的是XAUUSDm或XAUUSD。别小看这个后缀,Exness的m后缀代表微型账户,合约大小和标准账户不一样。
具体差异:
- XM标准账户黄金合约大小通常是100盎司,点值计算基于此
- Exness标准账户黄金合约大小也是100盎司,但微型账户是1盎司,点值差100倍
- 欧元兑美元方面,XM的点差在正常时段约1.6个点,Exness标准账户约1.0个点,但Exness的佣金结构不同
如果你在XM的模拟账户上回测,然后直接部署到Exness的微型账户,手数计算会完全错位。EA里如果写了固定手数0.1手,在XM上是10盎司,在Exness微型账户上只有0.1盎司。盈利和亏损都缩小到十分之一,但止损距离没变,结果就是频繁被扫止损。
部署前必做:在EA代码里用 SymbolInfoDouble(_Symbol, SYMBOL_TRADE_CONTRACT_SIZE) 动态获取合约大小,不要硬编码。同时检查 SymbolInfoInteger(_Symbol, SYMBOL_DIGITS) 获取小数位数,XM和Exness对某些品种的小数位处理不同。
回测通过就上实盘?先跑模拟
回测结果再好,也只是历史数据上的拟合。我见过太多人回测盈利因子2.0就直接上实盘,结果第一周就遇到连续亏损。回测和实盘之间还有一层:模拟盘。
模拟盘的意义不是验证策略方向,而是验证执行层面。点差是不是和回测一致?订单成交速度如何?有没有滑点?这些在回测里看不到。我的习惯是,任何EA回测通过后,至少在模拟盘跑两周,对比模拟盘的盈利因子和回测的偏差。如果偏差超过30%,说明回测模型有问题,需要回去检查点差设置和数据精度。
新手最容易忽略的环节,其实是回测数据的来源。MT5默认从经纪商服务器下载历史数据,但不同经纪商的数据质量差异很大。有些经纪商的tick数据只保留最近几个月,更早的数据是聚合过的。你用这种数据跑回测,等于在沙地上盖房子。花点时间从可靠的数据源导入tick数据,比优化策略参数重要得多。
你在回测时遇到过信号闪烁或者点差对不上的情况吗?留言说说你的排查过程。
免责声明:本文仅代表作者观点,不构成任何投资建议。市场有风险,交易需谨慎。
