Sign up with our partner broker and get free XAU/USD signals. JOIN US
LIVE MT5 BUILD 5830 LAST REV 2026-05-23
SESSION -- UTC --:--
SESSIONS
SYDNEY22:00–07:00 UTC
TOKYO00:00–09:00 UTC
LONDON07:00–16:00 UTC
NEW YORK12:00–21:00 UTC

Migrating from MQL4 to MQL5: what actually changes

MQL5 is not just MQL4 with a bigger version number. The two languages share syntax but differ fundamentally in how they handle orders, indicators, and program structure. Porting an EA is rarely a copy-paste exercise.

PUBLISHED 2026-05-24 READING TIME 11 MIN MT5 BUILD 5830 CATEGORY TOOLS
Reality: MQL5 was released in 2010 but adoption was slow because MQL4 EAs did not run on MT5 without modification. MetaQuotes froze MT4 development years ago. If you still have an MQL4 EA that you rely on, porting it is now a matter of when, not if.

1. The fundamental shift

MQL4 was designed around a single-position, single-symbol mental model. Each function (OrderSend, OrderClose, OrderModify) operated on individual tickets in a global pool. You could iterate through orders with OrdersTotal() and OrderSelect().

MQL5 reorganises everything. The terminology changed. The order pool became three pools (orders, positions, deals). Indicator access changed from direct value queries to handle-based buffer reads. The result is a more disciplined architecture but also a steeper learning curve.

2. Terminology mapping

The first source of confusion when reading MQL5 code as an MQL4 developer is vocabulary.

MQL4 termMQL5 equivalentNotes
OrderPosition (open) or Order (pending) or Deal (execution record)MQL5 splits the MQL4 "order" concept into three distinct things
OrderSendOrderSend (different parameters) or CTrade.Buy/SellFunction name kept but signature changed completely
OrderCloseCTrade.PositionCloseOperates on position tickets, not order tickets
OrderTypePOSITION_TYPE_BUY / SELL (for positions) or ORDER_TYPE_BUY_LIMIT etc. (for pending)Constants renamed and split
OrdersTotalPositionsTotal() and OrdersTotal()Two separate counts now
OrderSelectPositionSelectByTicket / PositionGetTicket / PositionGetInteger etc.Selection by index, ticket, or symbol
iMA returns valueiMA returns handle, then CopyBuffer reads valuesAll indicators now use this pattern
iCustom returns valueiCustom returns handle, then CopyBuffer reads valuesSame pattern as built-ins
start()OnTick()Renamed lifecycle function
init()OnInit()Renamed
deinit()OnDeinit(const int reason)Renamed, takes parameter

3. The order, position, deal trinity

MQL4 had one concept: the order. An order existed from placement until close. MQL5 distinguishes three things:

  • Order. An instruction to do something (open, close, modify). Orders are short-lived: market orders execute immediately, pending orders sit until triggered or cancelled. After execution, an order disappears from the orders pool.
  • Position. The result of an executed order. A position is open until it is closed. Each symbol can have one position (netting account) or multiple positions (hedging account).
  • Deal. The execution record. Every buy or sell that completes is logged as a deal. Deals are immutable historical records used for reporting and the trade journal.

When your MQL4 code says "close order 12345", the MQL5 equivalent is "close position 12345". The instruction to do the closing is an order in MQL5, and the act of execution generates a deal. Three concepts where MQL4 had one.

4. The indicator handle pattern

In MQL4, you could write:

// MQL4
double ma = iMA(NULL, 0, 20, 0, MODE_EMA, PRICE_CLOSE, 0);
if(Close[0] > ma) Print("Above MA");

In MQL5, you cannot. The same logic looks like:

// MQL5
int handle = iMA(_Symbol, _Period, 20, 0, MODE_EMA, PRICE_CLOSE);
double buf[1];
CopyBuffer(handle, 0, 0, 1, buf);
double ma = buf[0];

double price[1];
CopyClose(_Symbol, _Period, 0, 1, price);
if(price[0] > ma) Print("Above MA");

Two important consequences:

  • Indicator handles are created once (in OnInit usually) and used repeatedly. Creating a handle on every tick is wasteful and may exhaust resources.
  • CopyBuffer fills an array in reverse-chronological order by default: index 0 is the current bar, index 1 is the previous bar, and so on. The array indexing matches MQL4 conventions but the data source is different.

5. The price array problem

MQL4 exposed global arrays: Close[], Open[], High[], Low[], Volume[], Time[]. You could read prices anywhere in your code.

MQL5 removed these globals. To read prices you call CopyClose, CopyOpen, etc., into an array you declare. This forces you to think about how many bars you need and to handle the possibility that data is not yet available.

If you have a lot of MQL4 code referencing Close[0] directly, you face a choice: rewrite each reference using CopyClose, or use the compatibility wrapper functions (iClose(_Symbol, _Period, 0) still exists in MQL5 with similar semantics).

