MQL4 to MQL5 Migration: Case Study of a Grid EA That Survived the Rewrite

In 2019 a trader shipped a grid EA built by a freelancer. In 2025 his broker moved to FIFO enforcement, the developer was gone, and the only files left were compiled .ex4 binaries. This is the story of that EA surviving a full rewrite onto MQL5 — and of what to expect when you hire MQL4/MQL5 developers for a migration instead of a patch job.

August 19, 2026  |  12 min read  |  MQL4, MQL5, Migration, Grid EA

Table of Contents

  1. Why Migrations Fail
  2. The Case: A Legacy Grid EA With No Source Code
  3. Phase 1 — Audit: Three Bugs the Client Never Saw
  4. Phase 2 — Re-architecture: Events, Netting, State Rebuild
  5. Phase 3 — Parity Validation on Ten Years of Ticks
  6. The Numbers
  7. Six Lessons for Anyone Migrating
  8. Frequently Asked Questions

Why Migrations Fail

Most MQL4 to MQL5 migrations fail for reasons unrelated to strategy quality. The logic survives; the assumptions die. Four categories of assumptions kill ported systems, and any MQL4/MQL5 developer who does not hunt for them explicitly is not migrating — they are translating. The full technical delta between the platforms is documented in MQL4 vs MQL5 development.

  • Order polling versus trade events. An MQL4 EA loops over OrdersTotal() and OrderSelect() on every tick. MQL5 replaces that with OnTradeTransaction, which fires once per server-side trade event. A direct port that keeps the polling pattern inherits races: the same ticket processed twice, close attempts on already-closed orders, state updates a tick too late.
  • Tick semantics. In MQL4 the tick handler runs on the chart symbol's cadence. In MQL5, OnTick fires for the chart symbol only, and other symbols tick on their own schedule. A multi-pair EA that assumes all symbols tick together drifts immediately after the port.
  • Tester differences. The MT4 strategy tester simulates a single currency with a mostly fixed spread; the MT5 tester runs real multi-currency tick history with floating spread modeling. Parity testing therefore requires identical tick data in both platforms — a detail most migrations skip, then blame the EA for behaving differently live.
  • Silent logic drift. Hardcoded pip math, TP normalization, volume units, bar-index direction. These do not throw errors. They shift fill prices by a pip here and there, compounding into a curve that no longer matches.

The Case: A Legacy Grid EA With No Source Code

The client arrived with a familiar story. In 2019 he paid a freelancer to build a grid EA that ran on eight pairs with per-pair spacing, a martingale-style lot progression and basket take-profits. It traded profitably for years — until the broker introduced FIFO enforcement and restricted MT4 alongside other legacy platforms. When he contacted the original developer, the account was gone. The artifacts that remained: compiled .ex4 files, the 12-page specification the freelancer had written at the start of the project, and four years of account statements.

The honest part about reverse engineering: nobody who respects the platform's licensing will decompile your .ex4 for you. So the reconstruction used a cleaner evidence chain: the specification as the source of truth for intent, the statements as behavioral evidence for what actually executed, and the client's still-working MT4 terminal as a live reference tester. That combination was enough to rebuild the system — and to find bugs the client had been paying for since 2019.

Phase 1 — Audit: Three Bugs the Client Never Saw

The first two weeks were an audit, not a rewrite. Every order-related block was inventoried: magic numbers per pair, grid spacing, lot progression steps, basket take-profit logic, equity-stall rules. The audit produced a behavior map — the true specification of what the EA did, which differed from the written one in three places.

Bug 1 — the unprotected requote loop. The original code retried rejected orders inside while(true) on error 138 with no exit condition. During illiquid sessions the EA could spin inside that loop for minutes while price moved away.

Bug 2 — the 4-digit pip assumption. The classic: Point * 10 hardcoded as a pip. On the client's first broker, with 4-digit quotes, it worked. When he added a 5-digit broker, every grid step and take-profit distance silently doubled. Half the "strategy changes" the client had requested over the years were probably compensation for this bug.

Bug 3 — no restart recovery. All grid state lived in memory. Every weekend platform restart, every power cut, the EA forgot its open baskets and started fresh grids beside orphaned positions.

This audit phase is part of any MQL4 EA architecture review: you map the system before you touch it.

Phase 2 — Re-architecture: Events, Netting, State Rebuild

The rewrite replaced the entire execution layer. Raw OrderSend calls became CTrade with bounded retry and backoff, and the polling loop became OnTradeTransaction handlers keyed on DEAL_ENTRY_IN, DEAL_ENTRY_OUT and modification events. One event per action removes the double-processing races of the old design.

Netting support required the deepest change. The broker's FIFO requirement pushed the client toward a netting account, where MQL5 aggregates trades per symbol into a single position. On netting, POSITION_IDENTIFIER is unreliable as a basket key because it changes on every partial close. So the ported EA tracks baskets by symbol and magic number, re-derives state after every transaction event, and uses the identifier only as a consistency check. The result runs cleanly on both netting and hedging accounts — one of the checks from the developer vetting list we apply to our own work.

