Forward-test an MT5 EA to find operational failures
Key takeaways
- The first objective on demo is not profit. It is proving that the EA stayed active, sent each intended request once, and attached the required protection to the resulting position.
- Reconcile
signal → request → retcode → order → deal → position → Stop Loss/Take Profit; a chart icon or one visible position is not enough evidence. - Any code or input change starts a new observation. Unexplained duplicate orders, missing stops, or restart failures block further escalation.
How to Read an MT5 Strategy Tester Report ends at a deliberately narrow conclusion: a valid historical result can justify another experiment, but not a move directly to live capital.
The next experiment is forward observation on a demo account. Here, forward test means attaching a frozen EA and input set to current quotes from a demo trade server instead of replaying a selected historical interval.
This exposes conditions that a historical tester cannot fully reproduce: changing spread, session state, request rejection, partial execution, network loss, terminal restart, and two copies of an EA acting on the same account. Demo execution still does not reproduce every live liquidity, queue, latency, or slippage condition. Treat it as an operational lab, not a live-performance proxy.
Freeze the observation baseline
An observation is only comparable while its inputs and environment remain known. Create an observation ID and capture the baseline before enabling the EA.
| Evidence field | Record |
|---|---|
| Observation ID | For example, FWD-20260714-01 |
| Source and executable | EA file, source version, release, commit or hash when available |
| Runtime | Operating system and MT5 terminal build from Help → About |
| Account context | Broker/server, demo status, netting or hedging, currency, leverage |
| Chart context | Exact symbol, timeframe, and server timezone |
| Inputs | Saved .set file, volume rule, SL/TP, Magic Number |
| Symbol specification | Digits, point/tick size, volume limits, and trading sessions |
| Observation scope | Start and end rules, sessions and recovery events to cover |
Do not store a complete account number, password, API key, or identity document in the evidence bundle. A symbol name alone is insufficient: two servers can expose similar names with different contract sizes, sessions, stops levels, and execution rules.
Changing the code, inputs, account, symbol, or timeframe closes the current observation. Open a new ID. Adjusting volume or stop distance after an uncomfortable loss is a parameter change, not a continuation of the same test.
Define coverage by events, not calendar days
Five or ten elapsed days do not create evidence by themselves. Ten quiet days with no signal exercise less of the system than three days containing intended sessions, trade requests, a reconnection, and end-of-day handling.
| Stage | Purpose | Example completion evidence |
|---|---|---|
| Initialization | Confirm load, permissions, and account context | EA initializes on the intended account, chart, and inputs without error |
| First session | Audit the entire order path under supervision | First signal is reconciled through position and protection |
| Continuous observation | Cover session transitions and normal connectivity | Intended active hours and daily rollover behaviour are observed |
| Controlled recovery | Test restart/reconnect state restoration | Existing account state is recognized without a duplicate entry |
| Closeout review | Classify every discrepancy | Each difference has a cause, severity, and next reproducible test |
Begin restart testing while the demo account has no exposure. Turning off a terminal while a position is open can disable EA-managed exits or synthetic stops. A position-held recovery drill belongs in a separate controlled experiment after the code's intended behaviour is documented.
A low-frequency EA may produce no trades for several days. Record order path not yet observed, not “passed.” Do not loosen the signal rule merely to generate activity.
Monitor four operational surfaces
1. Uptime, connection, and permissions
A locally hosted EA needs the MT5 process, power, operating system, network, and broker-server connection to remain available. Toolbox → Journal records platform and network events; Experts contains EA initialization and messages emitted by the program.
At each review, ask:
- Is there an unexplained gap between log timestamps?
- Did sleep, an update, a reboot, or a crash stop the terminal?
- Is the EA still attached to the intended symbol and timeframe?
- Are global
Algo Tradingand the EA-level permission in the intended state? - After reconnection, is there evidence that quotes and account state were re-read?
If continuous observation is required, a VPS can remove some local power and connectivity dependencies. The official MetaTrader virtual-hosting guide opens in a new tab explains why an EA requires uninterrupted terminal-to-server connectivity. A VPS migration changes the runtime environment, so open a new observation ID. Do not knowingly run the same EA on the same account from both local and hosted terminals; two active instances can process one signal twice.
2. One intended action, one reconciled trade idea
One position row does not prove that only one request was sent. MT5 distinguishes an order, a deal, and a position, and one order can generate multiple deals.
Position accounting also changes what the operator sees:
| Account mode | Two same-direction executions on one symbol can appear as |
|---|---|
| Netting | Increased volume in one aggregate position |
| Hedging | Two separate positions |
Inspect account History as well as the current Trade tab. The official order, deal, and position reference opens in a new tab describes their identifiers and relationships.
For every intended trade idea, retain this chain:
signal timestamp / source bar
EA version / chart / Magic Number
request timestamp / requested volume
server retcode / order ticket / deal ticket
position identifier / resulting volumeCommon duplicate paths include:
- the EA is attached to two charts or launched from two terminals;
- local MT5 and a VPS instance both act on the same account;
- an
OnTickrule processes one bar repeatedly without an idempotent new-bar gate; - a timeout triggers immediate resend before account state is reconciled;
- restart logic forgets existing positions or pending orders; or
- the EA does not scope state by Magic Number, symbol, and position side.
A true return from MQL5 OrderSend() does not establish completed execution. The official OrderSend reference opens in a new tab requires inspection of MqlTradeResult.retcode, available order/deal fields, subsequent trade events, and final account state. Treating an ambiguous response as a definite failure and resending immediately can create the duplicate being investigated.
3. Protective stops on the resulting position
An EA log line that says “SL set” is not the same evidence as a non-zero Stop Loss on the resulting position. If the strategy design requires protection, inspect every new position.
| Check | Question |
|---|---|
| Presence | Is the SL/TP price non-zero on the actual position? |
| Side | Is a long SL below the relevant market price and a short SL above it? |
| Price normalization | Does the level respect tick size, digits, and the server's stops rules? |
| Modification result | If protection was added after entry, did that second request succeed? |
| Recovery behaviour | After reconnect, was existing protection preserved rather than removed or overwritten? |
Server-held Stop Loss and Take Profit levels are associated with a position and can operate without the client terminal. By contrast, a synthetic or “virtual” stop calculated only inside the EA cannot act while that runtime is unavailable. Keep those two mechanisms distinct in the record. The official position-protection documentation opens in a new tab explains the server-held behaviour and its account-mode caveats.
Record the count and affected tickets for responses such as invalid stops, trade disabled, price changed, timeout, no connection, or too many requests. Classify them with the MQL5 trade-server return-code table opens in a new tab. A position missing required protection is not a successful observation merely because entry completed. For stop-distance diagnosis, use How to Fix “Invalid Stops” in MT5.
4. Explain the backtest-to-demo gap
Do not try to force daily demo P/L to match a historical report. Start at the event level: did the same rule see a signal, send the same type of request, and reach a comparable account state?
| Dimension | Strategy Tester | Demo forward observation |
|---|---|---|
| Price input | Stored historical ticks/bars under a modelling choice | Current quotes delivered by the selected server |
| Spread | Historical or tester assumption | Current spread that can change through the session |
| Execution | Selected delay and tester model | Network path, server response, and current price state |
| Trading hours | Historical symbol/session data | Current server sessions and closures |
| Runtime | Controlled tester process | Sleep, disconnect, restart, and multiple-instance risk |
| Account rules | Configured test account | Demo server's netting/hedging and symbol restrictions |
After the forward interval ends, rerunning the same dates in Strategy Tester with the frozen EA and inputs can help diagnose differences. That interval is now observed data, so the comparison is a post-hoc diagnostic—not new out-of-sample evidence.
Align server timezones first, then reconcile:
- source bar and prices used by the signal;
- request timestamp, side, volume, and requested price;
- contemporaneous Bid, Ask, and spread;
- retcode and executed deal price;
- resulting SL/TP and modification history; and
- exit cause, commission, swap, and other reported costs.
A different deal price is not automatically an EA defect. It is also not enough to write “slippage” and move on. Determine whether the difference changes the rule, clusters in a session or spread regime, or is amplified by retry logic.
Use a three-point daily routine
| Review point | Verify | Preserve |
|---|---|---|
| Before the session | Account/server, symbol, timeframe, EA version, inputs, permissions, unexpected exposure | Baseline entry or settings capture |
| After each trade event | Signal, retcode, order/deal, volume, position, SL/TP | Experts/Journal lines and History tickets |
| End of day | Connection gaps, errors, unexpected requests, manual intervention, environment changes | Log files, account history, discrepancy list |
Fill these lines before looking at daily profit or loss:
Was the EA available for its full intended window?
Signals observed / requests sent / reconciled trade ideas:
Any duplicate, skipped, rejected, or partial execution?
Did every position have its required protection?
Unexplained differences and next reproduction attempt:Preserve logs daily. MetaTrader maintains separate Experts and platform journals, and older entries may need to be opened from log files; see the official Platform Logs guide opens in a new tab. A screenshot alone usually omits the preceding event, exact return code, and later state transition.
Predefine stop and hold criteria
A forward test is a cheap place to discover the next failure, not a certification ceremony. Three statuses keep short-term P/L from weakening the evidence threshold.
| Status | Examples | Response |
|---|---|---|
| Stop | Wrong symbol/side/volume, duplicate entry, required SL missing, failed state recovery | Block new entries according to the documented kill procedure; preserve logs and tickets |
| Hold | Repeated timeout, timezone mismatch, unexplained fill drift, spread sensitivity | Make no escalation decision; design a frozen reproduction |
| Observation complete | Predefined events covered and no unexplained discrepancy remains | Record only “no operational defect observed under this scope” |
Keep live-capital consideration blocked while any of these is true:
- requests, deals, or position changes do not match the written rule;
- required protection is absent or attached at an incorrect level;
- reconnect or restart repeats an already-processed signal;
- a profitable outcome is being used to waive an unresolved error;
- code or inputs changed but results are still pooled as one run;
- account mode, symbol specification, or server differences remain unknown; or
- no one can explain how open positions are handled after the kill switch is used.
Detaching an EA immediately is not a complete incident procedure. Server-held SL/TP may remain, while EA-only exits and trailing logic stop. Document the sequence for blocking new entries, managing existing demo exposure, and preserving evidence before an incident occurs.
Copyable forward-test record
Observation ID:
Start / end timestamp and timezone:
OS / MT5 build / broker server:
Demo account mode / currency / leverage:
EA file / version / commit or hash:
Symbol / timeframe / contract notes:
Inputs file / Magic Number:
Expected sessions and signal rule:
Uptime or connection gaps:
Signals observed:
Requests sent:
Server retcodes:
Orders / deals / positions reconciled:
Missing or changed SL/TP:
Duplicate or skipped entries:
Spread / requested price / deal price differences:
Manual intervention or environment changes:
Unexplained discrepancies:
Stop / hold / observation-complete decision:
Next reproducible test:
Evidence paths:Record manual intervention rather than editing it out of the story. If a position was manually closed or a stop moved, subsequent P/L is not the EA-only path. Keep failed observations; they become comparison evidence when the same defect returns.
Frequently asked questions
How many days should an MT5 demo forward test run?
There is no universal day count. The first few days can expose basic uptime and request-path defects, but the observation is incomplete until its defined sessions, real signals, protective-order path, and recovery events have been exercised. A low-frequency strategy may require a much longer calendar window.
Does the EA keep running when the PC is off?
Not when the EA runs only in that local terminal. Existing server-held SL/TP may still operate, but EA-managed entries, exits, synthetic stops, and trailing logic do not execute. Treat VPS hosting as a separate environment and validate it separately.
Does demo profit confirm the backtest?
No. A short demo interval has limited observations, and demo execution can differ from live execution. The useful conclusion is whether the frozen rule and operational path behaved as documented under the observed conditions.
Does one visible position rule out duplicate orders?
No. A netting account can aggregate multiple deals into one position. Reconcile History, order and deal tickets, resulting volume, Magic Number, and the EA's intended trade idea.
What if no trade occurs for several days?
Separate “no valid signal” from a silent data, permission, session, or initialization failure. Without heartbeat or signal-evaluation evidence, label the order path unobserved rather than stable.
Risk note
A demo account provides a no-real-funds environment for learning platform behaviour and testing a strategy, but it cannot reproduce every aspect of live liquidity, execution priority, latency, slippage, or spread expansion. Historical and demo results do not establish future performance. Leveraged products can produce rapid and substantial losses.
This article is educational and broker-neutral. It does not recommend an EA, broker, symbol, parameter set, or trade. Confirm current platform behaviour with the official MetaTrader 5 getting-started documentation opens in a new tab, your terminal build, and the selected server's current contract specifications.
Up next
Continue with How to Recover MT5 EA State After Restart or Reconnect for Magic Number scoping, open-position and pending-order reconciliation, idempotent new-bar entry, OnTradeTransaction evidence, and the single-active-runtime rule for local terminals and VPS hosting.