MQL5 Error 10030 Unsupported Filling Mode: How to Fix It (EA Code + Real Backtest)

Published 2026-11-03 · Ranar Algo

To fix MQL5 error 10030 ("Unsupported filling mode", TRADE_RETCODE_INVALID_FILL), stop hard-coding type_filling. Read the symbol's allowed policies with SymbolInfoInteger(_Symbol, SYMBOL_FILLING_MODE), test the SYMBOL_FILLING_FOK and SYMBOL_FILLING_IOC bit flags, and only use ORDER_FILLING_RETURN when the symbol is not in Market Execution mode. Set the result in MqlTradeRequest.type_filling before every OrderSend().

Why the error happens

Every MT5 symbol tells the terminal which volume filling policies the broker accepts. When your EA sends a market order with a policy the server does not allow, the request is rejected with retcode 10030 and no position is opened. It is one of the most common reasons an EA that "works on my demo" does nothing on another broker: the code was written for one account and copied to another with a different execution model.

Two details from the MQL5 documentation cause most of the confusion:

The filling policies themselves mean:

The fix: choose the policy from the symbol

This helper follows the documented rules. It prefers FOK, falls back to IOC, then RETURN when the execution mode allows it:

ENUM_ORDER_TYPE_FILLING PickFilling(const string sym)
{
   long modes=SymbolInfoInteger(sym,SYMBOL_FILLING_MODE);
   long exe  =SymbolInfoInteger(sym,SYMBOL_TRADE_EXEMODE);
   if((modes&SYMBOL_FILLING_FOK)==SYMBOL_FILLING_FOK) return ORDER_FILLING_FOK;
   if((modes&SYMBOL_FILLING_IOC)==SYMBOL_FILLING_IOC) return ORDER_FILLING_IOC;
   if(exe!=SYMBOL_TRADE_EXECUTION_MARKET)              return ORDER_FILLING_RETURN;
   return ORDER_FILLING_IOC;
}

Call it per request (q.type_filling = PickFilling(_Symbol);). Do not cache it once in OnInit() for every symbol if your EA trades several instruments, because each symbol can have different settings.

If you use the standard library instead of raw OrderSend(), CTrade already has this: call trade.SetTypeFillingBySymbol(_Symbol) after creating the object. Per the docs, when both FOK and IOC are allowed it picks FOK, same as the helper above. That is the lazy, correct option for most EAs.

Full working EA

Here is a complete EMA crossover EA that uses the helper, trades only on a new bar, reads closed bars from CopyBuffer() (shift 1, so signals do not repaint), and logs the retcode plus the filling it tried when a request fails. That log line is what you want when a user on another broker says "it doesn't trade".

#property version "1.00"
input int    FastMA   = 10;
input int    SlowMA   = 30;
input double Lots     = 0.10;
input int    SL_Points= 300;
input int    TP_Points= 600;
int hFast=INVALID_HANDLE, hSlow=INVALID_HANDLE;

ENUM_ORDER_TYPE_FILLING PickFilling(const string sym)
{
   long modes=SymbolInfoInteger(sym,SYMBOL_FILLING_MODE);
   long exe  =SymbolInfoInteger(sym,SYMBOL_TRADE_EXEMODE);
   if((modes&SYMBOL_FILLING_FOK)==SYMBOL_FILLING_FOK) return ORDER_FILLING_FOK;
   if((modes&SYMBOL_FILLING_IOC)==SYMBOL_FILLING_IOC) return ORDER_FILLING_IOC;
   if(exe!=SYMBOL_TRADE_EXECUTION_MARKET)              return ORDER_FILLING_RETURN;
   return ORDER_FILLING_IOC;
}

bool Open(const ENUM_ORDER_TYPE type)
{
   MqlTradeRequest q; MqlTradeResult r; ZeroMemory(q); ZeroMemory(r);
   MqlTick t; if(!SymbolInfoTick(_Symbol,t)) return false;
   double price=(type==ORDER_TYPE_BUY)?t.ask:t.bid;
   double dir  =(type==ORDER_TYPE_BUY)?1.0:-1.0;
   q.action      =TRADE_ACTION_DEAL;
   q.symbol      =_Symbol;
   q.volume      =Lots;
   q.type        =type;
   q.price       =price;
   q.sl          =NormalizeDouble(price-dir*SL_Points*_Point,_Digits);
   q.tp          =NormalizeDouble(price+dir*TP_Points*_Point,_Digits);
   q.deviation   =10;
   q.type_filling=PickFilling(_Symbol);
   if(!OrderSend(q,r))
   {
      PrintFormat("OrderSend failed: retcode=%u filling=%s",r.retcode,EnumToString(q.type_filling));
      return false;
   }
   return r.retcode==TRADE_RETCODE_DONE || r.retcode==TRADE_RETCODE_PLACED;
}

int OnInit()
{
   hFast=iMA(_Symbol,_Period,FastMA,0,MODE_EMA,PRICE_CLOSE);
   hSlow=iMA(_Symbol,_Period,SlowMA,0,MODE_EMA,PRICE_CLOSE);
   if(hFast==INVALID_HANDLE || hSlow==INVALID_HANDLE) return INIT_FAILED;
   PrintFormat("Filling chosen for %s: %s",_Symbol,EnumToString(PickFilling(_Symbol)));
   return INIT_SUCCEEDED;
}
void OnDeinit(const int reason){ IndicatorRelease(hFast); IndicatorRelease(hSlow); }

void OnTick()
{
   static datetime last=0;
   datetime bar=iTime(_Symbol,_Period,0);
   if(bar==last) return;
   last=bar;
   double f[],s[];
   if(CopyBuffer(hFast,0,1,2,f)<2 || CopyBuffer(hSlow,0,1,2,s)<2) return;
   if(PositionSelect(_Symbol)) return;
   if(f[0]<=s[0] && f[1]>s[1]) Open(ORDER_TYPE_BUY);
   else if(f[0]>=s[0] && f[1]<s[1]) Open(ORDER_TYPE_SELL);
}

Note the return check: OrderSend() returning true only means the request was accepted for processing. The actual outcome is in MqlTradeResult.retcode, so check for TRADE_RETCODE_DONE (or TRADE_RETCODE_PLACED) and log anything else.

Real backtest of this exact EA

We compiled the EA above and ran it in the MetaTrader 5 Strategy Tester (MetaQuotes-Demo data). The point of the test was to confirm the filling logic places trades without a single 10030 rejection. It is not a profitable strategy and is not presented as one:

116 orders filled with no filling errors, which is what the article is about. A plain 10/30 EMA cross with a fixed 300/600 point SL/TP lost money over this period, a useful reminder that order plumbing and strategy edge are separate problems. Past performance does not guarantee future results.

Quick checklist when you see 10030

Generating EAs that get this right

Ranar Algo, the tool behind this blog, turns a plain-English strategy description into MQL5 source, compiles it, and runs a real MT5 backtest, so issues like a wrong filling mode show up before you ever attach the EA to a chart. You get the source code and keep the IP. It is still being improved, and feedback on what it gets wrong is welcome.

Summary

Error 10030 is not a broker bug. It means your EA asked for a filling policy the symbol does not allow. Read SYMBOL_FILLING_MODE as bit flags, respect the Market Execution rule for RETURN, set type_filling on every request, and check retcode after OrderSend(). Your EA will then work across brokers without edits.

Build & backtest your own EA free →

Ranar Algo turns a plain-English strategy into a compiled MQL5 Expert Advisor with a real MetaTrader 5 backtest. You keep your IP. Past performance does not guarantee future results.