Convert an MT4 strategy to MT5: what changes and why
MT5 does not load MQL4 files, so converting an MT4 strategy means rewriting it in MQL5. The rules stay the same, but orders become orders, deals and positions, the account type decides how repeated entries behave, indicator reads use handles and buffers, and the port must be re-tested against a reference trade list before live use.
By Soren Huang · Published · updated · Editorial policy
Contents
- Can an MT4 EA run on MT5 directly?
- How does the MQL4 order model differ from the MQL5 position model?
- Netting or hedging: which account type does the converted strategy need?
- What has to be rewritten in indicators and event handlers?
- Why do MT5 backtest results differ from MT4, and how do you re-test?
- A conversion checklist you can follow in order
- Frequently asked questions
- References
Can an MT4 EA run on MT5 directly?
To convert an MT4 strategy to MT5, you rewrite it in MQL5: MT5 does not load MQL4 files. The rules stay the same, but the trade model, the indicator calls and the event handlers change, and the result must be re-tested, because the MT5 tester reports different numbers even for a correct port.
An expert advisor (EA) is a program that runs inside MetaTrader and places trades from rules. On MT4 it is written in MQL4 and compiled to an .ex4 file; on MT5 it is written in MQL5 and compiled to an .ex5 file. MT5 opens neither .mq4 nor .ex4. The two languages share a C-like look, so a loop or an if-statement reads the same in both, which is why the port looks small at first. It is not small, because the parts that touch the broker and the chart are built differently.
A useful picture: the strategy is your furniture and the platform is the apartment. Moving from MT4 to MT5 is not copying a box from one shelf to another. It is moving the same furniture into a building with a different floor plan. Every piece still fits somewhere, but you place each one again, and you check that the room works before you live in it. The same is true when a strategy moves between other platforms; the article on what changes when you move a strategy from EasyLanguage to PowerLanguage shows the same pattern with a different pair of languages.
| Item | MT4 | MT5 |
|---|---|---|
| Strategy language | MQL4 | MQL5 |
| File type | .mq4 source, .ex4 compiled | .mq5 source, .ex5 compiled |
| Trade model | Orders | Orders, deals and positions |
| Account types | Hedging behaviour only | Netting or hedging, set by the broker account |
| Strategy tester | One symbol per run | Several symbols per run, several tick modes |
The route with the least hand translation is to keep the rules in a form that is not tied to either language and to write both from it. AlphaPrime (Valynox) holds a strategy as rules and parameters and writes MQL4 and MQL5 source from that one definition, so a strategy that lives there reaches MT5 through platform export rather than through a line-by-line port. For a hand-written EA, the rest of this article is the route.
How does the MQL4 order model differ from the MQL5 position model?
MQL4 treats every open trade as one order that you close by its ticket, while MQL5 splits one trade into three objects, an order, a deal and a position, so every open, modify and close step in the strategy must be remapped. This remapping is where most ported EAs break, and the breaks are quiet: the code compiles, runs, and then modifies the wrong object.
In MQL4 an order is the open trade itself. You send it, you receive a ticket number, and that ticket carries the volume, the stop loss, the take profit and the floating profit. To change the stop you select the ticket and modify it; to exit you close the ticket. One object, one ticket, from entry to exit.
In MQL5 the three objects have three jobs. An order is a request to buy or sell that you send to the server; it carries the requested volume, price and stop levels, and it has a state such as placed, filled or cancelled. A deal is a fill, the executed part of an order; one order can produce several deals when it is filled in parts, and each deal records the executed volume and price. A position is what you hold after the deals; it carries the current volume, the stop loss, the take profit and the floating profit. Realized profit appears on the deal that closes the position.
The remapping, step by step:
- Open. MQL4: send the order and keep its ticket. MQL5: send the order request, wait for the deal, then read the position it created and keep the position ticket, not the order ticket.
- Read. MQL4: loop over orders and select each by ticket. MQL5: loop over positions for the symbol; open pending orders live in a separate list and are not holdings yet.
- Modify the stop. MQL4: modify the order. MQL5: modify the position. A routine that still addresses the opening order does nothing useful.
- Close. MQL4: close the ticket. MQL5: send an opposite order that references the position; the deal that fills it closes or reduces the position.
Netting or hedging: which account type does the converted strategy need?
On a netting account one symbol holds one position and a second buy adds to it while a sell reduces it, whereas a hedging account keeps separate positions as MT4 did, so a strategy that pyramids or holds long and short at the same time behaves differently unless the account type matches its logic. The EA does not choose this; the broker account does, and the EA can read the account's margin mode to find out which one it is running on.
A netting account is an account where all deals in one symbol are combined into a single position with one average price and one volume. A hedging account is an account where each opening deal creates its own position with its own ticket, stop and profit, so two longs or a long and a short can exist in the same symbol at the same time. MT4 only knows the second behaviour. MT5 supports both, and the difference is not cosmetic: it changes which trades appear in the report and what profit each one shows.
Hypothetical example
A strategy buys 1 lot at 100.00 and adds 1 lot at 102.00, then sells 1 lot at 103.00. On a netting account the position goes from 1 lot to 2 lots at an average price of 101.00, and the sell reduces it to 1 lot with a realized profit of 2.00 points on the closed lot. On a hedging account the two buys are two positions; if the code closes the first ticket, the realized profit is 3.00 points and a 1-lot position opened at 102.00 stays open, and if the code simply sends a sell, a new 1-lot short opens and all three positions stay on the book. Three different trade lists from one rule set.
| Strategy behaviour | Netting account | Hedging account |
|---|---|---|
| One position at a time, flat between trades | Works as on MT4 | Works as on MT4 |
| Pyramiding (adds to a winner) | Adds become one position with one average price and one stop | Each add keeps its own stop and profit |
| Partial exit | Reduces the combined position | Code must name which ticket to close |
| Long and short at the same time | Not possible; the two offset | Possible, as on MT4 |
Decide the account type before writing a line of MQL5, because it decides how the close and modify steps from the previous section are written. If the strategy is flat between trades, both types give the same trade list. If it pyramids or runs two directions, choose hedging to keep MT4 behaviour, or rewrite the sizing and exit logic for netting and accept a different trade list. How platforms handle positions and account types is one of the points covered in how the automated trading platforms differ.
What has to be rewritten in indicators and event handlers?
MQL4 returns an indicator value in one call each time you ask, while MQL5 creates an indicator handle once and copies values from a buffer, and the init/start/deinit entry points become OnInit, OnTick and OnDeinit, so every indicator read and every timing assumption must be checked bar by bar. The rule itself does not change. The way the code reaches the numbers the rule uses does.
An indicator handle is a reference to an indicator that the terminal calculates for you; you create it once, usually in OnInit, and later copy as many values as you need from its buffer into an array. In MQL4 a moving average call names the symbol, the timeframe, the period and the bar, and returns one number. In MQL5 the same moving average is created once as a handle, and each tick you copy, for example, the last three values into an array and read from that array. Copying fewer values than the rule needs, or reading before the buffer is ready, gives wrong numbers that look plausible.
Bar indexing is the second trap. In MQL4 the built-in price arrays and indicator calls count backwards: index 0 is the current bar and index 1 is the last closed bar. In MQL5 a copied array runs oldest-first unless you set it as a series. A port that keeps the MQL4 index habit without setting the direction reads the wrong bar, often the current unfinished bar instead of the last closed one, which is the same leak described in look-ahead bias and the one-bar check. Run that check on the port.
| Part | MQL4 | MQL5 |
|---|---|---|
| Entry points | init, start, deinit (newer code may already use the On- names) | OnInit, OnTick, OnDeinit |
| Indicator read | One value returned per call | Handle created once, values copied from a buffer |
| Bar indexing | Series order by default, 0 is the current bar | Array direction set explicitly |
| Current prices | Built-in Bid, Ask and price arrays | Read through symbol and rate functions |
| Trade events | Polled inside start | OnTrade and OnTradeTransaction available |
The event handlers map one to one, and OnTick still runs on every price tick in both platforms. A strategy that should act once per bar needs a new-bar check in both languages, so carry that logic over unchanged. Trade events are different: MQL4 code finds out that a stop was hit by polling the order list on the next tick, while MQL5 can also be told through OnTrade or OnTradeTransaction. A straight port can keep polling with position functions; switching to events is a design change, and design changes belong after the trade lists match, not during the port.
Why do MT5 backtest results differ from MT4, and how do you re-test?
Even a correct port gives a different report, because the two testers build ticks, spreads, margin and fills differently, so treat the MT5 run as a new backtest and compare trade lists against a reference run with the same costs instead of waiting for the old numbers to come back. The MT4 tester builds ticks from one-minute bars with one spread value; the MT5 tester offers several tick modes, can replay recorded spreads, takes margin and swap from the symbol settings, and can fill an order in parts. The same entry rule meets different prices on the way in and out.
The question to answer is not "is the net profit the same" but "did the port fire on the same bars in the same direction". A difference in fill price on the same bar comes from the tester and is expected. A trade that exists in one list and not the other, or that exits a bar early, comes from the port and has to be fixed. Sorting the differences into these two groups is the whole re-test.
A reference run makes this sorting easier. A reference run is a backtest of the same rules on the same bars with fixed commission and slippage and next-bar execution, produced outside both terminals, so that neither the MT4 nor the MT5 report is the judge. The run below shows what such a reference looks like. It tested NQ daily bars from 2019-01-02 to 2025-06-30, long and short, one contract, with $20 commission and $10 slippage per trade. It used a Trend Cycle Oscillator rule as its only entry and exit, with no stop, target or filter, as a stand-in for a strategy to port, not as the subject of this article. It is the one candidate the search kept out of roughly a thousand it tried, kept for its return against its drawdown, and picking the kept one after the fact flatters it; Bailey, Borwein, López de Prado and Zhu (2014) show how large that selection bonus can be. Nothing here says the rule earned that money or that a reader can expect it.
Source: AlphaPrime product engine (CPU), run 2026-10-31. NQ daily bars, 2019-01-02 to 2025-06-30, long and short, 1 contract, $20 commission and $10 slippage per trade.
| Number | Result |
|---|---|
| Net profit (closed trades) | $251,455 |
| Max drawdown | $114,205 |
| Trades | 60 |
| Win rate | 63.33% |
| Profit factor | 1.864 |
| Average trade | $4,190.92 |
| Time in market | 85.7% |

