Five Broker-Safety Checks Every Production MQL5 Expert Advisor Needs

12 November 2026, 04:30
Li Lu
0
10

Many MetaTrader 5 prototypes look fine on a single demo symbol in Strategy Tester yet fail silently—or oversize risk—when deployed onto real multi-asset or prop-firm accounts. Below are five concrete execution and risk guards we build into production MQL5 Expert Advisors.

1. Risk Sizing With OrderCalcProfit Instead of Cached Tick Values

Relying on a cached SYMBOL_TRADE_TICK_VALUE multiplied by stop points breaks on cross pairs, index CFDs, and metals whenever conversion rates update—and silently falling back to SYMBOL_VOLUME_MIN on a small account can risk several multiples of the trader's budget. Instead, evaluate loss directly at the final normalized entry and stop prices with OrderCalcProfit , floor to the broker step, and skip the trade when even the minimum lot exceeds the cash risk cap:

double unitLoss = 0.0;
if(!OrderCalcProfit(orderType, symbol, 1.0, entryPrice, stopPrice, unitLoss) || unitLoss >= 0.0)
   return 0.0; // Fail closed when loss cannot be priced reliably

double rawLots  = maxCashRisk / (-unitLoss);
double normLots = FloorToBrokerStep(symbol, rawLots);
if(normLots < minVol)
   return 0.0; // Skip rather than violating risk budget with minVol

2. Exact Step Flooring for Non-Decimal Contracts

NormalizeDouble(lots, 2) corrupts crypto steps such as 0.001 and index/CFD steps such as 0.25 (and rounds 0.5`..`0.9 upward past your risk limit). Compute integer step units directly relative to SYMBOL_VOLUME_MIN and SYMBOL_VOLUME_STEP using MathFloor((vol - minVol + 1e-9) / step) .

3. Closing-Side StopsLevel, FreezeLevel & Tick-Size Validation

A Buy position closes at Bid and a Sell position closes at Ask. Validating stops against the entry side instead of the closing side triggers TRADE_RETCODE_INVALID_STOPS whenever spread widens. Snap all stop and target prices to SYMBOL_TRADE_TICK_SIZE (which differs from SYMBOL_POINT on symbols like XAUUSD and equity indices) and verify both SYMBOL_TRADE_STOPS_LEVEL and SYMBOL_TRADE_FREEZE_LEVEL before submitting or trailing.

4. Netting vs. Hedging Guards & Ambiguous Timeout Reconciliation

On ACCOUNT_MARGIN_MODE_RETAIL_NETTING accounts, sending a second order merges into a single position and overwrites protective stops. Enforce exclusive single-position ownership on netting symbols, inspect both the boolean return of CTrade and ResultRetcode() , and lock out duplicate bar entries if a request returns TRADE_RETCODE_TIMEOUT or TRADE_RETCODE_PLACED until order/deal history resolves.

5. Fail-Closed Native Economic Calendar Filtering

MQL5's built-in CalendarValueHistory avoids external DLLs and web scrapers, but two subtleties matter: if the calendar feed has not synced yet (returning false with a non-zero error), pause new entries rather than assuming "no news"; and in MQL_TESTER , require an explicit user setting when historical calendar replay is unavailable so backtest assumptions stay transparent.