All posts · MQL4 · MQL5 · Expert Advisors

Converting MQL4 to MQL5: 7 Things to Remember

Porting an EA or indicator from MT4 to MT5? The seven MQL4 to MQL5 changes that matter most, from trade requests and positions to indicator handles.

· 4 min read · Updated

If you've been building in MQL4 and are thinking of porting your scripts, EAs or indicators to MQL5, you're not alone. MetaQuotes has been steering everyone toward MetaTrader 5, and there are good reasons to follow.

Why move to MT5 at all

The biggest one is the MT5 Strategy Tester. Compared with MT4, it gives you:

  • Optimization spread across all your CPU cores (and optionally the MQL5 Cloud Network), where MT4 optimizes on a single core
  • Multi-currency testing, so one EA can trade and be tested on several symbols at once
  • An "every tick based on real ticks" mode that replays your broker's actual tick history
  • Richer reports, plus custom optimization criteria through OnTester()

If you want to validate strategies properly rather than throwing darts at EURUSD, that alone makes MQL5 worth learning.

The other reason: MT5 is the platform MetaQuotes is pushing. Its own site only offers MetaTrader 5, and MT4 is now mainly available through brokers that still support it. If you've built useful tools in MQL4, now is a good time to migrate.

Converting isn't plug-and-play, though. MQL5 changes the structures, the events and, above all, the trading logic. Here are the seven differences that matter most, fast. (For the bigger picture first, see MQL4 vs MQL5: the differences that matter.)

1. Trading logic: requests and results

MQL4: one call

MQL4
OrderSend(Symbol(), OP_BUY, 1.0, Ask, 3, 0, 0, "Buy Order", 0, 0, clrGreen);

MQL5: a request structure

MQL5
MqlTradeRequest request;
MqlTradeResult  result;
ZeroMemory(request);
ZeroMemory(result);

request.action    = TRADE_ACTION_DEAL;
request.symbol    = _Symbol;
request.volume    = 1.0;
request.type      = ORDER_TYPE_BUY;
request.price     = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
request.deviation = 10;      // MQL4's "slippage", in points
request.magic     = 123456;
request.comment   = "Buy Order";

if(!OrderSend(request, result))
   PrintFormat("OrderSend failed: retcode %u (%s)", result.retcode, result.comment);

If this feels like overkill, you're not alone. In return you get precise control and detailed error reporting through result.retcode and result.comment.

Two things to watch. First, the request also has a filling mode (type_filling), and brokers support different ones. A mode the symbol doesn't allow is rejected with retcode 10030, "Unsupported filling mode". Second, the standard library's CTrade class (#include <Trade\Trade.mqh>) wraps all of this, and trade.SetTypeFillingBySymbol(_Symbol) picks a filling mode the symbol supports. For most EAs, CTrade is the simpler route.

2. Order management: MT5 tracks positions, not just orders

MQL4 treats every trade as an order. MT5 splits that into three things:

  • Orders: your request ("I want to buy")
  • Deals: what actually got executed
  • Positions: your current exposure ("I'm long 1 lot of EURUSD")

So the way you read open trades has to change.

MQL4

MQL4
for(int i = 0; i < OrdersTotal(); i++)
{
   if(OrderSelect(i, SELECT_BY_POS))
   {
      if(OrderType() == OP_BUY)
      {
         // Your logic
      }
   }
}

MQL5

MQL5
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
   ulong ticket = PositionGetTicket(i); // also selects the position
   if(ticket == 0) continue;
   if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
   {
      // Your logic
   }
}

Watch out: OrdersTotal() still exists in MQL5, but there it only counts pending orders. An MQL4 loop ported as-is never finds your open trades.

MT5 accounts can also be netting (one position per symbol, where an opposite order reduces or closes it) or hedging (several positions per symbol, like MT4). Check ACCOUNT_MARGIN_MODE if your logic depends on it.

3. Indicator buffers: where most conversions break

If you only read one section, read this one.

  1. MQL5 indicators don't return values directly.
  2. You create a handle and copy buffers.
  3. You have to understand ArraySetAsSeries(), or you'll read the wrong candle.

MQL4

MQL4
double value = iRSI(NULL, 0, 14, PRICE_CLOSE, 1);

Simple. Done.

MQL5

MQL5
int rsiHandle = INVALID_HANDLE;

