All posts · MQL4 · MQL5

MQL4 vs MQL5: The Differences That Matter for Your Code

MQL4 and MQL5 look alike but work differently. How trading, events, indicator handles and price data differ between MetaTrader 4 and MetaTrader 5 code.

· 4 min read · Updated

MQL4 and MQL5 are the programming languages of MetaTrader 4 and MetaTrader 5. You use them to write Expert Advisors (trading bots), custom indicators and scripts. Both have C++-like syntax, so code in one looks familiar in the other. Underneath, they handle data and orders very differently.

The difference that trips up programmers most is how you get data, especially indicator values and price history. In MQL4 you ask for a value and get it back. MQL5 splits that into steps, and code written the MQL4 way can compile and still read the wrong numbers.

The key differences

1. Programming style

  • MQL4 code is usually procedural, written like C. Classes have been supported since build 600, but most MQL4 code and examples don't use them.
  • MQL5 is built around object-oriented code. The standard library gives you classes such as CTrade, CPositionInfo and CSymbolInfo, and most modern MQL5 code uses them.

2. Order execution

  • MQL4 sends a trade with one call to OrderSend(), passing every detail as an argument.
  • MQL5 fills in a trade request structure (MqlTradeRequest), sends it, and reads the outcome from a result structure (MqlTradeResult). It also separates orders, deals and positions, which changes how you check for open trades.

3. Events

Both languages have OnInit(), OnDeinit(), OnTick(), OnTimer() and OnChartEvent(). MQL5 adds trade events, OnTrade() and OnTradeTransaction(), which tell your EA when an order, deal or position changes. It also adds OnBookEvent() for market depth and extra Strategy Tester events for optimization.

4. Indicator values and price data

This is the most important difference. MQL4 returns indicator values directly from a function call. MQL5 gives you a handle to an indicator and you copy values out of its buffers.

MQL4: direct access

In MQL4, you call iMA() and get the moving average value for the bar you ask for:

MQL4
double ma_value;

void OnTick()
{
   ma_value = iMA(NULL, 0, 14, 0, MODE_SMA, PRICE_CLOSE, 0);
   Print("MA value: ", ma_value);
}

The arguments, in order:

  1. NULL: the chart's symbol (for example EURUSD)
  2. 0: the chart's timeframe
  3. 14: the moving average period
  4. 0: no horizontal shift of the line
  5. MODE_SMA: simple moving average
  6. PRICE_CLOSE: calculated on closing prices
  7. 0: the bar to read, where 0 is the current bar

There's no indicator state to manage. You ask for a value and get it.

MQL5: handles and buffers

In MQL5, iMA() doesn't return a value. It creates the indicator once and returns a handle, an ID you use to read its values later with CopyBuffer():

MQL5
int    handle = INVALID_HANDLE;
double ma_value[];

int OnInit()
{
   handle = iMA(_Symbol, _Period, 14, 0, MODE_SMA, PRICE_CLOSE);
   if(handle == INVALID_HANDLE)
      return INIT_FAILED;
   return INIT_SUCCEEDED;
}

void OnTick()
{
   if(CopyBuffer(handle, 0, 0, 1, ma_value) > 0)
      Print("MA value: ", ma_value[0]);
}

iMA() takes the same settings as in MQL4 (symbol, timeframe, period, shift, method, price), minus the bar to read. Which bar you get is decided later, by CopyBuffer().

How CopyBuffer() works

MQL5
CopyBuffer(handle, buffer_index, start_pos, count, array);
  • handle: the indicator to read from, as returned by iMA().
  • buffer_index: which of the indicator's lines to read. A moving average has one line, buffer 0. Indicators like MACD have several (main line, signal line).
  • start_pos: the bar to start from, where 0 is the current bar and 1 the last closed bar.
  • count: how many values to copy.
  • array: where the values go.

It returns the number of values copied, or -1 if the data isn't ready yet (common right after the EA starts). Always check it.

What happens behind the scenes:

  1. iMA() sets the indicator up once. The terminal calculates it and keeps it updated as new prices arrive.
  2. CopyBuffer() copies already-calculated values from the indicator's buffer into your array.
  3. Calculation and reading are separate steps. That's more code than MQL4, but your EA no longer recalculates the indicator itself.

Price history: iClose() vs CopyRates()

In MQL4, you read the last closed bar's close directly:

MQL4
double last_close = iClose(NULL, 0, 1);

MQL5 has iClose() as well, but when you need whole bars, the MQL5 way is CopyRates(), which fills an array of MqlRates structures with open, high, low, close, time and volume:

MQL5
MqlRates rates[];
if(CopyRates(_Symbol, _Period, 1, 1, rates) == 1)
{
   double last_close = rates[0].close; // bar 1, the last closed bar
}

Note the start position of 1. Starting at 0 would give you the current bar, which is still forming.

Why MQL5 works this way

  1. The terminal does the calculating. Indicators run separately from your EA's code, and the EA just copies finished values.
  2. Indicators with several lines. You read each buffer on its own, for example a MACD's main and signal lines.
  3. Several timeframes. Each handle is tied to one symbol and timeframe. Create one handle per timeframe in OnInit() and read each one cheaply with CopyBuffer(), rather than recalculating anything per tick.
  4. Custom indicators. Your own indicators plug into the same handle-and-buffer model through iCustom().

The cost is more code and new ways to get it wrong, such as reading arrays in the wrong order or using data before it's ready. If you're moving an existing bot across, our guide to converting MQL4 to MQL5 covers the changes one by one, and MT4 vs MT5 for trading bots covers which platform to build for.

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