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中不再提供`Bid`、`Ask`、`Point`、`Digits`。替换方式:
```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)