Page 3 of 3

Re: MQL5: How to efficiently resolve "OrderSend error 130" during M1 scalping

Posted: Wed Sep 02, 2026 6:13 pm
by PTScalper
Because broker implementations of MT5 vary wildly, hardcoding ORDER_FILLING_FOK or ORDER_FILLING_IOC will inevitably crash your EA when deployed across different liquidity providers. Some ECNs strictly require IOC, while standard STP accounts might only accept FOK or RETURN.

In MQL5, SYMBOL_FILLING_MODE is returned as a bitmask. You cannot use a simple equality check (==); you must use bitwise AND (&) operations to parse the supported modes.

Here is how to dynamically evaluate the broker's matching engine and apply the correct policy to your MqlTradeRequest.

1. The Dynamic Filling Mode Evaluator

Because you have already built an architecture capable of tracking Volume Weighted Average Price (VWAP) across partial fills, Immediate or Cancel (IOC) is your mathematically superior choice. It guarantees you sweep available liquidity without leaving passive orders on the book.

Fill or Kill (FOK) is "safer" from a math perspective (no slippage via partials), but when pushing high-volume lots, FOK will result in massive rejection rates because the book rarely has enough liquidity at a single price level to absorb the entire order instantly.

This helper function prioritizes IOC but safely falls back to whatever the broker allows.

Code: Select all

ENUM_ORDER_TYPE_FILLING GetOptimalFillingMode(const string symbol) 
{
    long fillModes = SymbolInfoInteger(symbol, SYMBOL_FILLING_MODE);
    
    // 1. Prioritize IOC for high-volume sweeping (Partials allowed, remainder killed)
    if ((fillModes & SYMBOL_FILLING_IOC) != 0) 
    {
        return ORDER_FILLING_IOC;
    }
    
    // 2. Fallback to FOK (No partials, entire order must fill instantly or be killed)
    if ((fillModes & SYMBOL_FILLING_FOK) != 0) 
    {
        return ORDER_FILLING_FOK;
    }
    
    // 3. Last resort: RETURN (Standard for Market Maker/B-Book accounts)
    // Warning: This leaves unfilled remainder as a resting limit order.
    return ORDER_FILLING_RETURN; 
}

Re: MQL5: How to efficiently resolve "OrderSend error 130" during M1 scalping

Posted: Wed Sep 02, 2026 6:13 pm
by PTScalper
2. Applying the Policy to the Entry Request

When constructing your initial OrderSendAsync market entry, call the evaluator and assign its result to request.type_filling.

Code: Select all

void DispatchInitialEntry(double targetVolume, ENUM_ORDER_TYPE direction) 
{
    MqlTradeRequest request = {};
    MqlTradeResult  result  = {};
    
    request.action       = TRADE_ACTION_DEAL;
    request.symbol       = _Symbol;
    request.volume       = targetVolume;
    request.deviation    = 20; // Acceptable slippage in points
    request.magic        = 123456;
    
    // Dynamically apply the safest supported execution policy
    request.type_filling = GetOptimalFillingMode(_Symbol);
    
    if (direction == ORDER_TYPE_BUY) 
    {
        request.type  = ORDER_TYPE_BUY;
        request.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
    }
    else 
    {
        request.type  = ORDER_TYPE_SELL;
        request.price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
    }

    // Since this is an ECN environment, DO NOT attach SL/TP on entry
    request.sl = 0.0;
    request.tp = 0.0;

    if (!OrderSendAsync(request, result)) 
    {
        PrintFormat("Entry Dispatch Failed! Error: %d", GetLastError());
    }
    else 
    {
        PrintFormat("Async Entry Dispatched. Request ID: %u | Policy: %s", 
                    result.request_id, EnumToString(request.type_filling));
        
        // Initialize your state tracker here
        // ActiveTrades[index].state = STATE_ENTRY_PENDING;
        // ...
    }
}

Re: MQL5: How to efficiently resolve "OrderSend error 130" during M1 scalping

Posted: Wed Sep 02, 2026 6:13 pm
by PTScalper
The Broker-Side "Zero Mode" Edge Case

There is a known edge case with certain MT5 server bridges (particularly poorly configured White Label brokers) where SymbolInfoInteger(_Symbol, SYMBOL_FILLING_MODE) returns 0, falsely implying the symbol supports no filling modes at all.

If your EA hits a broker returning 0, the bitwise checks will fail and the function will default to ORDER_FILLING_RETURN. On a true ECN, sending a RETURN policy will trigger an immediate TRADE_RETCODE_INVALID_FILL (10030) rejection.

If you encounter this specific server misconfiguration, you must bypass SYMBOL_FILLING_MODE entirely and hardcode request.type_filling = ORDER_FILLING_FOK; or ORDER_FILLING_IOC; to force the request through the bridge.

Re: MQL5: How to efficiently resolve "OrderSend error 130" during M1 scalping

Posted: Sat Oct 03, 2026 1:21 pm
by LondonNewsTrader
PTScalper wrote: The two most critical transaction types for this workflow are TRADE_TRANSACTION_DEAL_ADD (when your entry actually fills) and TRADE_TRANSACTION_REQUEST (when the broker formally accepts or rejects your async request).
The comment on the failure branch mentions the freeze level, but the code only handles TRADE_RETCODE_INVALID_STOPS and TRADE_RETCODE_REQUOTE. A modification rejected because the stop is inside the freeze level comes back as TRADE_RETCODE_FROZEN, which matches neither branch, so the trade sits in STATE_STOPS_PENDING indefinitely with no stops and no retry. Some brokers raise freeze and stop levels around releases, so that is exactly when it would happen.

Two other things I'd tighten. The DEAL_ADD lookup uses trans.position, but before the fill you only know the request id and then the order ticket, so the map needs to go request id, then order, then position. And the retry path should recalculate the stop from the current price and the stop level rather than resend the same one. If the spike carried price through the intended stop, resending it will fail every time.

I'd also put a ceiling on retry_count. After a few failures, closing the unprotected position is cheaper than holding it naked through a fast market.

Re: MQL5: How to efficiently resolve "OrderSend error 130" during M1 scalping

Posted: Mon Oct 19, 2026 11:31 am
by FXS Prop Desk
Clear explanation of the error. One more check worth adding: the symbol's freeze level, which prevents modifying orders when price is close to the stop or target. During fast markets on M1, an EA may pass the stop-level check on entry but then fail to modify the position later because of the freeze level.

Logging the actual stop level, freeze level and spread at the time of each error also helps identify whether a specific broker or time of day causes the problem.

For M1 scalpers on MT5, another source of 10016 is calculating the stop from the ask for a buy order (or the bid for a sell) when the spread is wide. The stop-level distance is measured from the price at which the position would close, so buy stops are checked against the bid and sell stops against the ask. Building a helper that takes direction, entry type and desired distance, and returns a valid normalised stop, keeps the logic in one place and avoids the error in every order function.