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.
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.
The first source of confusion when reading MQL5 code as an MQL4 developer is vocabulary.
| MQL4 term | MQL5 equivalent | Notes |
|---|---|---|
| Order | Position (open) or Order (pending) or Deal (execution record) | MQL5 splits the MQL4 "order" concept into three distinct things |
| OrderSend | OrderSend (different parameters) or CTrade.Buy/Sell | Function name kept but signature changed completely |
| OrderClose | CTrade.PositionClose | Operates on position tickets, not order tickets |
| OrderType | POSITION_TYPE_BUY / SELL (for positions) or ORDER_TYPE_BUY_LIMIT etc. (for pending) | Constants renamed and split |
| OrdersTotal | PositionsTotal() and OrdersTotal() | Two separate counts now |
| OrderSelect | PositionSelectByTicket / PositionGetTicket / PositionGetInteger etc. | Selection by index, ticket, or symbol |
| iMA returns value | iMA returns handle, then CopyBuffer reads values | All indicators now use this pattern |
| iCustom returns value | iCustom returns handle, then CopyBuffer reads values | Same pattern as built-ins |
| start() | OnTick() | Renamed lifecycle function |
| init() | OnInit() | Renamed |
| deinit() | OnDeinit(const int reason) | Renamed, takes parameter |
MQL4 had one concept: the order. An order existed from placement until close. MQL5 distinguishes three things:
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.
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:
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).
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.
MQL5 supports two account types and your code may behave differently on each.
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.
When you paste MQL4 code into MetaEditor and try to compile, expect:
| Error | Cause | Fix |
|---|---|---|
'OP_BUY' - undeclared identifier | MQL4 constants removed in MQL5 | Use ORDER_TYPE_BUY or POSITION_TYPE_BUY depending on context |
'iMA' - wrong parameters count | iMA signature changed | Remove the shift parameter at the end and use CopyBuffer to read values |
'Close' - undeclared identifier | Price arrays removed | Use CopyClose or iClose |
'Ask' - undeclared identifier | Predefined Ask/Bid removed | Use SymbolInfoDouble(_Symbol, SYMBOL_ASK) or _Ask after declaring access |
'OrderTicket' - undeclared identifier | Order selection API completely changed | Use PositionGetTicket, PositionGetInteger, etc. |
For a non-trivial MQL4 EA, do not attempt a line-by-line port. Use this approach instead:
Not everything is different. Many things port cleanly:
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.
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.
Usually no. MQL5 is faster than MQL4 in raw execution. The migration friction is conceptual, not performance.
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.
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.