MQL4 to MQL5 Migration: A Sensible Information from the Trenches – Different – 6 February 2026


MQL4 to MQL5 Migration: A Sensible Information from the Trenches

Introduction

For those who’re studying this, you most likely have a working MQL4 EA or indicator that you have to port to MQL5. Perhaps your dealer is phasing out MT4, possibly you need entry to MQL5’s higher backtesting, or possibly a shopper is paying you to transform their legacy code.

No matter your purpose, I have been there. I’ve migrated dozens of EAs and indicators, and I can let you know: it is not a easy find-and-replace job. Nevertheless it’s additionally not as scary because it appears to be like.

This information offers you the sensible information I want I had after I began.

The Massive Image: What Truly Modified?

Earlier than diving into code, perceive the architectural shift:

MQL4: Easy and Direct

// Need the RSI? Simply name it. double rsi = iRSI(NULL, 0, 14, PRICE_CLOSE, 0); // Wish to open a commerce? One perform. int ticket = OrderSend(Image(), OP_BUY, 0.1, Ask, 3, 0, 0);

MQL5: Deal with-Primarily based and Object-Oriented

// RSI requires a deal with (create as soon as, use many occasions)
int rsi_handle = iRSI(_Symbol, _Period, 14, PRICE_CLOSE);
double rsi_buffer();
ArraySetAsSeries(rsi_buffer, true);
CopyBuffer(rsi_handle, 0, 0, 1, rsi_buffer);
double rsi = rsi_buffer(0);

// Buying and selling makes use of the CTrade class
#embrace 
CTrade commerce;
commerce.Purchase(0.1, _Symbol);

Why the change? Efficiency. MQL5’s deal with system lets the terminal cache indicator calculations. In MQL4, iRSI() recalculates each time you name it. In MQL5, you calculate as soon as and skim from reminiscence.

Step 1: The Entry Factors

That is the straightforward half. Discover and exchange:

MQL4 MQL5 Notes
init() onInit() Should return INIT_SUCCEEDED or INIT_FAILED
deinit() OnDeinit(const int purpose) Now receives a purpose code
begin() OnTick() For EAs
begin() OnCalculate(…) For indicators (completely different signature!)

Frequent mistake: Forgetting that OnInit() should return an int. Your MQL4 init() that returned 0 must return INIT_SUCCEEDED.

