Three Production Failures in AI-Generated MQL Code That the Strategy Tester Never Catches
Three failure patterns recur in AI-generated EAs. The code compiles clean and backtests well. It fails in production because it misses the conditions that only exist when real money is on the line.
No State Persistence After Terminal Restart
AI-generated EAs store trade state in RAM — static variables, global scope counters. When the terminal restarts, everything resets. The EA forgets its open positions and opens duplicates.
A common AI pattern:
In the Strategy Tester, this works perfectly — the tester never restarts mid-run. In live trading, after a VPS reboot, openTradeCount resets to 0. The EA opens a new position while the previous one is still running.
The fix requires scanning the order pool on every init:
The counter is never the source of truth. The broker's order pool is.
Missing Order Context Validation
AI treats the order pool as a static list. It selects an order by position index, reads its properties, runs trailing logic, then calls OrderModify() — assuming the pool stayed frozen between operations.
Two things break this assumption in live trading. First, the order can close between OrderSelect() and OrderModify() . Second, if the trailing logic contains any intervening OrderSelect() call — checking a hedge position, scanning for a related order — the internal selection shifts. The subsequent OrderOpenPrice() and OrderTakeProfit() calls return values from whatever order was last selected, not the intended target.
The production-ready pattern re-selects by ticket before every modification:
Three extra lines. One concept: the order pool is live, and any operation that changes it invalidates previous selections.
Broker Constraint Blindness
AI generates order operations that ignore runtime constraints enforced by the broker's trade server.
Stop level violation. Every broker defines MODE_STOPLEVEL — the minimum distance between price and any stop loss or take profit. AI generates OrderModify() without checking this. The trade server rejects the call with error 130 (invalid stops), and an EA that does not check the return value never notices.
Lot step mismatch. AI sends raw calculated lot sizes to OrderSend(), such as 0.0847 lots, and what happens next depends on the platform. In MT4 the order opens at 0.08 lots with no error: in our tests on a demo account and in the Strategy Tester, the terminal cut the volume to two decimals before sending it, so the actual risk is lower than intended and the EA never knows. In MT5 the same request fails with retcode 10014 (invalid volume), live and in the Strategy Tester, and an EA that does not check the result never opens the trade.
Trade context busy. In MT4, one trade operation at a time per terminal. AI never checks IsTradeAllowed() . The EA gets error 146 and proceeds as if the order was never attempted.
A composite production-ready pattern. It measures the buy's stop from Bid, as MT4 does, sizes the lot from the stop it will actually send, rounds the lot down to the broker's step, and skips the trade rather than raising the lot to the minimum:
Why the Strategy Tester Misses All of This
The tester never restarts mid-run. Orders do not close between operations within the same tick. Stop levels are often not enforced or set to zero. Trade context is always available. AI learns from code that works in this controlled environment because production failures are posted as forum complaints — not as code samples.
The code is not broken. It is incomplete. It handles the strategy logic and nothing else.
Quick Diagnostic Checklist
Before running any AI-generated EA live, search the source for:
- GlobalVariableSet or FileWrite in OnInit() — state persistence
- OrdersTotal() or PositionsTotal() in OnInit() — position reconciliation
- OrderSelect(ticket, SELECT_BY_TICKET) before every OrderModify() — re-selection
- MODE_STOPLEVEL or SYMBOL_TRADE_STOPS_LEVEL — stop level validation
- MODE_LOTSTEP or SYMBOL_VOLUME_STEP — lot normalization
- IsTradeAllowed() before OrderSend() — trade context guard
If any of these is missing, the code is not production-ready.
Correction, 9 October 2026: the lot step paragraph said the broker rounds an off-step volume to the nearest step. Tests on MT4 and MT5 demo accounts and in the Strategy Tester showed otherwise, and the paragraph now says what each platform does. The stop level sentence no longer says the broker may silently adjust a stop. The composite example now measures a buy's stop loss from Bid, as MT4 does, and sizes the lot from the stop it actually sends.


