MQL5 EA Reconnect Logic: Code Auto-Retry & Sleep

Build resilient MQL5 EA reconnect logic with auto-retry loops and Sleep(). Learn to detect disconnects, avoid double orders, and keep your Expert Advisor.

mql5-ea-reconnect-logic-code-auto-retry-sleep

You know that sick feeling. You check your VPS at 3 AM, and the Journal is full of trade timeout and connection lost messages. The EA was running, the signal fired, but the order never reached the server. Price moved, and you missed the move. Or worse, the EA kept trying to send an order while the terminal was reconnecting, and it double-submitted when the link came back.

Most traders blame the broker or their VPS provider. And sure, sometimes the broker's server really does hiccup or the VPS host has a bad night. But the real culprit is usually the EA itself. Out-of-the-box, most MQL5 Expert Advisors assume the connection is permanent. They call OrderSend() once, and if it fails, they just log the error and move on to the next tick. That's fine for a demo test on a fiber connection with zero latency and a server that never blinks. It's a disaster on a real account over Wi-Fi or during a broker's Sunday maintenance window when the server drops for ten minutes.

This article is for developers who want their EAs to survive real-world conditions. We'll build a proper MQL5 EA reconnect logic from scratch. You'll learn how to detect disconnects, implement a retry loop that doesn't freeze your EA, and use the Sleep() function correctly so your EA pauses and resumes without manual intervention. This isn't about buying a VPS or configuring a watchdog — that's a platform-level fix. This is about writing code that handles the mess gracefully, inside the EA itself.

Why Your EA Fails on Disconnect

Let's be clear about what happens when your MT5 terminal loses connection. The terminal's market watch freezes. Price data stops updating. But your EA's OnTick() might still fire if there's cached tick data, or it might go completely silent. The problem is that OnTick() doesn't tell you the connection state. You have to check it yourself.

The most common failure pattern I see in client code is this:

void OnTick()
  {
   if(SomeSignal())
     {
      MqlTradeRequest request = {0};
      MqlTradeResult result = {0};
      // ... fill request ...
      if(!OrderSend(request, result))
         Print("Order failed: ", result.retcode);
     }
  }

If the connection is down, OrderSend() returns false and you get a retcode like 10021 (no connection) or 10018 (trade timeout). The EA prints the error and forgets about it. The signal was valid, but the trade is gone. On the next tick, the signal might not be true anymore, so the opportunity is lost forever.

There's a second, more dangerous failure mode. The terminal reconnects silently. Your EA, unaware of the blip, sends an order. The server receives it, but your EA timed out and thinks it failed. It sends it again. Now you have a double position. This is the "retry without state" bug, and it's why naive retry loops are dangerous. I've seen traders blow up accounts this way — not because the strategy was wrong, but because the execution layer didn't know what had already been sent.

Building Blocks: Terminal Info and Sleep

Before we write the full reconnect logic, let's cover the two core MQL5 functions you'll rely on. Understanding these deeply will save you hours of debugging later, especially when you're staring at a Journal full of cryptic error codes at 2 AM wondering why your EA isn't doing anything.

TerminalInfoInteger() for Connection State

The TERMINAL_CONNECTED flag is your primary health check. It's a simple boolean that reflects whether the terminal has an active connection to the trade server.

bool IsConnected()
  {
   return (bool)TerminalInfoInteger(TERMINAL_CONNECTED);
  }

That's the easy part. The harder part is knowing when it's actually safe to trade. A connected terminal can still reject orders if the broker is in a no-trading session, or if the specific symbol is halted. So while TERMINAL_CONNECTED is your first gate, it's not sufficient. You should also check MQLInfoInteger(MQL_TRADE_ALLOWED) to ensure the EA has trade permission, and ideally check the symbol's trade mode via SymbolInfoInteger(_Symbol, SYMBOL_TRADE_MODE).

Let me give you a concrete example. I once had an EA trading EURUSD on a broker that paused trading during their daily rollover window (typically 5 minutes around midnight server time). The terminal was connected, the EA had permission, but OrderSend() kept returning 10019 (trade disabled). My reconnect logic thought everything was fine because it only checked TERMINAL_CONNECTED. I had to add a second check for the symbol's trade mode and a time-based filter for the rollover window. The lesson: connection state and tradeability are two different things, and your retry logic needs to respect both.