int OnInit()
{
   rsiHandle = iRSI(_Symbol, _Period, 14, PRICE_CLOSE); // create once
   if(rsiHandle == INVALID_HANDLE)
      return INIT_FAILED;
   return INIT_SUCCEEDED;
}

void OnTick()
{
   double rsi[];
   ArraySetAsSeries(rsi, true);           // index 0 = newest, like MQL4
   if(CopyBuffer(rsiHandle, 0, 0, 3, rsi) < 3)
      return;                             // data not ready yet
   double current  = rsi[0];              // current (forming) candle
   double previous = rsi[1];              // last closed candle
}

Without ArraySetAsSeries(rsi, true), the three copied values run oldest-first:

  • rsi[0] is the oldest of the three (two candles ago)
  • rsi[2] is the current candle

With it, indexing works like MQL4:

  • rsi[0] = current candle
  • rsi[1] = previous candle
  • rsi[2] = two candles ago

This one line saves hours of head-scratching. Call it on the array before reading any values from it.

4. Custom indicator buffers

For custom indicators, buffer setup changes slightly too.

MQL4

MQL4
double buffer[];
SetIndexBuffer(0, buffer);

MQL5

MQL5
double buffer[];
SetIndexBuffer(0, buffer, INDICATOR_DATA);

And in MQL5 you style plots with the PlotIndexSet*() functions instead of SetIndexStyle():

MQL5
PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_LINE);
PlotIndexSetInteger(0, PLOT_LINE_COLOR, clrBlue);

More boilerplate, more control. Our guide to coding custom indicators in MQL5 walks through a complete one.

5. Price and time series

The predefined Close[], Time[] and friends don't exist in MQL5.

MQL4

MQL4
double price = Close[1];
datetime time = Time[1];

MQL5

MQL5
double   close[];
datetime time[];
ArraySetAsSeries(close, true);
ArraySetAsSeries(time, true);
CopyClose(_Symbol, _Period, 0, 5, close);
CopyTime(_Symbol, _Period, 0, 5, time);
// close[1] and time[1] are now the last closed bar, as in MQL4

For a single value, iClose(_Symbol, _Period, 1) and iTime(_Symbol, _Period, 1) also work in MQL5. If you copy arrays, though, forgetting ArraySetAsSeries() gives you backwards arrays, and your logic fails silently.

6. Timeframes and symbols

MQL4

MQL4
string symbol = Symbol();
int    tf     = Period();

MQL5

MQL5
string          symbol = _Symbol;
ENUM_TIMEFRAMES tf     = _Period;

MQL5 types timeframes as ENUM_TIMEFRAMES and adds ones MT4 doesn't have (M2, M3, H2, H6, H12 and more). The values differ too: in MQL4 PERIOD_H1 is 60 (minutes), in MQL5 it's 16385. Never do arithmetic on timeframe constants. Use PeriodSeconds(tf) when you need a bar's length.

7. Testing and optimization

Once the code compiles, use what the MT5 tester gives you:

  • Test multi-symbol logic in a single run.
  • Write a custom optimization criterion in OnTester() instead of optimizing for raw profit.
  • Optimize in parallel across all cores.

Then compare the converted bot's trades with the MQL4 version's in the Strategy Tester. Small differences are normal because the two testers use different price data, but missing or doubled trades usually point at one of the changes above.

Conversion cheat sheet

MQL4 MQL5
OrderSend(...) OrderSend(request, result) or CTrade
OrdersTotal() + OrderSelect() for open trades PositionsTotal() + PositionGetTicket()
OrderSelect() on history HistorySelect() + HistoryDealGetTicket()
OrderOpenPrice() PositionGetDouble(POSITION_PRICE_OPEN)
Ask, Bid SymbolInfoDouble(_Symbol, SYMBOL_ASK) / SYMBOL_BID
iRSI(..., shift) iRSI() handle + CopyBuffer() + ArraySetAsSeries()
Close[i], Time[i] CopyClose() / CopyTime(), or iClose() / iTime()
Point, Digits _Point, _Digits

Rather not port it by hand? Our MQL4 to MQL5 converter converts an EA or indicator with AI and reports every part it had to change or couldn't convert. Compile and test its output like any port.

Converted bots need the same care as new ones: run them on a demo account before trusting them with real money.

Build a bot from your idea

Describe your trading idea and the AI writes MT4 or MT5 code for you to review and test, with a plain-English explanation and setup steps. Your first bot is free.

More from the blog