Five Broker-Safety Checks Every Production MQL5 Expert Advisor Needs
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.