What makes this run useful as a reference is its size and its settings, not its profit. Sixty trades over six and a half years is a list a person can check line by line in an afternoon. Time in market of 85.7 percent tells you the rule is almost always holding a position, so the netting-versus-hedging question from the previous section matters for it: it flips from long to short rather than going flat, and a port must reverse the position in one step on a netting account or close one and open another on a hedging account. Run the MT4 original and the MT5 port on the same daily bars with $20 commission and $10 slippage, as described in commission, slippage and the average trade in backtests, and lay the three trade lists side by side. The same comparison method, written for a different platform, is the subject of how to import a strategy into MultiCharts and match the backtest. Pardo (2008) describes this habit of re-evaluating a strategy whenever its implementation changes as part of the normal evaluation cycle, not as an extra.
A conversion checklist you can follow in order
Freeze the rules, pick the account type, map orders to positions, rebuild indicator handles, port the event handlers, re-test on the same bars with the same costs, and compare trade lists before any live use, in that order. The order matters because each step fixes a decision the next step depends on; mapping orders before choosing the account type means mapping them twice.
- Freeze the rules and settings. Write down every parameter, session filter, stop and exit of the MT4 version. If the strategy exists as rules in a generator rather than as hand-written code, this is the moment to generate the MT5 expert advisor from the rules instead of translating the MQL4 code, then continue from step 6.
- Choose netting or hedging. Decide from the table in the account-type section. Open the MT5 account of that type before testing, because the tester uses the account's margin mode.
- Map orders to positions and deals. Rewrite open, read, modify and close against positions. Store position tickets. Point every stop change at the position.
- Rebuild the indicator handles. Create each handle once in OnInit, copy enough values in OnTick, set the array direction, and confirm with the one-bar check that the rule reads the last closed bar.
- Port OnInit, OnTick and OnDeinit. Carry the new-bar logic over unchanged. Keep polling for trade state in this pass; event handlers can come later.
- Re-test on the same bars with the same costs. Same symbol, same bar size, same date range, same commission and slippage in the MT4 tester, the MT5 tester and the reference run.
- Compare the trade lists. Match each trade by entry bar and direction. Fill-price differences are the tester. Missing, extra or shifted trades send you back to step 3.
Start today with step 6 on the MT4 side alone: run the original EA on a fixed date range with fixed costs, export its trade list, and count the trades. That list is the yardstick every later MT5 run is measured against, and having it before the port begins is what turns "the numbers look different" into a list of specific bars to check.
Frequently asked questions
Can an MT4 EA run on MT5?
No. MT5 does not load .mq4 source files or .ex4 compiled files, and MT4 does not load .mq5 or .ex5 files. An MT4 expert advisor has to be rewritten in MQL5 and compiled in the MT5 editor. The rules can stay the same, but the trade functions, indicator calls and entry points are different in the two languages.
What must change when converting MQL4 to MQL5?
Four areas change. Trade handling moves from single orders to orders, deals and positions, so opening, modifying and closing are rewritten against positions. Indicator reads move from one value per call to a handle created once and values copied from a buffer. The entry points become OnInit, OnTick and OnDeinit. Array indexing direction must be set explicitly, because copied arrays are not in series order by default.
What is the difference between netting and hedging accounts in MT5?
On a netting account all deals in one symbol combine into one position with one average price, so a second buy adds to the position and a sell reduces it. On a hedging account every opening deal creates its own position with its own stop and profit, so two longs or a long and a short can be open at once, which is how MT4 behaves. The broker account sets the type, and a strategy that pyramids or holds both directions needs the type chosen to match its logic.
Why do MT5 backtest results differ from MT4 for the same strategy?
The two strategy testers model the market differently. MT4 builds ticks from one-minute bars with one spread value; MT5 offers several tick modes, can replay recorded spreads, applies margin and swap from the symbol settings, and can fill orders in parts. A correct port therefore fills at slightly different prices and reports a different equity curve. Compare the trade lists by entry bar and direction to tell these tester differences from real porting errors.
References
- Bailey, D. H., Borwein, J., López de Prado, M., & Zhu, Q. J. (2014). Pseudo-Mathematics and Financial Charlatanism: The Effects of Backtest Overfitting on Out-of-Sample Performance. Notices of the American Mathematical Society, 61(5), 458–471.
- Pardo, R. (2008). The Evaluation and Optimization of Trading Strategies (2nd ed.). John Wiley & Sons.

