说出来不怕各位笑话,上周我那个EURUSD的网格EA,MT5自带策略测试器里跑得漂漂亮亮,年化28%,最大回撤11%,结果切到demo跑了一周,账面浮亏直接比回测预期多了45美元。45美元听着不多,但换算成点差损耗和滑点成本,这EA的夏普比率直接从1.8掉到1.1,完全两个物种。我一开始以为是VPS网络延迟问题,后来把tick数据导出来逐笔比对,才发现问题出在回测环境对市场深度的模拟压根没考虑真实盘口厚度。
先说最坑的一个点:MT5默认的“每个tick基于真实tick”模式,听起来高大上,但它用的是历史报价的买卖价差,并不包含你实际下单时可能吃到的滑点分布。我那个EA是挂限价单的,回测里每次都能在预设价位成交,但实盘里价格穿过那个价位时,流动性往往已经被吃掉几个pip了。后来我做了个粗暴的校准:把回测里所有成交价加一个动态偏移量,偏移值用过去两周demo盘的滑点标准差来拟合,大概是0.8个pip,然后再跑一遍,盈亏曲线才勉强贴近实盘。
具体校准流程我分成四步,每一步都有个我踩过的坑。
做完这四步,我的回测结果和demo盘的日度盈亏偏差从45美元缩小到大概9美元,剩下的差额我归因于周五尾盘和新闻时段的极端流动性缺失,这部分我选择在EA里加个时间过滤器,避开格林威治时间12:00-13:00的非农/CPI发布窗口。
还有个细节,如果你用的是MT4而不是MT5,滑点校准会更麻烦,因为MT4的回测引擎是基于控制点模式,没有真实tick数据,只能通过调整“点差”参数来近似。我建议MT4用户直接改用MT5跑回测,哪怕EA代码得重写一遍,数据颗粒度带来的优势远超迁移成本。
最后问一句,你们在跑黄金或英镑类EA时,有没有遇到过回测和实盘偏差特别离谱的情况?我最近在琢磨怎么把订单簿深度衰减模型塞进自定义的tick生成器里,有搞过的朋友麻烦指点下方向,感激不尽。
先说最坑的一个点:MT5默认的“每个tick基于真实tick”模式,听起来高大上,但它用的是历史报价的买卖价差,并不包含你实际下单时可能吃到的滑点分布。我那个EA是挂限价单的,回测里每次都能在预设价位成交,但实盘里价格穿过那个价位时,流动性往往已经被吃掉几个pip了。后来我做了个粗暴的校准:把回测里所有成交价加一个动态偏移量,偏移值用过去两周demo盘的滑点标准差来拟合,大概是0.8个pip,然后再跑一遍,盈亏曲线才勉强贴近实盘。
具体校准流程我分成四步,每一步都有个我踩过的坑。
- 第一步,先把EA里所有涉及止损止盈和挂单的价位,全部改成用Ask/Bid动态计算,不要用Close价。我一开始偷懒用Close,回测和实盘偏差最大的就是止损触发逻辑,因为Close价在回测里是tick最后一口价,实盘里你止损单触发用的是对手价。
- 第二步,收集至少500笔实盘demo成交记录,按订单类型(市价单/挂单)分别统计滑点分布,不要混在一起算均值。我吃过这个亏,市价单平均滑点0.3pip,挂单平均1.2pip,混着算出来0.7,结果市价单那部分还是被高估了。
- 第三步,在MT5的策略测试器里,把“延迟”参数从0改成80-120毫秒,模拟VPS到broker的物理延迟。这个参数很多人忽略,但如果你EA里有条件判断后马上发单的逻辑,这点延迟足以让成交价偏离好几个tick。
- 第四步,也是最容易被忽略的——检查你的EA是否在回测里用了未来函数,比如iHigh/iLow在同一根K线内调用且不shift。我那个EA就藏着个bug,用了shift=0的iHigh来判断突破,回测里等于提前知道最高价,实盘自然崩。
做完这四步,我的回测结果和demo盘的日度盈亏偏差从45美元缩小到大概9美元,剩下的差额我归因于周五尾盘和新闻时段的极端流动性缺失,这部分我选择在EA里加个时间过滤器,避开格林威治时间12:00-13:00的非农/CPI发布窗口。
还有个细节,如果你用的是MT4而不是MT5,滑点校准会更麻烦,因为MT4的回测引擎是基于控制点模式,没有真实tick数据,只能通过调整“点差”参数来近似。我建议MT4用户直接改用MT5跑回测,哪怕EA代码得重写一遍,数据颗粒度带来的优势远超迁移成本。
最后问一句,你们在跑黄金或英镑类EA时,有没有遇到过回测和实盘偏差特别离谱的情况?我最近在琢磨怎么把订单簿深度衰减模型塞进自定义的tick生成器里,有搞过的朋友麻烦指点下方向,感激不尽。