int OnInit() { // Setup code… if(something_failed) return(INIT_FAILED); return(INIT_SUCCEEDED); }

Step 2: Add the Commerce Libraries

On the prime of your file, add:

#embrace 
#embrace 
#embrace 

Then declare world situations:

CTrade commerce; CPositionInfo place; CSymbolInfo symbol_info;

In OnInit():

commerce.SetExpertMagicNumber(MagicNumber);
commerce.SetDeviationInPoints(10);
symbol_info.Title(_Symbol);

Step 3: Changing Order Features

That is the place most individuals wrestle. MQL5 separates orders (pending) from positions (open trades).

Opening Trades

MQL4:

int ticket = OrderSend(Image(), OP_BUY, 0.1, Ask, 3, sl, tp, “Remark”, Magic); if(ticket < 0) Print("Error: ", GetLastError());

MQL5:

if(!commerce.Purchase(0.1, _Symbol, 0, sl, tp, "Remark"))
{
   Print("Error: ", commerce.ResultRetcodeDescription());
}

Word: In MQL5, passing 0 as worth means “use present market worth” — the category handles Ask/Bid robotically.

Closing Trades

MQL4:

OrderClose(ticket, OrderLots(), Bid, 3);

MQL5:

commerce.PositionClose(ticket);

Checking Open Positions

MQL4:

for(int i = OrdersTotal() – 1; i >= 0; i–) { if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if(OrderSymbol() == Image() && OrderMagicNumber() == Magic) { // Discovered our place } } }

MQL5:

for(int i = PositionsTotal() - 1; i >= 0; i--)
{
   if(place.SelectByIndex(i))
   {
      if(place.Image() == _Symbol && place.Magic() == Magic)
      {
         // Discovered our place
      }
   }
}

Step 4: Changing Indicators

That is the most important psychological shift. Create handles as soon as, learn values many occasions.

Instance: Transferring Common

MQL4:

double ma = iMA(NULL, 0, 20, 0, MODE_SMA, PRICE_CLOSE, 0); double ma_prev = iMA(NULL, 0, 20, 0, MODE_SMA, PRICE_CLOSE, 1);

MQL5:

// Declare at world stage
int ma_handle;
double ma_buffer();

// In OnInit()
ma_handle = iMA(_Symbol, _Period, 20, 0, MODE_SMA, PRICE_CLOSE);
if(ma_handle == INVALID_HANDLE)
{
   Print("Error creating MA deal with");
   return(INIT_FAILED);
}
ArraySetAsSeries(ma_buffer, true);

// In OnTick()
if(CopyBuffer(ma_handle, 0, 0, 2, ma_buffer) < 2)
   return; // Not sufficient information
   
double ma = ma_buffer(0);
double ma_prev = ma_buffer(1);

// In OnDeinit() - IMPORTANT!
IndicatorRelease(ma_handle);

Why ArraySetAsSeries()? MQL5 arrays index from oldest to latest by default. Setting as sequence flips it so index 0 is the present bar (like MQL4).

Step 5: Value Information

MQL4:

double shut = Shut(0); double excessive = Excessive(1); datetime time = Time(0);

MQL5:

double shut = iClose(_Symbol, _Period, 0);
double excessive = iHigh(_Symbol, _Period, 1);
datetime time = iTime(_Symbol, _Period, 0);

Or utilizing arrays:

double shut(), excessive(); ArraySetAsSeries(shut, true); ArraySetAsSeries(excessive, true); CopyClose(_Symbol, _Period, 0, 10, shut); CopyHigh(_Symbol, _Period, 0, 10, excessive); // Now shut(0) is present bar, shut(1) is earlier, and so forth.

Step 6: Account and Image Information

MQL4:

double steadiness = AccountBalance();
double fairness = AccountEquity();
double level = Level;
int digits = Digits;
double bid = Bid;
double ask = Ask;

MQL5:

double steadiness = AccountInfoDouble(ACCOUNT_BALANCE); double fairness = AccountInfoDouble(ACCOUNT_EQUITY); double level = SymbolInfoDouble(_Symbol, SYMBOL_POINT); int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS); double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); // Or utilizing CSymbolInfo class: symbol_info.RefreshRates(); double bid = symbol_info.Bid(); double ask = symbol_info.Ask();

Frequent Pitfalls (Be taught from My Errors)

1. Forgetting to Launch Handles

Reminiscence leak alert! All the time launch indicator handles in OnDeinit():

void OnDeinit(const int purpose)
{
   IndicatorRelease(ma_handle);
   IndicatorRelease(rsi_handle);
   // and so forth.
}

2. Arrays Not Set as Collection

Your code appears to be like proper however offers improper values? Examine ArraySetAsSeries(). MQL5 arrays are “as sequence” = false by default.

3. Bid/Ask Not Updating

symbol_info.Bid() returns cached values. Name symbol_info.RefreshRates() first, or use SymbolInfoDouble() instantly.

4. Place vs Order Confusion

  • OrdersTotal() = pending orders solely
  • PositionsTotal() = open positions solely

In MQL4, OrdersTotal() included each. In MQL5, they’re separate.

5. ENUM Modifications

Some enums modified names:

  • OP_BUY → ORDER_TYPE_BUY (however commerce.Purchase() handles this)
  • MODE_SMA → Similar identify, however test the worth matches
  • PRICE_CLOSE → Similar identify

Fast Reference Card

Activity MQL4 MQL5
Present bid Bid SymbolInfoDouble(_Symbol, SYMBOL_BID)
Present ask Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK)
Level measurement Level SymbolInfoDouble(_Symbol, SYMBOL_POINT)
Digits Digits SymbolInfoInteger(_Symbol, SYMBOL_DIGITS)
Present shut Shut(0) iClose(_Symbol, _Period, 0)
Bar rely Bars Bars(_Symbol, _Period)
Open purchase OrderSend(…, OP_BUY, …) commerce.Purchase(…)
Shut place OrderClose(ticket, …) commerce.PositionClose(ticket)
Depend positions OrdersTotal() PositionsTotal()
Get MA worth iMA(…, shift) CopyBuffer(ma_handle, …)

Migration Guidelines

  • ☐ Rename init() → OnInit() (return INIT_SUCCEEDED)
  • ☐ Rename deinit() → OnDeinit(const int purpose)
  • ☐ Rename begin() → OnTick() (EA) or OnCalculate() (indicator)
  • ☐ Add #embrace and mates
  • ☐ Create CTrade commerce; world variable
  • ☐ Set magic quantity in OnInit(): commerce.SetExpertMagicNumber(Magic)
  • ☐ Convert all OrderSend() → commerce.Purchase()/Promote()
  • ☐ Convert all OrderClose() → commerce.PositionClose()
  • ☐ Convert order loops to place loops
  • ☐ Convert indicators to handle-based system
  • ☐ Add IndicatorRelease() calls in OnDeinit()
  • ☐ Substitute Bid/Ask with SymbolInfoDouble()
  • ☐ Substitute Shut()/Excessive()/and so forth. with iClose()/iHigh()/and so forth.
  • ☐ Check totally in Technique Tester

Ultimate Ideas

MQL5 migration is not nearly making code compile — it is about understanding the brand new structure. When you internalize the handle-based indicator system and the position-based order administration, all the pieces clicks.

The payoff is value it: sooner backtesting, cleaner code, higher debugging instruments, and entry to the rising MQL5 market.

Need assistance migrating your EA? Examine my GitHub portfolio for examples: https://github.com/jimmer89/mql5-portfolio

© 2026 Jaume Sancho. Free to make use of and share with attribution.



Supply hyperlink

Leave a Comment

Discover more from Education for All

Subscribe now to keep reading and get access to the full archive.

Continue reading