首页 > 博客 > 彻底解决Unsupported filling mode(MT5错误10030)

MT5MQL5错误故障排查EA

彻底解决Unsupported filling mode(MT5错误10030)

发布日: 2026-07-07阅读时间:约 2 分钟
本文为发布之日的信息。EA的业绩数值(PF、DD、年化)会随实盘运行与重新验证而变动,最新数值请在各EA页面确认。 查看最新EA业绩

彻底解决Unsupported filling mode(MT5错误10030)

昨天还在别的经纪商正常运行的EA,一转到新账户,Expert标签页里就接连出现 Unsupported filling modeOrderSend error 10030导致一笔订单都下不出去——这是MT5使用EA时更换经纪商最常见的典型故障之一。这并不代表EA坏了,也不代表账户有问题。问题仅仅在于:订单指定的"填单方式(filling mode)"在新经纪商的该品种上不被允许而已。

本文面向使用MT5运行EA的交易者,以及用MQL5编写EA的开发者,将TRADE_RETCODE_INVALID_FILL(10030)的真相、FOK/IOC/RETURN的含义、30秒即可完成的排查方法,以及代码层面的根治方案一次性整理清楚。关于错误代码的完整列表,请参阅MQL5 / MT5 错误代码处理综合指南

本文以2026年7月时点的MT5(build 4xxx系列)为前提。界面名称与表述可能因经纪商或版本略有差异。


什么是10030(TRADE_RETCODE_INVALID_FILL)

OrderSend() 的执行结果会写入 MqlTradeResult.retcode。其中返回的 10030 = TRADE_RETCODE_INVALID_FILL,是服务器端的拒绝通知,意思是"请求中指定的 type_filling(填单方式)在该品种上不被允许"。

含义: 指定的填单方式(filling type)不被支持
常量: TRADE_RETCODE_INVALID_FILL
值  : 10030
显示: Unsupported filling mode / Invalid order filling type
// 日志中常见的典型输出示例
2026.07.07 09:15:32.441 EA_NAME EURUSD,M15: OrderSend error 10030
2026.07.07 09:15:32.441 EA_NAME EURUSD,M15: failed market buy 0.10 EURUSD [Unsupported filling mode]

关键点在于,这与资金、手数、价格完全无关。10030仅仅是请求中 MqlTradeRequest.type_filling 这一个字段的问题,只要修正它,同一笔订单就能顺利通过。

填单方式(type_filling)的四种类型

MQL5的 ENUM_ORDER_TYPE_FILLING 中共有4个取值。

常量通称含义
ORDER_FILLING_FOKFill or Kill仅在能全部成交时才执行。若1手订单只有0.7手的流动性,则整笔订单取消
ORDER_FILLING_IOCImmediate or Cancel能成交多少就立即成交多少剩余部分取消。0.7手成交,0.3手作废
ORDER_FILLING_RETURNReturn执行可成交的部分,剩余数量作为挂单留在盘口(等待后续成交)。多用于交易所式执行
ORDER_FILLING_BOCBook or Cancel仅在能挂入盘口(被动等待成交)时才接受,若价格会立即成交则拒绝。专用于限价/止损限价单(较新版本中新增)

在常见的外汇EA中,实际使用的几乎都是FOK或IOC。RETURN主要用于股票、期货等交易所式执行(Exchange execution),BOC则是需要强制挂单(Maker)的特殊用途。

为什么会"不合法"——SYMBOL_FILLING_MODE

接受哪种填单方式,是由经纪商针对每个品种设置的标志位SYMBOL_FILLING_MODE)决定的。可在MQL5中这样读取:

long flags = SymbolInfoInteger(_Symbol, SYMBOL_FILLING_MODE);
// 若 SYMBOL_FILLING_FOK 标志位置1,则允许 FOK
// 若 SYMBOL_FILLING_IOC 标志位置1,则允许 IOC

SYMBOL_FILLING_MODE 是位标志,包含FOK和IOC的允许情况(若两者都允许,则两个标志位都会置1)。RETURN不包含在此标志位中,能否使用取决于该品种的执行模式(后文详述)。

也就是说,10030的成因非常简单:

EA发送的 type_filling ∉ 该品种允许的填单方式 → 10030

仅此而已。


为什么偏偏在"更换经纪商当天"出现

10030之所以被称为"更换经纪商的经典错误",原因如下:

  1. 允许的填单方式因经纪商、品种而异。 有的经纪商对外汇品种只允许FOK,有的只允许IOC,还有的两者都允许。即便在同一经纪商内,外汇与CFD、股票之间的设置也常常不同。
  2. 许多EA将type_filling写死在代码中。 例如写有 request.type_filling = ORDER_FILLING_FOK; 的EA,在允许FOK的经纪商A上可以运行多年而毫无问题。由于在作者的环境中一直正常运行,这个问题往往不会被当作bug识别出来。
  3. 一旦转移到不允许FOK的经纪商B,从第一笔下单开始就全部失败。 由于策略测试器的成交处理往往比真实服务器宽松,这个问题在回测中常常不会暴露,而是恰好在转到实盘账户当天才显现出来。