State rebuild on startup was the direct fix for Bug 3. On OnInit the EA queries open positions and the day's trade history and reconstructs every active grid basket — spacing, step count, average price, expected next level. If the reconstruction is ambiguous, it logs the uncertainty and refuses to open new grids instead of doubling into an unknown state.

Finally, configuration was externalized: pair list, grid spacing, lot progression, recovery mode and session windows became named inputs, editable without a recompile. The MT5 build was assembled against the same layered architecture described in our MT5 development approach.

Phase 3 — Parity Validation on Ten Years of Ticks

Parity validation is the step most migrations skip. The protocol: same symbol, same dates, ten years of identical tick data, same deposit and lot progression. The original MQL4 EA ran in the client's preserved MT4 build; the ported EA ran in MT5.

MetricOriginal MT4 BacktestMigrated MT5 BacktestDelta
Total trades3,4123,405-7 (-0.2%)
Profit factor1.281.26-0.02
Max drawdown18.4%18.9%+0.5 percentage points
Win rate42.1%41.8%-0.3 percentage points
Average trade R-multiple0.310.30-0.01

The deltas are execution-model differences, not logic differences. The MT5 tester models floating spreads and per-tick fills from real history; MT4's fixed-spread simulation fills a handful of the 3,400 trades at slightly different prices. Seven trades fell outside the fill-tolerance band over ten years — each traced to a spread spike the MT4 model could not reproduce, and each documented in the migration report.

The Numbers

  • 11 weeks from audit kickoff to live cutover: 2 weeks audit, 4 weeks rebuild, 3 weeks parity testing, 2 weeks parallel demo.
  • 3,405 trades parity-checked across ten years of identical tick data, with every delta traced to a documented cause.
  • 3 latent bugs found and fixed — the requote spin, the 4-digit pip assumption, the missing restart recovery.
  • Under 1.5% divergence between the MT4 original and the MT5 port over six weeks of parallel demo.
  • 0 warnings, 0 errors on the delivered MQL5 source, now running on a FIFO-compliant netting account.

Six Lessons for Anyone Migrating

  1. Migrate the specification, not the code. Line-by-line translation carries the old bugs with it. Rewrite against what the system should do, and let the audit show what it actually did.
  2. Never preserve old pip math. Normalize everything through SymbolInfoDouble(SYMBOL_POINT) at runtime so 4-digit and 5-digit brokers are handled identically.
  3. Rebuild state from the server, not from memory. Open positions plus trade history are the only state that survives a restart. If the EA cannot reconstruct its state, it should refuse to trade, not guess.
  4. Parity-test before you optimize. If the port does not reproduce the original curve within explained deltas on identical data, no parameter tuning will save it — the drift is structural.
  5. Run both versions during cutover. A parallel demo period turns invisible drift into visible divergence while the cost of catching it is still zero.

Frequently Asked Questions

Can an MQL4 EA be converted to MQL5?

Yes — not by line-by-line translation, but by re-architecting against a written specification. The order loops, pip math and in-memory state of MQL4 must be rebuilt with CTrade, OnTradeTransaction and server-side state recovery. A proper conversion is a rewrite with parity validation, typically taking 2 to 8 weeks depending on complexity.

How long does an MT4 to MT5 migration take?

A realistic timeline: 1 to 2 weeks to audit, 2 to 4 weeks to rebuild in MQL5, and 2 to 3 weeks of parity testing plus a parallel demo run. Simple single-pair EAs can migrate in under two weeks; the multi-pair grid system in this case study took 11 weeks including live cutover.

Will the migrated EA behave identically?

Not perfectly — and that is expected. MT4 and MT5 testers and execution engines differ, so a parity-validated migration lands within small explained deltas (typically under 1% of trades and a few hundredths of profit factor). The goal is equivalence within tolerance, verified on identical tick data, not byte-for-byte identical output.

Can you migrate an EA without the source code?

Yes, but honestly: not by decompiling the .ex4, which we do not offer. The legitimate path is behavioral reconstruction — using the original specification, account statements, and a preserved MT4 terminal as a reference tester. With no spec and no statements, the migration is effectively a new build from your description.

Why do migrated EAs sometimes trade differently?

Four reasons: order polling replaced by trade events (different timing), tick semantics (MQL4 ticks arrive on chart-symbol cadence, MQL5 on per-symbol cadence), tester differences (fixed spread in MT4 versus real-tick spread modeling in MT5), and silent logic drift like hardcoded 4-digit pip math. A disciplined audit finds these before they hit a live account.

Migrate Once. Trade Everywhere.

A migration is an engineering project, not a find-and-replace. If your MQL4 system is being pushed off MT4 by your broker, send us the specification — or whatever artifacts you have. You will get an audit that finds the bugs you did not know you were paying for, a rewrite that survives restarts, and parity numbers you can verify yourself.

Get a Migration Quote MQL4 vs MQL5 Comparison MT5 Development Services
🚀 Invite friends — Earn $5 You both get $5 credit on Go Ad · opencode.ai AI-Powered Coding Agent — Try Free Build apps, fix bugs & ship faster with opencode. Get $5 free credit when you join. × Ad · quo.com QuoPhone — $20 Visa Gift Card Free Sign up to Quo, subscribe 3 months, get a $20 Visa gift card. Atif's referral gift for you. ×