The MQL5 Sleep() Function — Use It Wisely

Here's where a lot of developers get confused. In MQL4, Sleep() pauses the entire Expert Advisor for a specified number of milliseconds. In MQL5, it does the same thing, but there's a critical restriction: you cannot call Sleep() from within an indicator's OnCalculate() or a script's OnStart() if you want to keep processing ticks. In EAs, it works fine in OnTick(), but it blocks the thread. While your EA sleeps, it won't process new ticks, timers, or events.

That's actually a feature for our reconnect logic. We want to pause trading and wait. Blocking the EA is exactly what we need to avoid sending orders during a flaky connection. The key is to keep the sleep duration short and check the connection state after each interval, rather than sleeping for 5 minutes straight and hoping the connection is back. If you sleep for 5 minutes and the connection comes back in 10 seconds, you've just wasted 4 minutes and 50 seconds of trading time.

One practical note: Sleep() in MQL5 also works in OnTimer() and OnTradeTransaction() handlers, but I've found it's safest to keep it only in OnTick() or in a dedicated retry function that you call from OnTick(). If you call Sleep() inside a custom function that's also called from an indicator or a script, you'll get an error (ERR_CALL_FUNCTION_NOT_ALLOWED). Keep your reconnect logic isolated to the EA's main event handlers. This is one of those MQL5 quirks that will drive you insane if you don't know about it in advance.

FunctionReturnsUse CaseCommon Pitfall
TerminalInfoInteger(TERMINAL_CONNECTED)boolPrimary check for network link to trade server.Does not reflect broker-side trading restrictions.
MQLInfoInteger(MQL_TRADE_ALLOWED)boolConfirms the EA has permission to trade in the terminal.Can be false if user disables algo trading manually.
HistorySelect()boolLoads trade history to check if an order actually went through.Must be called before accessing history deals/orders.
Sleep()voidPauses EA execution for a given number of milliseconds.Blocks the thread; not allowed in indicator OnCalculate().

Designing the Retry Loop: State Machine Approach

Don't write a giant while loop that tries to reconnect forever. That freezes your EA and prevents it from reacting to anything else. If you've ever had an EA that "hangs" and you have to kill the terminal from Task Manager, a blocking retry loop is often the culprit. Instead, use a simple state machine. Your EA has three states: Normal, Retrying, and Paused.

  • Normal: Connection is up, and you process signals and send orders normally.
  • Retrying: Connection is down. You wait a short interval, check again, and increment a counter.
  • Paused: You've exceeded the retry threshold. You stop trading entirely and only check periodically (e.g., every 5 minutes) to see if the connection is back.

This approach keeps your EA responsive. During the Paused state, you don't want to block OnTick() for long periods. Instead, use a timer or a simple time check to avoid sleeping for too long. The idea is to be a good citizen of the terminal's event loop, not a monopolist.

Why a state machine and not just a loop? Because a loop inside OnTick() will block everything else. If you have an OnTimer() handler that manages a trailing stop, or an OnTradeTransaction() handler that updates a dashboard, a blocking loop will starve them. I've seen EAs that work perfectly in the Strategy Tester but freeze on a live chart because the tester doesn't simulate the full event queue the same way. The state machine lets you spread the retry logic across multiple ticks, which is the idiomatic MQL5 way to handle this.

Global Variables and Inputs

First, define your inputs. These should be exposed in the EA's input parameters so users can tune them without recompiling. I always prefix input variables with Inp to distinguish them from globals — it makes the code easier to read when you're scanning through dozens of lines, and it's a convention that MetaEditor's code wizard actually follows too.

ParameterTypeDefaultDescription
InpReconnectAttemptsint10Number of quick retries before entering paused state.
InpReconnectDelayMsint5000

Want to build your own version?

Recreate similar entry logic, risk rules, and filters in TradingBotMaker—no MQL coding. Start free.

Community

Clap for the article and open comments only when you want to read them.

0 claps0 comments

Related articles