也就是说,10030与其说是EA的bug,不如说是"对运行环境的想当然假设"被暴露了出来。反过来说,只要改为读取品种的允许标志位并动态选择填单方式,EA就能在任何经纪商上正常运行(具体代码见后文)。

与执行模式(SYMBOL_TRADE_EXEMODE)的关系

除填单方式外,品种还有执行模式这一属性,它会影响哪种填单方式真正有意义。

执行模式常量典型场景填单方式倾向
InstantSYMBOL_TRADE_EXECUTION_INSTANT部分外汇品种(多见于做市商模式)按指定价格执行。FOK/IOC与拒price(requote)并存
MarketSYMBOL_TRADE_EXECUTION_MARKET多数外汇/CFD(无交易台模式)市价执行。FOK或IOC(取决于经纪商设置)
ExchangeSYMBOL_TRADE_EXECUTION_EXCHANGE股票、期货挂入盘口执行。以RETURN为基本方式
RequestSYMBOL_TRADE_EXECUTION_REQUEST遗留模式请求式执行(目前罕见)

严格来说,具体允许哪种组合取决于经纪商的服务器设置,但实务上只需记住"外汇/CFD的Market执行通常是FOK或IOC,交易所式品种则以RETURN为前提"即可。执行模式也可以通过 SymbolInfoInteger(_Symbol, SYMBOL_TRADE_EXEMODE) 确认。


先用30秒完成初步排查

① 查看品种的允许方式(MT5界面)

打开**"市场报价" → 右键点击品种 → 规格(Specification),查看"填充"(Filling)**这一行。会显示 Fill or Kill / Immediate or Cancel 或两者皆有。若EA发送的方式没有出现在这里,即可确定是10030问题

② 查看EA的输入参数

设计良好的EA通常会提供 FillingType / Filling Mode 之类的输入参数。如果有,只需按①中确认的允许方式进行修改即可解决问题(无需改代码)。

③ 用代码确认(面向开发者)

long flags = SymbolInfoInteger(_Symbol, SYMBOL_FILLING_MODE);
PrintFormat("%s filling: FOK=%s IOC=%s exemode=%d",
            _Symbol,
            ((flags & SYMBOL_FILLING_FOK) != 0) ? "yes" : "no",
            ((flags & SYMBOL_FILLING_IOC) != 0) ? "yes" : "no",
            (int)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_EXEMODE));

用脚本执行以上代码,即可在一行输出中看到该经纪商、该品种的实际允许情况。


根治方案——读取允许标志位自动选择的MQL5代码

10030的正确解决方式并非"每次更换经纪商都手动调整",而是让EA自身读取品种的允许标志位并自动选择填单方式。以下是可以直接使用的标准实现。

自动判断函数

// 返回该品种实际允许的填单方式
// 优先级: FOK → IOC → RETURN(交易所式的兜底方案)
ENUM_ORDER_TYPE_FILLING GetFillingMode(const string symbol)
{
   long flags = SymbolInfoInteger(symbol, SYMBOL_FILLING_MODE);

   if((flags & SYMBOL_FILLING_FOK) != 0)
      return ORDER_FILLING_FOK;    // 仅在能全部成交时执行(不产生部分成交)

   if((flags & SYMBOL_FILLING_IOC) != 0)
      return ORDER_FILLING_IOC;    // 能成交多少就执行多少,剩余取消

   return ORDER_FILLING_RETURN;    // 无标志位 = 交易所式等情况,使用RETURN发送
}

在OrderSend中的用法

MqlTradeRequest req; MqlTradeResult res;
ZeroMemory(req); ZeroMemory(res);

req.action       = TRADE_ACTION_DEAL;
req.symbol       = _Symbol;
req.volume       = lots;
req.type         = ORDER_TYPE_BUY;
req.price        = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
req.deviation    = 20;
req.magic        = MagicNumber;
req.type_filling = GetFillingMode(_Symbol);   // ← 不再写死

if(!OrderSend(req, res) || res.retcode != TRADE_RETCODE_DONE)
{
   if(res.retcode == TRADE_RETCODE_INVALID_FILL)   // 10030
      PrintFormat("Unsupported filling mode: sent=%d, allowed flags=%d",
                  (int)req.type_filling,
                  (int)SymbolInfoInteger(_Symbol, SYMBOL_FILLING_MODE));
   else
      PrintFormat("OrderSend failed: retcode=%d", res.retcode);
}

这样一来,无论是仅支持FOK的经纪商,还是仅支持IOC的经纪商,同一份程序都能正常运行,不再需要每次更换经纪商都手动调整。

使用CTrade的情况

标准库中的 CTrade 提供了 SetTypeFillingBySymbol(),可根据品种的允许标志位自动设置填单方式。

#include <Trade/Trade.mqh>
CTrade trade;

int OnInit()
{
   trade.SetExpertMagicNumber(MagicNumber);
   trade.SetTypeFillingBySymbol(_Symbol);   // 读取允许标志位并自动设置
   return INIT_SUCCEEDED;
}

