Summary: 本文面向高阶EA开发者,系统讲解从MQL4迁移到MQL5时必须重构的订单模型、预定义变量替换、回测差异及代码转换模式,并附带可运行的迁移示例。




将EA从MQL4迁移至MQL5并非简单的重新编译。两大平台在订单处理、时间序列访问和预定义变量方面存在根本性差异。本文聚焦于进阶开发者的核心迁移模式。

1. 订单 vs 持仓模型
MQL4使用OrderSelect()OrderSend()和扁平订单池。MQL5将挂单(COrder)和市价持仓(CPositionInfo)分离。无法直接映射,需重构逻辑。

示例:开市价多单
MQL4:
``cpp
int ticket = OrderSend(Symbol(), OP_BUY, lot, Ask, 3, stopLoss, takeProfit, "EA", magic, 0, clrNONE);
if(ticket < 0) Print("错误:", GetLastError());
`
MQL5:
`cpp
CTrade trade;
trade.SetExpertMagicNumber(magic);
trade.SetDeviationInPoints(3);
if(!trade.Buy(lot, Symbol(), 0, stopLoss, takeProfit))
Print("错误:", trade.ResultRetcode());
`
CTrade类处理滑点和订单填充模式。对于市价单,避免直接使用SymbolInfoDouble(Symbol(), SYMBOL_ASK)——Buy()方法会自动使用当前卖价。

2. 时间和Tick函数
两者
TimeCurrent()均返回datetime,但MQL5需用TimeTradeServer()获取服务器时间。历史K线iTime():MQL4基于偏移量,MQL5基于序列索引。推荐使用CopyTime()

3. 预定义变量的移除
MQL5中不再提供
BidAskPointDigits。替换方式:
`cpp
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
`

4. OrderSend的替代模式
对于复杂订单,使用
COrderSend配合CRequest。示例发送限价单:
`cpp
CRequest request;
request.action = TRADE_ACTION_PENDING;
request.type = ORDER_TYPE_BUY_LIMIT;
request.volume = lot;
request.price = limitPrice;
request.sl = stopLoss;
request.tp = takeProfit;
request.deviation = 5;
COrderSend sender;
if(!sender.Send(request))
Print("发送失败:", sender.ResultRetcode());
`

5. 回测迁移要点
MT4回测
MODEL_EVERY_TICK对应MT5的EVERY_TICK(基于真实Tick)。使用OnTester()处理优化回合数据。TesterStatistics()函数有差异:例如用TRADE_PROFIT替代GROSS_PROFIT`。

参考来源: MQL5官方文档 – “从MQL4迁移到MQL5”(mql5.com)