Migrating an Expert Advisor from MQL4 to MQL5 is not a simple recompilation. The two platforms differ fundamentally in order handling, time series access, and pre-defined variables. This guide focuses on core migration patterns for advanced developers.
1. Order vs Position Model
MQL4 uses
OrderSelect(), OrderSend(), and a flat order pool. MQL5 separates pending orders (COrder) and market positions (CPositionInfo). A direct mapping is impossible; logic must be restructured.Example: Open a buy market order
MQL4:
``
cpp
int ticket = OrderSend(Symbol(), OP_BUY, lot, Ask, 3, stopLoss, takeProfit, "EA", magic, 0, clrNONE);
if(ticket < 0) Print("Error: ", GetLastError());
`
MQL5:
`cpp
CTrade trade;
trade.SetExpertMagicNumber(magic);
trade.SetDeviationInPoints(3);
if(!trade.Buy(lot, Symbol(), 0, stopLoss, takeProfit))
Print("Error: ", trade.ResultRetcode());
`
The CTrade class handles slippage and order filling modes. For market orders, avoid using SymbolInfoDouble(Symbol(), SYMBOL_ASK) directly – the Buy() method automatically uses current Ask.
2. Time and Tick Functions
TimeCurrent() returns datetime in both, but MQL5 requires TimeTradeServer() for server time. iTime() for historical bars: MQL4 uses shift from current, MQL5 uses series index. Use CopyTime() for flexibility.
3. Pre-defined Variables Removal
Bid, Ask, Point, Digits are not available in MQL5. Replace with:
`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 Replacement Pattern
For complex orders, use COrderSend with CRequest. Example sending a limit order:
`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("Send failed: ", sender.ResultRetcode());
`
5. Backtest Migration Tips
MT4 backtest MODEL_EVERY_TICK corresponds to EVERY_TICK (based on real ticks) in MT5. Use OnTester() for optimization pass processing. The TesterStatistics() function differs: e.g., TRADE_PROFIT instead of GROSS_PROFIT`.Reference: MQL5 Documentation – "Migration from MQL4 to MQL5" (mql5.com)