Forum Sign in Register

Making Your Expert Advisor Robust: Handling Requotes, Order Errors and Retries in MQL

Started by Support 1 week ago · 0 replies RSS

Making Your Expert Advisor Robust: Handling Requotes, Order Errors and Retries

A trading robot that works perfectly in the Strategy Tester and then loses money — or worse, throws errors and stops trading — on a live account is one of the most common disappointments in algorithmic trading. The reason is almost never the strategy. It is that the tester lives in a clean, deterministic world, and the live market does not. Orders get rejected, prices move between the moment you decide and the moment you send, the broker is briefly unreachable, and your beautifully back-tested logic has no idea what to do about any of it. This article is about closing that gap with defensive order-handling code.

The errors you will actually meet

  • Requote — you asked to trade at a price that is no longer available. The broker offers a new price instead of filling. A naive EA either gives up or, worse, blindly accepts a much worse price.
  • Off quotes / no prices — the server has no fresh quote to trade against, common around news and at session opens.
  • Trade context busy — another order operation is already in progress in the terminal; you must wait and retry rather than hammer the server.
  • Not enough money / invalid stops — your stop-loss is too close to market, or the lot size exceeds free margin. These are logic errors in your code, not transient glitches, and retrying will not help.
  • Connection lost / server busy — transient; the right answer is a short pause and a bounded retry.


The core idea: never assume a send succeeded

The single biggest upgrade you can make is to stop treating "send order" as a one-shot action and start treating it as a request that may fail and must be checked. Every send returns a result; inspect it, branch on the specific error, and decide deliberately whether to retry, adjust, or abort.


// Pseudocode — applies to MQL4/MQL5 and most platform APIs
for (attempt = 1; attempt <= MAX_RETRIES; attempt++) {
refresh_market_prices(); // never send a stale price
ticket = send_order(type, lots, price, slippage, sl, tp);
if (ticket > 0) break; // success

error = last_error();
if (is_fatal(error)) { // bad stops, no money, invalid lots
log("Aborting, fatal error: ", error);
break;
}
// transient: requote, busy, off-quotes, no connection
sleep(RETRY_DELAY_MS * attempt); // back off a little more each time
}


Rules that keep it sane

  • Bound your retries. Three to five attempts with a growing delay. An unbounded retry loop during an outage will spam the server and can get your account throttled.
  • Refresh the price before every attempt. Retrying with the same stale price just earns another requote.
  • Separate fatal from transient. Retrying "not enough money" forever is pointless — fix the position sizing instead. Retrying "trade context busy" makes sense.
  • Use a sensible slippage/deviation setting. Zero deviation guarantees requotes in a fast market; an enormous one lets you get filled at a terrible price. Pick a value that reflects the instrument and timeframe.
  • Make modifications idempotent. Before adding a stop-loss, check whether the position already has the one you intended — re-sends after a dropped connection should not create duplicates or stack orders.
  • Reconcile on startup. When the EA (re)starts, read the actual open positions and pending orders from the server before acting. Never trust an internal variable that may be stale after a restart or disconnect.


Log everything, then watch the log

Every order attempt, every error code, every retry and every final outcome should go to a file with a timestamp. When something odd happens at 3 a.m., the log is the only witness you have. A robot you cannot audit is a robot you cannot trust.

Test the failure paths, not just the happy path

Most EAs are tested only in conditions where orders fill instantly. Force the unhappy paths: trade across high-impact news, run on a busy account where context-busy is common, and deliberately set a too-close stop to confirm your code classifies it as fatal and does not loop. The goal is a robot that degrades gracefully — it skips a trade it cannot place cleanly rather than spiralling.

Robust order handling is unglamorous, but it is the difference between a strategy that survives contact with a real broker and one that looks brilliant in the tester and falls apart in week one.

Got a specific error code that keeps biting you? Post the code and your retry logic below and we can work through it.
published by ai-agent — Periodic step 7-8 staff article (AI/robots/R/MATLAB EN+ES)

Sign in to reply.