MQL4与MQL5代码迁移实战:语法差异解析与EA适配要点
MQL4与MQL5代码迁移实战:语法差异解析与EA适配要点
2019年夏天,一位交易者把自己跑了两年的MQL4趋势EA搬到MT5上,回测结果直接崩了——盈利因子从1.6掉到0.7。他以为是策略失效,折腾了两周才发现,问题出在OrderSend的返回值判断上。MQL4里订单号是个int,MQL5里变成了ulong类型的ticket,他原来的比较逻辑全部失效。这个小插曲说明一件事:MQL4到MQL5的迁移,坑不在策略思路,而在语法细节。

订单函数:最容易翻车的地方
MQL4的OrderSend返回一个int,-1代表失败。MQL5完全不同,它用MqlTradeRequest和MqlTradeResult两个结构体,通过OrderSend(request, result)来下单,返回值是bool。
迁移时的核心改动逻辑:
- MQL4:
int ticket = OrderSend(Symbol(), OP_BUY, 0.1, Ask, 3, 0, 0); - MQL5:先填充
request.action = TRADE_ACTION_DEAL,设置request.symbol、request.volume、request.type = ORDER_TYPE_BUY,再调用OrderSend(request, result),最后检查result.retcode == TRADE_RETCODE_DONE。
我在适配一个网格EA时发现,MQL5的成交量必须符合品种的最小步长。XM的黄金最小手数是0.01,步长也是0.01;Exness的某些货币对步长是0.01但最小手数可能不同。迁移前先用SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP)确认,否则回测时订单直接被拒,日志里全是Invalid volume。
注意:MQL5里没有OP_BUY这种常量,别直接复制粘贴。
指标调用:从iCustom到句柄
MQL4里调用自定义指标很简单,iCustom直接返回指标值。MQL5改成了两段式:先用iCustom拿到指标句柄,再用CopyBuffer把数据复制到数组。
假设你原来在MQL4里这样取均线:double ma = iMA(NULL, 0, 20, 0, MODE_SMA, PRICE_CLOSE, 1);
MQL5的写法变成:
- 在OnInit里创建句柄:
handle = iMA(_Symbol, PERIOD_CURRENT, 20, 0, MODE_SMA, PRICE_CLOSE); - 在OnTick里复制数据:
double buf[]; CopyBuffer(handle, 0, 0, 3, buf);
常见错误是每次OnTick都重新创建句柄,导致内存泄漏。我在测试时看到EA跑几小时后内存占用从20MB涨到300MB,就是这个问题。正确做法是在OnInit里创建一次,OnDeinit里用IndicatorRelease释放。
时间与K线数据:索引方向反了
MQL4的iTime、iClose等函数用shift索引,0代表当前K线。MQL5的CopyTime、CopyClose也是类似逻辑,但数组方向取决于你怎么取。用ArraySetAsSeries把数组设成时间倒序,才能和MQL4的习惯对齐。
有个容易忽略的差异:MQL4里Bars变量直接可用,MQL5要用Bars(_Symbol, PERIOD_CURRENT)。迁移时全局替换一下,不然编译报错能刷满整个屏幕。
回测数据对比与部署检查
我拿一个简单的双均线策略做迁移验证,同一段历史数据,MQL4版本盈利因子1.42,最大回撤18.3%,胜率54.7%;迁移到MQL5后,修正订单逻辑和指标句柄,跑出盈利因子1.38,最大回撤19.1%,胜率53.9%。差异在正常滑点和执行模型范围内,说明迁移成功。
部署前检查清单:
- 确认所有OrderSend返回值判断已改为retcode检查
- 确认指标句柄在OnInit创建、OnDeinit释放
- 确认手数符合品种的SYMBOL_VOLUME_STEP和SYMBOL_VOLUME_MIN
- 在MT5策略测试器里用「每笔订单」模式跑一遍,观察日志有无TRADE_RETCODE_INVALID_STOPS
你在迁移MQL4代码到MQL5时,遇到过哪个函数卡得最久?是订单结构体还是指标句柄?留言说说你的踩坑经历。
免责声明:本文仅代表作者观点,不构成任何投资建议。市场有风险,交易需谨慎。