6. The standard trade library

One thing that genuinely makes MQL5 easier than MQL4 once you adapt is the standard library. Including <Trade/Trade.mqh> gives you the CTrade class, which collapses the verbose OrderSend request structure into one-line method calls.

MQL4 order send:

// MQL4
int ticket = OrderSend(Symbol(), OP_BUY, 0.01, Ask, 3, Ask-200*Point, Ask+400*Point, "comment", MagicNumber, 0, clrBlue);

MQL5 with CTrade:

// MQL5
CTrade trade;
trade.SetExpertMagicNumber(MagicNumber);
trade.Buy(0.01, _Symbol, 0, Ask-200*_Point, Ask+400*_Point, "comment");

Cleaner once you know it. Verbose without it: the raw OrderSend in MQL5 requires you to populate an MqlTradeRequest struct and check an MqlTradeResult struct manually.

7. Netting vs hedging accounts

MQL5 supports two account types and your code may behave differently on each.

  • Netting. One position per symbol. Sending a buy order when a sell position exists reduces the sell. Sending a sell into a net flat results in a new short position. Common in US-regulated brokers and in equities.
  • Hedging. Multiple positions per symbol. Buy and sell orders create independent positions that can coexist. Common in EU and offshore FX brokers.

If your MQL4 EA assumed hedging (the only MT4 mode), you may need to add explicit account-type checks in MQL5 and adjust logic that opens opposing positions.

8. Compile errors you will see

When you paste MQL4 code into MetaEditor and try to compile, expect:

ErrorCauseFix
'OP_BUY' - undeclared identifierMQL4 constants removed in MQL5Use ORDER_TYPE_BUY or POSITION_TYPE_BUY depending on context
'iMA' - wrong parameters countiMA signature changedRemove the shift parameter at the end and use CopyBuffer to read values
'Close' - undeclared identifierPrice arrays removedUse CopyClose or iClose
'Ask' - undeclared identifierPredefined Ask/Bid removedUse SymbolInfoDouble(_Symbol, SYMBOL_ASK) or _Ask after declaring access
'OrderTicket' - undeclared identifierOrder selection API completely changedUse PositionGetTicket, PositionGetInteger, etc.

9. Practical migration strategy

For a non-trivial MQL4 EA, do not attempt a line-by-line port. Use this approach instead:

  1. Read the MQL4 source and write down the strategy logic in plain language. Entry rules, exit rules, position sizing, risk management. Forget the implementation; capture the intent.
  2. Set up a fresh MQL5 EA template in MetaEditor. Use the Expert Advisor wizard. You get clean OnInit, OnTick, OnDeinit stubs.
  3. Reimplement the strategy in MQL5 idioms from scratch. Use CTrade for orders. Use handles and CopyBuffer for indicators. Use SymbolInfoDouble for prices.
  4. Compare backtests between the original MQL4 EA on MT4 and the new MQL5 EA on MT5 using the same date range and the same broker symbol. Expect small differences from data quality and execution model changes; large differences indicate a logic bug.
  5. Iterate until results converge. Then move forward in MQL5 only.

10. Things that just work

Not everything is different. Many things port cleanly:

  • Variable declarations and types (with minor adjustments)
  • If/else, loops, switch statements
  • Math functions (MathAbs, MathMax, MathSqrt, etc.)
  • String manipulation (StringFormat, StringConcatenate, StringFind)
  • File I/O (FileOpen, FileWrite, FileClose), though paths and flags differ slightly
  • Time functions (TimeCurrent, TimeLocal, TimeGMT)

FAQ

Can I run my MQL4 EA on MT5 without changes?

No. The compiled .ex4 file is not compatible with MT5. The source code .mq4 will not compile in MetaEditor for MT5. You must port the code.

Is there an automated MQL4 to MQL5 converter?

There are tools that claim to do this, with limited success. They handle syntax-level changes but cannot resolve semantic differences like the order/position/deal split. Expect any output to need manual review and testing.

Will my MQL5 EA be slower than my MQL4 version?

Usually no. MQL5 is faster than MQL4 in raw execution. The migration friction is conceptual, not performance.

Does MQL5 support OOP (object-oriented programming)?

Yes. MQL5 has full class support with inheritance, polymorphism, virtual functions, and templates. MQL4 had limited OOP added late in its life. If you want to structure your code into classes, MQL5 is the better environment.

Should I learn MQL5 or use MetaEditor's MQL4 mode?

MQL4 mode in MetaEditor is for maintaining legacy MT4 code only. New development should target MQL5 on MT5. MetaQuotes ended feature development of MT4 in 2015 and stopped issuing new MT4 licenses to brokers in 2018; only security and compatibility updates have been released since (most recently Build 1440 in February 2025). MT4 still works and existing brokers continue to support it, but it is on a maintenance track with no roadmap for new capabilities.