如果EA是因为旧式写法 trade.SetTypeFilling(ORDER_FILLING_FOK);(写死指定)而出现10030,只需替换为这一行即可解决。若想手动指定,也可以将前述 GetFillingMode() 的返回值传给 SetTypeFilling(),效果相同。

使用限价单(BOC)时的注意事项

ORDER_FILLING_BOC(Book or Cancel)专用于限价单、止损限价单,若指定的价格会立即成交,则会被拒绝。将其用于市价单是错误用法,市价类EA无需将BOC纳入选项。


关于经纪商的注意事项(更换时需重新确认)

  • 填单方式的允许设置不仅因经纪商而异,即使在同一经纪商内,也会因品种(品种分组)不同而不同。 外汇允许IOC,而股票CFD仅允许RETURN,这种配置很常见。
  • 账户类型或服务器变更也可能导致设置发生变化。 不仅是更换经纪商,在同一经纪商内的服务器迁移、账户类型变更、品种规格修订后,也可能突然出现10030。
  • 因此,作为运维规则,建议养成"只要账户、服务器、品种中任一项发生变化,就在规格界面(或脚本中)重新确认填单方式"的习惯,这样更为稳妥。若EA已内置自动判断代码,则这项确认本身也就不再需要了。

由于特定经纪商"该品种仅支持FOK"之类的信息会随服务器设置变更而过时,本文不做具体列举。请务必以自己账户的品种规格为准进行确认


优先级检查清单

优先级确认事项处理方法
🚨 首先品种规格中的"填充"一栏与EA指定的方式是否一致改为使用允许的方式
🚨 首先EA是否有FillingType输入参数仅需修改参数即可解决(无需改代码)
⚠️ 其次EA代码中type_filling是否被写死替换为GetFillingMode() / SetTypeFillingBySymbol()
⚠️ 其次是否更换过经纪商、服务器、账户类型变更后务必重新确认规格
✅ 确认执行模式(Instant/Market/Exchange)的差异交易所式品种以RETURN为前提
🛠 开发是否针对10030的retcode进行了单独处理记录发送的方式与允许标志位的日志

总结

  • Unsupported filling mode10030 / TRADE_RETCODE_INVALID_FILL)是当订单的 type_filling(FOK / IOC / RETURN / BOC)在该品种上不被允许时,服务器发出的拒绝通知,与资金或手数无关。
  • 由于允许的方式因经纪商、品种而异,将type_filling写死的EA会在更换经纪商当天集中出现10030,这是该错误的典型模式。
  • 用户只需"查看品种规格的填充栏 → 修改EA的输入参数"即可立即解决。开发者则可以通过读取 SymbolInfoInteger(SYMBOL_FILLING_MODE) 的标志位自动选择(或使用 CTrade::SetTypeFillingBySymbol())来实现根治

关于错误代码的完整内容,请参阅MQL5 / MT5 错误代码处理综合指南。FXEA365提供的EA均已实现填单方式的自动判断,无论使用哪家经纪商都能正常运行(EA一览)。


常见问题

Q: 昨天还能正常运行的EA,换了经纪商之后完全无法下单,一直报10030,是EA坏了吗?

并非EA故障。只是EA指定的填单方式(例如FOK)在新经纪商的该品种上不被允许而已。请确认品种规格中的"填充"一栏,调整EA的输入参数(如FillingType),或将代码改为自动判断方式,即可恢复正常运行。

Q: FOK和IOC应该用哪个?

如果品种两者都允许,两者的差异主要体现在"流动性不足时"。FOK在无法全部成交时会取消整笔订单(不会产生仓位不完整的情况),IOC则只持有能成交的部分(可能产生部分成交)。对于个人外汇交易的手数规模而言,流动性不足本身较为少见,实际使用中两者差别不大。像自动判断代码那样以FOK优先并无问题。

Q: 回测中不出现,但实盘账户却报10030,这是为什么?

策略测试器的成交处理无法完全还原真实服务器的设置,因此type_filling不匹配的问题有时不会在测试中暴露出来。建议在实盘或模拟账户首次运行时,先核对品种规格中的填充栏。

Q: 同一家经纪商,为什么有的品种报10030,有的不报?

这是正常(可能出现)的现象。填单方式的允许设置是按品种单独配置的,因此外汇货币对允许IOC、股票CFD仅允许RETURN这类差异,会因品种分组而不同。多品种EA务必针对每个品种分别读取 SYMBOL_FILLING_MODE

Q: 无法修改EA代码(只持有.ex5文件),该怎么办?

请先确认EA的输入参数中是否有FillingType相关选项。如果没有,说明该EA在当前经纪商的该品种上无法使用。可以联系作者请求支持,或者改用允许该EA所依赖的填单方式的经纪商/账户类型进行运营。

📧 涨价预告 + 免费5天邮件课程

所有EA目前均为首发价,并将随销量阶梯式上调。在每次涨价前收到通知,另有每日一封邮件:自动交易本质、正确解读回测、券商选择技巧。

※ 严格保护隐私。可随时取消订阅。

评论与提问