The same five structural gaps often hide inside a "working" EA. This is not about strategy logic. The strategies are often fine. The failures are in the plumbing: error handling, state management, environment assumptions, execution validation, and defensive guards.
Here are the five patterns a rescue review checks first, with MQL4 code examples showing both the problem and the fix.
1. No Error Handling on OrderSend
The EA sends a trade request and never checks what happened:
In the Strategy Tester, every order fills. In live trading, requotes, margin failures, and trade context busy conditions cause silent failures. The EA's internal state diverges from reality.
Consider a grid EA where the counter increments on every OrderSend() call regardless of the result. In live trading, requotes during volatile sessions create phantom grid levels. The average entry price in the EA's memory diverges from the account's actual average.
2. No State Persistence Across Restarts
The EA stores all state in runtime variables:
Terminal restarts constantly — VPS reboots, MetaTrader updates, broker disconnects. Every restart fires OnDeinit() then OnInit() , and every static variable resets to its initial value.
Consider a martingale EA that tracks its multiplier this way. After a weekend restart during a drawdown, the multiplier resets to 1. The EA opens a base lot position while the losing chain is still open.
The global variable pool ( GlobalVariableSet , GlobalVariableGet ) also survives restarts and is simpler for single-value persistence.
3. Hardcoded Environment Assumptions
Point * 10 is correct for 5-digit forex pairs. It is wrong for gold, indices, and 4-digit brokers:
Every hardcoded value in the first block can break an EA. The runtime queries in the second block prevent it.
4. Ignoring Execution Feedback
Beyond OrderSend() , an EA must never ignore OrderModify() , OrderClose() , or OrderDelete() return values:
I fixed a trailing stop EA where OrderModify() was rejected every tick with error 130 (invalid stops) because the new SL violated MODE_STOPLEVEL . The EA logged "trailing active" while the stop loss had not moved in hours.
5. No Defensive Guards
The final pattern: no bounds checking, no zero-denominator guards, no validation of indicator return values.
Consider the same calculation during a news spike: ATR collapses to effectively zero on a single bar, and the division returns an enormous lot size. NormalizeDouble() rounds it without complaint, and OrderSend() submits it. What stops that order is outside the EA: the symbol's maximum lot size and the broker's margin check.
The Pattern
All five failures share the same root cause: the EA was tested only in the Strategy Tester — the environment where everything works. Orders fill instantly. Terminals never restart. Symbol properties match the developer's setup. History is complete.
Live trading is the environment where things fail. Production-ready code assumes that every trade request can be rejected, every stored value can be lost, and every assumption about the broker can be wrong.
Five questions to check any EA:
- Does it check return values on every OrderSend , OrderModify , and OrderClose ?
- Does it persist critical state and reconcile on startup?
- Does it query symbol properties at runtime?
- Does it validate execution feedback and log effective values?
- Does it guard against zero denominators and insufficient history?
If any answer is "no," the backtest results are fiction with a delayed fuse.
Correction, 9 October 2026: an earlier version said this scenario produced an infinite lot size that NormalizeDouble() turned into a very large number, and that the broker's lot limit was the only thing that stopped the order. The paragraph now describes a near-zero ATR producing an enormous lot size, and names what stops such an order outside the EA: the symbol's maximum lot size and the broker's margin check.


