Live trading is messier than the Strategy Tester. Connections drop. Prices jump. The trade server rejects an order that looked fine a tick ago. If your EA assumes every OrderSend succeeds, you will get stuck positions and duplicate risk.
What usually breaks
- The terminal loses the trade server for a few seconds. Your EA keeps thinking an order is pending when it never landed, or the opposite.
- A requote or trade context busy error returns. A naive retry loop hammers the server and can open two tickets for one signal.
- After a restart, OnInit runs again. Without a recovery path, the EA forgets which magic numbers it already owns.
Patterns that hold up
Track intent separately from confirmation
When you decide to enter, write a local state: signal id, side, volume, stop, take profit, timestamp. Only clear that intent after you see a matching deal in history or an open position with your magic and comment. If OrderSend fails, leave the intent and decide whether to retry under clear rules.
Bound your retries
Retry on transient codes such as trade context busy. Do not retry forever on invalid stops, no money or market closed. Sleep a short, increasing delay between attempts, and give up after a small number of tries for that signal.
Rehydrate state on startup
In OnInit, scan open positions and recent history for your magic number. Rebuild any trailing or breakeven state from what is actually on the account. Never assume memory from before the crash still matches the book.
One signal, one ticket
Store the bar time or a unique signal key for the last entry. Refuse a second entry for the same key even if the chart redraws or OnTick fires again after a reconnect.
Log failures with the retcode
Print or write the trade retcode, bid, ask, and relative spread when an order fails. When a client says "it randomly skipped trades," those logs are the difference between a guess and a fix.
A minimal checklist before you go live
- Kill the terminal mid trade on demo and confirm the EA recovers cleanly.
- Change the internet path (or use airplane mode for a minute) and watch how pending intents resolve.
- Verify magic number filters so a manual trade on the same chart is never managed by accident.
None of this replaces a real edge. It stops infrastructure noise from looking like strategy failure.
I write about MT5 risk control and custom bots at Custom Trading Bots.
Top comments (1)
I would add one recovery test: disconnect just after the server accepts the request, before the EA receives confirmation. OrderSend() returning true does not prove a fill, so check result.retcode and reconcile orders and deals before retrying. The expected result is one entry for the signal, even after restart. A timeout should leave that intent unresolved until reconciliation, rather than automatically triggering another send.