Phase 4: Weekend / Market-Closed Initialization
Many traders deploy EAs on Friday evening or Sunday before markets open, only to find errors or crashes when the market finally opens because the initialization sequence failed while prices were static.
How to Simulate: Attach your EA to a live or demo chart on a Sunday when markets are completely closed, or during a scheduled maintenance window.
What to Look For:
Does the EA handle missing tick data, zero spreads, or stale bid/ask prices gracefully during OnInit()?
Does it crash or throw array-out-of-range errors when calculating technical indicators (like moving averages or ATR) when historical bar data is incomplete?
Verification: Inspect the journal tab for initialization errors and ensure your EA checks for valid pricing data (SymbolInfoDouble(Symbol(), SYMBOL_BID) > 0) before executing any calculations on startup.
Simulating a broker outage in your EA testing
Re: Simulating a broker outage in your EA testing
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Simulating a broker outage in your EA testing
To build an Expert Advisor that survives real-world chaos, network dropouts, and broker restarts, you need code structures that do not rely on volatile run-time memory alone.
Below are robust MQL5 code snippets demonstrating dynamic state recovery on startup (OnInit), safe broker error handling, and a throttled retry loop to prevent server spamming.
Below are robust MQL5 code snippets demonstrating dynamic state recovery on startup (OnInit), safe broker error handling, and a throttled retry loop to prevent server spamming.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Simulating a broker outage in your EA testing
1. Dynamic State Recovery on Startup (OnInit)
Instead of losing track of your states when MetaTrader restarts or your VPS reboots, force your EA to query the broker server immediately upon initialization (OnInit) to map all active positions back into local tracking variables.
Instead of losing track of your states when MetaTrader restarts or your VPS reboots, force your EA to query the broker server immediately upon initialization (OnInit) to map all active positions back into local tracking variables.
Code: Select all
//--- Input parameters
input long MagicNumber = 123456;
//--- Global tracking variables
bool g_hasOpenPosition = false;
ulong g_activeTicket = 0;
double g_entryPrice = 0.0;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// 1. Check if the terminal is actually connected to the broker server
if(!TerminalInfoInteger(TERMINAL_CONNECTED))
{
Print("Initialization Warning: Terminal is currently disconnected from the broker!");
// Do not fail entirely; allow it to load so it can recover once connection resumes
}
// 2. Perform state recovery: scan open positions on the broker server
RecoverEAState();
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Scan broker server to rebuild internal EA state |
//+------------------------------------------------------------------+
void RecoverEAState()
{
g_hasOpenPosition = false;
g_activeTicket = 0;
int totalPositions = PositionsTotal();
for(int i = 0; i < totalPositions; i++)
{
ulong ticket = PositionGetTicket(i);
if(ticket > 0)
{
// Filter by symbol and Magic Number to manage only this EA's trades
if(PositionGetString(POSITION_SYMBOL) == _Symbol &&
PositionGetInteger(POSITION_MAGIC) == MagicNumber)
{
g_hasOpenPosition = true;
g_activeTicket = ticket;
g_entryPrice = PositionGetDouble(POSITION_PRICE_OPEN);
Print("State Recovery Successful: Re-attached to active ticket #", ticket, " at price: ", g_entryPrice);
break; // Assuming single-position EA for this example
}
}
}
if(!g_hasOpenPosition)
{
Print("State Recovery: No active positions found on broker server for Magic Number: ", MagicNumber);
}
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Simulating a broker outage in your EA testing
2. Safe Error Handling & Throttled Retry Loop
When a broker returns a temporary error (such as TRADE_RETCODE_CONNECTION or TRADE_RETCODE_BUSY), an EA shouldn't hammer the server in a tight loop. It needs a measured back-off mechanism and a way to parse fatal errors vs. retryable errors.
When a broker returns a temporary error (such as TRADE_RETCODE_CONNECTION or TRADE_RETCODE_BUSY), an EA shouldn't hammer the server in a tight loop. It needs a measured back-off mechanism and a way to parse fatal errors vs. retryable errors.
Code: Select all
//+------------------------------------------------------------------+
//| Safe function to send trade requests with error management |
//+------------------------------------------------------------------+
bool SendOrderWithRetry(MqlTradeRequest &request, MqlTradeResult &result)
{
int maxRetries = 3;
int retryDelayMs = 1000; // 1 second back-off
for(int attempt = 1; attempt <= maxRetries; attempt++)
{
ResetLastError();
bool success = OrderSend(request, result);
// If execution was successful at the network/API level, check return code
if(success)
{
switch(result.retcode)
{
case TRADE_RETCODE_DONE:
case TRADE_RETCODE_DONE_PARTIAL:
Print("Order executed successfully. Ticket: ", result.deal);
return true;
// Temporary errors where a retry makes sense
case TRADE_RETCODE_REQUOTE:
case TRADE_RETCODE_PRICE_OFF:
case TRADE_RETCODE_CONNECTION:
case TRADE_RETCODE_BUSY:
Print("Attempt ", attempt, " failed with temporary broker error: ", result.retcode, ". Retrying in ", retryDelayMs, "ms...");
Sleep(retryDelayMs);
retryDelayMs *= 2; // Exponential back-off
continue;
// Fatal errors where retrying will achieve nothing (e.g., bad stops, insufficient funds)
case TRADE_RETCODE_INVALID_STOPS:
case TRADE_RETCODE_INVALID_VOLUME:
case TRADE_RETCODE_NO_MONEY:
Print(ErrorDescription(result.retcode), " (Code: ", result.retcode, "). Aborting request—manual fix required.");
return false;
default:
Print("Unclassified trade return code: ", result.retcode);
return false;
}
}
else
{
// MQL system-level failure (e.g., trade context busy)
uint err = GetLastError();
Print("OrderSend system failure. Error code: ", err, ". Attempt ", attempt, " of ", maxRetries);
Sleep(retryDelayMs);
}
}
Print("Critical: Order placement failed completely after ", maxRetries, " attempts.");
return false;
}
// Simple helper string mapping for standard retcodes
string ErrorDescription(uint retcode)
{
switch(retcode)
{
case 10013: return "ERR_INVALID_STOPS (Stop loss/Take profit too close)";
case 10014: return "ERR_INVALID_TRADE_VOLUME (Invalid lot size)";
case 10019: return "ERR_NO_MONEY (Insufficient margin)";
default: return "FATAL_TRADE_ERROR";
}
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Simulating a broker outage in your EA testing
Best Practices Checklist for Robust EAs
Never rely on global run-time variables to remember if a partial close or a trailing adjustment happened. Query the broker's ticket properties (PositionGetInteger) on every tick or use persistent files (FileWrite / FileRead) if complex local states must survive a full platform crash.
Always validate pricing data inside OnInit() and the beginning of OnTick() using SymbolInfoDouble(_Symbol, SYMBOL_BID) > 0 to prevent zero-divide crashes when attached on weekends or during server freezes.
Log critical state transitions to your local terminal file using Print() so you can cross-reference the exact microsecond a disconnection or recovery occurred during post-mortem debugging.
Never rely on global run-time variables to remember if a partial close or a trailing adjustment happened. Query the broker's ticket properties (PositionGetInteger) on every tick or use persistent files (FileWrite / FileRead) if complex local states must survive a full platform crash.
Always validate pricing data inside OnInit() and the beginning of OnTick() using SymbolInfoDouble(_Symbol, SYMBOL_BID) > 0 to prevent zero-divide crashes when attached on weekends or during server freezes.
Log critical state transitions to your local terminal file using Print() so you can cross-reference the exact microsecond a disconnection or recovery occurred during post-mortem debugging.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Simulating a broker outage in your EA testing
Thanks. If I had to pick one test from that list, it's the restart with an open trade, because that is where I've found real bugs. My first EA kept its trailing level in a variable. After a reboot it forgot it, saw a 40 pip winner with no trail and happily tried to manage it from scratch, moving the stop back to the original 15 pips. On a 0.6 lot position that was about 150 dollars of locked profit handed back for nothing.
The fix was to store state somewhere that survives a restart, either global variables or a small file, and on init to scan open positions by magic number and rebuild the state from them. Then I added a rule that on startup it never opens anything for the first 30 seconds, only reconciles.
One more test I'd add is a duplicate-order check. Pull the cable right after sending an order, reconnect, and see whether the EA resends because it never saw a confirmation.
Do you give each EA its own magic number scheme, or share one across strategies? And what does yours do when a modify request keeps failing?
The fix was to store state somewhere that survives a restart, either global variables or a small file, and on init to scan open positions by magic number and rebuild the state from them. Then I added a rule that on startup it never opens anything for the first 30 seconds, only reconciles.
One more test I'd add is a duplicate-order check. Pull the cable right after sending an order, reconnect, and see whether the EA resends because it never saw a confirmation.
Do you give each EA its own magic number scheme, or share one across strategies? And what does yours do when a modify request keeps failing?
It’s Fairman 