Introduction
If you’ve built or purchased Expert Advisors (EAs) and indicators for MetaTrader 4, you know the platform is reliable but limited. MetaTrader 5 offers superior backtesting (multi-threaded, tick-level), 21 timeframes, more order types (market, limit, stop), and a built-in economic calendar. The catch: MQL4 code does not run on MT5. This guide walks you through the MT4 to MT5 conversion process, covering syntax changes, order functions, and indicator handling. By the end, you’ll be able to migrate your own EA migration projects with confidence.
Prerequisites
Before starting, ensure you have:
- MetaTrader 5 installed (free from your broker or the MetaQuotes website).
- MetaEditor 5 (comes with MT5).
- The original MQL4 source code (.mq4 files) for your EAs and indicators. Compiled .ex4 files cannot be converted.
- A demo account with an MT5 broker (to test the converted code).
- Basic familiarity with the MetaEditor interface and MQL language concepts.
Step-by-Step Instructions
Step 1: Create a New MQL5 Project
Open MetaEditor 5 (press F4 in MT5 or launch from the Start menu). Go to File > New > Expert Advisor (or Indicator). Give it the same name as your MT4 file. This creates a skeleton file with the correct MQL5 structure.
Step 2: Copy Code Structure
Open your original .mq4 file alongside the new .mq5 file. Copy the #property directives, global variables, and input parameters. Note that MQL5 uses slightly different property names:
#property indicator_chart_window(same)#property indicator_buffers(same)#property indicator_plots(MQL5 only, replacesindicator_separate_windowin some cases)- For EAs,
#property versionis optional in MQL5 but recommended.
Step 3: Convert Order Functions (The Biggest Change)
This is where most of the work lies. MQL4 uses a single set of order functions (OrderSend, OrderSelect, etc.) while MQL5 uses a position-based model with separate trade classes. Here’s a conversion table:
| MQL4 Function | MQL5 Replacement | Notes |
|---|---|---|
| OrderSend() | CTrade::PositionOpen() or OrderSend() (deprecated) | Use the CTrade class; avoid the legacy OrderSend() function. |
| OrderSelect() | PositionSelect() or HistorySelect() | Positions and orders are separate in MQL5. |
| OrderModify() | CTrade::PositionModify() or OrderModify() (for pending orders) | Modify stop loss/take profit on positions; modify price on pending orders. |
| OrderClose() | CTrade::PositionClose() | Specify the position ticket. |
| OrdersTotal() | PositionsTotal() | Returns number of open positions. |
| OrderTicket() | PositionGetTicket() | Use with a loop to iterate positions. |
Example conversion: In MQL4, you might have:
int ticket = OrderSend(Symbol(), OP_BUY, 0.1, Ask, 3, 0, 0, "My EA", 0, 0, Green);
In MQL5, use the CTrade class:
#include <Trade\Trade.mqh>
CTrade trade;
double price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
if(trade.Buy(0.1, _Symbol, price, 0, 0, "My EA"))
Print("Buy order placed, ticket: ", trade.ResultOrder());
Step 4: Convert Indicator Buffers and Plots
MQL5 requires explicit buffer arrays and plot indices. In MQL4, you declare buffer arrays and use SetIndexBuffer(). In MQL5, the same function exists but you must also set PlotIndexSetInteger() for colors and styles. Example:
MQL4:
double Buffer1[];
SetIndexBuffer(0, Buffer1);
SetIndexStyle(0, DRAW_LINE);
MQL5:
double Buffer1[];
SetIndexBuffer(0, Buffer1, INDICATOR_DATA);
PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_LINE);
Also, MQL5 uses #property indicator_plots to define the number of plot lines (distinct visual series), separate from buffer count.
Step 5: Handle Time and Bar Indexing
MQL5 uses CopyRates() and CopyClose() instead of iClose() series functions. For example:
iClose(Symbol(), PERIOD_H1, 1)becomesCopyClose(Symbol(), PERIOD_H1, 1, 1, buffer)then readbuffer[0].iTime()becomesCopyTime().iHigh()becomesCopyHigh().
Note that MQL5 bar indexing starts at 0 (current forming bar) just like MQL4, but CopyRates() returns data from newest to oldest by default.
Step 6: Test in Strategy Tester
After converting, compile the code (F7 in MetaEditor). Fix any errors. Then open the MT5 Strategy Tester (Ctrl+R), select your EA, choose a symbol and timeframe, and run a single backtest. Check the Journal tab for errors and the Results tab for trade history. Compare with your MT4 results to verify consistency.
Tips and Best Practices from Experience
- Start with a simple EA first. If you have multiple EAs, convert the simplest one to learn the patterns.
- Use the same variable names where possible to minimize confusion. MQL5 is case-sensitive; MQL4 is not.
- Leverage the Trade class. The CTrade class handles slippage, magic number, and comment automatically. It’s more reliable than raw
OrderSend()in MQL5. - Check the MQL5 Reference in MetaEditor (F1) for function prototypes. The built-in help is excellent.
- Convert indicators first if your EA uses custom indicators. Custom indicator calls change from
iCustom()(MQL4) toCopyBuffer()(MQL5). - Use #include for libraries. MQL5 supports include files; move common functions (like money management) to a separate .mqh file.
Common Mistakes and Troubleshooting
Mistake 1: Forgetting to Include the Trade Library
If you get “‘trade’ – undeclared identifier”, you forgot #include <Trade\Trade.mqh> at the top of your EA.
Mistake 2: Using MQL4 Order Functions Directly
MQL5 still has OrderSend() but it’s deprecated. It may work for simple cases but fails with multiple positions. Always use the CTrade class.
Mistake 3: Incorrect Bar Indexing in Indicators
In MQL5, the OnCalculate() function receives rates_total and prev_calculated. The first call has prev_calculated = 0. Make sure you handle the initial calculation correctly. A common fix:
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
if(prev_calculated == 0)
{
// Initial calculation
ArrayInitialize(Buffer1, EMPTY_VALUE);
}
// ... rest of calculation
}
Mistake 4: Not Updating SymbolInfo Calls
MQL4 uses MarketInfo(); MQL5 uses SymbolInfoDouble() and SymbolInfoInteger(). Convert all MarketInfo(Symbol(), MODE_SPREAD) to SymbolInfoInteger(_Symbol, SYMBOL_SPREAD).
Mistake 5: Ignoring Time Conversions
In MQL5, TimeCurrent() returns server time; TimeTradeServer() is also available. For bar times, use CopyTime() rather than assuming iTime() works.
Summary and Next Steps
You’ve learned the core differences between MQL4 and MQL5, converted order functions, adapted indicator buffers, and tested your migrated code. The key takeaway: MT4 to MT5 conversion is systematic, not magical. Focus on the order model (position vs. order), the trade class, and the new time/series functions.
Next steps:
- Convert a second, more complex EA to solidify your skills.
- Explore MT5-specific features like multi-threaded backtesting and hedging mode.
- Join the MQL5 community forum for additional support.
- Consider using the built-in MT4 to MT5 Converter tool in MetaEditor (Tools > Convert MQL4 to MQL5) as a starting point, but always review the output manually.
With practice, you’ll be able to migrate any MQL4 to MQL5 project in a few hours.
Frequently Asked Questions
Can I run MT4 EAs directly on MT5 without conversion?
No. MT5 uses a completely different executable format (.ex5 vs .ex4) and a different API. You must convert the source code (.mq4 to .mq5) and recompile.
Is there an automatic tool to convert MQL4 code to MQL5?
MetaEditor includes a “Convert MQL4 to MQL5” tool under Tools menu. It handles basic syntax (like function renames) but fails on complex order logic, custom indicators, and file operations. Always review and test the output.
Will my converted EA produce identical results on MT5?
Not always. Differences in order execution (instant vs. request), tick generation, and bar indexing can cause slight variations. Always compare backtest statistics and trade logs between platforms.
Do I need to convert my indicators separately from my EAs?
Yes. If your EA calls custom indicators via iCustom() in MQL4, you must convert those indicators to MQL5 and use CopyBuffer() to access their values






