上个月帮一个汇友看EA,他做的是黄金,参数设得挺细,挂单距离用ATR动态算,回测2023年至今曲线漂亮得不行。结果一上实盘,图表直接卡死,CPU单核跑满,订单发不出去,日志里全是超时。他问我第一句话就是:回测能过,实盘为啥就瘫了?我让他把源码发过来,翻到OnTick第二十行,看见一个Sleep(500)。问题就在这。
很多刚转MT5的朋友会把MT4的习惯带过来。MT4的OnTick跑在独立线程里,Sleep一下顶多让当前tick处理慢点。但MT5的OnTick是跑在图表主线程上的,你在里面Sleep,等于把整个图表的UI刷新、鼠标响应、指标重算全部堵住。回测的时候策略测试器是模拟环境,它不渲染图表也不处理界面消息,所以Sleep看起来“没事”。实盘一挂上,行情稍微活跃点,比如欧美开盘那会儿一秒几十个tick,每个tick进来你都Sleep半秒,主线程直接排队排到天荒地老,表现就是图表白屏、EA不响应、手动平仓都点不动。
那正确的做法是什么?我当时给他改了三处。
改完之后他那个黄金EA跑了一周,图表流畅,订单响应正常。他后来跟我说,原来MT5的OnTick跟MT4的OnTick压根不是一回事。我补了一句,MT5里任何阻塞主线程的操作都要警惕,Sleep只是最明显的一个,还有FileWrite大文件、WebRequest同步请求、甚至MessageBox弹窗,放在OnTick里都是雷。回测环境不会告诉你这些,因为它根本不跑UI线程。
另外提醒一下,如果你用的是VPS,CPU核心数少,主线程被堵住的表现会更明显。我一般建议EA跑在至少2核、主频3GHz+的VPS上,同时图表别开太多,一个品种挂一个EA就够了。你要是也遇到过回测好好的、实盘一跑就卡死的情况,不妨先搜一下代码里有没有Sleep、MessageBox、WebRequest这几个关键词。你们在MT5上还踩过哪些“回测通过实盘翻车”的坑?评论区聊聊,我看看能不能帮大家定位一下。
很多刚转MT5的朋友会把MT4的习惯带过来。MT4的OnTick跑在独立线程里,Sleep一下顶多让当前tick处理慢点。但MT5的OnTick是跑在图表主线程上的,你在里面Sleep,等于把整个图表的UI刷新、鼠标响应、指标重算全部堵住。回测的时候策略测试器是模拟环境,它不渲染图表也不处理界面消息,所以Sleep看起来“没事”。实盘一挂上,行情稍微活跃点,比如欧美开盘那会儿一秒几十个tick,每个tick进来你都Sleep半秒,主线程直接排队排到天荒地老,表现就是图表白屏、EA不响应、手动平仓都点不动。
那正确的做法是什么?我当时给他改了三处。
- 首先,把Sleep从OnTick里彻底拿掉。如果业务逻辑确实需要“等一会儿再判断”,改用OnTimer配合EventSetTimer。比如你需要每5秒检查一次挂单状态,就在OnInit里写EventSetTimer(5),然后在OnTimer里做轮询,OnTick只负责接收价格和发单。
- 然后,如果是要等某个订单成交后再做下一步,不要用Sleep死等。用OnTradeTransaction事件驱动,或者把状态存到全局变量里,下次tick或下次timer再查。MT5的订单是异步的,你Sleep那几秒,订单状态可能早变了。
- 还有,如果非要在OnTick里做耗时计算,比如遍历几百根K线算指标,把它拆出去。可以用CopyBuffer先取数据,算完缓存到全局数组,OnTick里只读缓存结果。别每次tick都全量重算。
改完之后他那个黄金EA跑了一周,图表流畅,订单响应正常。他后来跟我说,原来MT5的OnTick跟MT4的OnTick压根不是一回事。我补了一句,MT5里任何阻塞主线程的操作都要警惕,Sleep只是最明显的一个,还有FileWrite大文件、WebRequest同步请求、甚至MessageBox弹窗,放在OnTick里都是雷。回测环境不会告诉你这些,因为它根本不跑UI线程。
另外提醒一下,如果你用的是VPS,CPU核心数少,主线程被堵住的表现会更明显。我一般建议EA跑在至少2核、主频3GHz+的VPS上,同时图表别开太多,一个品种挂一个EA就够了。你要是也遇到过回测好好的、实盘一跑就卡死的情况,不妨先搜一下代码里有没有Sleep、MessageBox、WebRequest这几个关键词。你们在MT5上还踩过哪些“回测通过实盘翻车”的坑?评论区聊聊,我看看能不能帮大家定位一下。
