首页 > 博客 > MT5「Not enough money」(134/10019)报错的7个原因及解决方法

MT5MQL5报错故障排除EA保证金

MT5「Not enough money」(134/10019)报错的7个原因及解决方法

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

彻底解决 ERR_NO_MONEY(MT5/MQL5)

运行EA时,如果在Expert标签页或日志中看到 ERR_NO_MONEYnot enough money,很多人会立刻联想到"资金不够了吗?",但实际上即使账户余额充足,这个错误也会出现。原因不仅仅是"资金为零",还包括手数计算、杠杆、已有持仓占用保证金等多种情况。

本文面向所有使用MT5运行EA的交易者,以及用MQL5开发EA的开发者,全面整理了 ERR_NO_MONEY本质、6个原因、可立即执行的对策、各经纪商的注意事项,以及在代码层面进行长期防范的方法,是一篇决定版指南。关于所有错误代码的汇总列表,请参阅MQL5 / MT5 错误代码处理综合指南

本文以2026年6月时的MT5(build 4xxx系列)为前提编写。具体数值和界面名称可能因经纪商或版本略有不同。


ERR_NO_MONEY 是什么(134 与 10019 的区别)

在MQL5中,表示"资金不足"的数值根据获取来源不同分为两种。如果混淆这两者,会导致排查原因走弯路。

① ERR_NO_MONEY = 134(GetLastError() 返回的运行时错误)

这是 GetLastError() 返回的运行时错误代码。当 OrderCalcMargin()OrderCalcProfit() 等计算类函数,或旧式代码判断"所需保证金超过可用保证金"时,会返回134。

含义: 交易操作所需资金不足(not enough money)
常量: ERR_NO_MONEY
值  : 134

② TRADE_RETCODE_NO_MONEY = 10019(OrderSend() 的返回代码)

在MQL5中实际下单时,OrderSend() 的结果会存入 MqlTradeResult.retcode。当下单被服务器拒绝时的"资金不足",不是134,而是10019(TRADE_RETCODE_NO_MONEY)。这并非MT5本身的错误,而是来自经纪商服务器的拒绝通知

含义: 执行订单所需资金不足(There is not enough money to complete the request)
常量: TRADE_RETCODE_NO_MONEY
值  : 10019
// 日志中常见的典型输出示例
2026.06.12 09:15:32.441 EA_NAME XAUUSD,H1: OrderSend error 10019

实务中的区分方法:

获取来源数值出现场景
GetLastError()134 (ERR_NO_MONEY)OrderCalcMargin 等计算、内部检查
MqlTradeResult.retcode10019 (TRADE_RETCODE_NO_MONEY)OrderSend 被服务器拒绝
CTrade.ResultRetcode()10019通过 CTrade 下单被拒绝

如果日志中出现"134",说明是计算/内部检查阶段;如果是"10019"或Expert标签页中的 not enough money,则说明是服务器拒绝阶段。两者的根本原因相同(所需保证金 > 可用保证金),因此对策也是通用的。


先用30秒完成初步排查

请打开MT5的"工具箱 → 交易"标签页,查看以下三项。

账户余额(Balance)        : 账户现金
净值(Equity)             : 余额 ± 浮动盈亏
可用保证金(Free Margin)   : 当前可用于新开仓的保证金 ← 关键在此
保证金比例(Margin Level %): Equity / Margin × 100
  • 如果可用保证金(Free Margin)小于即将建立的这一笔持仓所需的保证金 → 必然会出现 ERR_NO_MONEY。
  • 如果余额充足却仍然报错,则属于下文所述的"②手数过大"、"④已有持仓占用保证金"、"⑥账户类型不同"中的一种。

单笔持仓所需的保证金,可在MT5的"报价 → 右键点击品种 → 规格"中查看(1手所需保证金)。粗略计算公式如下。

所需保证金 ≈ (手数 × 合约大小 × 价格) / 杠杆

原因与对策(6种模式)

① 单纯资金不足

症状: 浮亏扩大,Free Margin 已低于新开仓所需数额。多见于连续亏损后或补仓(马丁)层数较深时。

对策:

  1. 追加入金,或
  2. 手动平掉部分持仓以回收保证金
  3. 调低EA的 RiskPercent,减小后续手数

如果这种情况反复出现,说明手数相对于资金本身就过大。请参见②。


② 手数过大(相对于账户余额而言)

症状: 余额明明充足,但从第一笔订单开始就出现 ERR_NO_MONEY。多见于固定手数运行方式。

原因: FixedLot 与账户余额、杠杆不匹配。例如在10万日元(≈$670)的账户上,以0.1手建立 XAUUSD 仓位时,根据杠杆不同,所需保证金可能超过账户余额。

对策:

  1. 先将固定手数降至最小(0.01),确认能否成功下单
  2. 切换为风险百分比自动计算(UseFixedLot=false / RiskPercent
  3. 若0.01手仍无法建仓,说明账户杠杆或资金不足 → 请参见③・⑥

参考标准:以10万日元(≈$670)标准账户、最小手数0.01起步是较为稳妥的设计基准。若资金低于此额度,或希望更安全地以小额运行,可考虑下文的"迷你(美分)账户"。


③ 杠杆过低/周末或重大事件导致杠杆被限制

症状: 同一个EA、同样的手数,在另一个账户上可以正常建仓,唯独这个账户出现 ERR_NO_MONEY。或者错误集中出现在周五傍晚到周一早上之间。

原因: 账户杠杆过低(例如1:30的欧盟监管账户 vs 1:1000的海外账户)会使所需保证金相差数十倍。此外,部分经纪商会在周末或重要经济数据公布前后下调杠杆(例如XM在周末会将杠杆限制为200:1),这会导致持仓期间所需保证金突然增加从而触发该错误。黄金和加密货币等品种有时还会单独设置更低的杠杆上限。

对策:

  1. 确认账户杠杆(经纪商会员页面/MT5账户信息)
  2. 确认品种规格中的"保证金比率"(部分品种可能单独设置较低比率)
  3. 使用周末前不持仓的设置(如 CloseAllBeforeWeekend=true),或改用没有周末杠杆限制的经纪商
  4. 切换至高杠杆账户,或降低手数

④ 已有持仓占用了保证金

症状: 第一笔仓位可以正常建立,但第二笔及以后、或补仓(马丁)时出现 ERR_NO_MONEY。

原因: 已持有的仓位占用了保证金,导致Free Margin低于新开仓所需数额。在同一账户上同时运行多个货币对或多个EA时容易出现此情况。

对策:

  1. 在"交易"标签页确认已用保证金(Margin)和 Free Margin
  2. 确认多个EA是否在同一账户中争夺保证金(多EA运行时)
  3. 通过EA参数限制同时持仓数量上限
  4. 补仓/网格类EA层数越深,保证金消耗越快 → 重新审视层数上限、手数倍率、紧急平仓等设置

⑤ 将赠金/信用额度计入了保证金

症状: 按"余额 + 赠金"计算本应足够,却仍出现 ERR_NO_MONEY。

原因: 部分经纪商的信用额度(赠金)不计入或仅部分计入保证金计算。这会导致显示余额与服务器实际使用的保证金出现偏差。

对策: 查阅经纪商的赠金条款,确认"信用额度是否计入保证金"。如果不计入,请仅按实际入金部分来设定能满足所需保证金的手数。


⑥ 账户类型的合约大小不同(标准账户 vs 美分/迷你账户)

症状: 同样是"0.01手",换了账户后突然出现 ERR_NO_MONEY;或者相反,变成手数过大。

原因: 美分(迷你)账户与标准账户的合约大小相差约100倍。 美分账户的0.01手,实际敞口约为标准账户的1/100。如果EA不区分账户类型而统一使用固定手数,可能在其中一种账户上出现保证金不足。

对策:

  1. 若资金较少、希望稳健运行,可使用美分/迷你账户,即使最小手数也不会形成过大风险
  2. EA设计上不应将账户类型写死,而应通过 OrderCalcMargin() 实时获取所需保证金来决定手数(详见下一章)

各经纪商的注意事项

经纪商特点ERR_NO_MONEY 出现频率
XM有周末杠杆限制・强平比例20%中(周末偏高)
Exness提供无限杠杆账户・强平比例0%
HFM / FXGT 等提供高杠杆账户

Exness的无限杠杆账户(Pro/Raw Spread账户)即使可用保证金几乎为零,很多情况下仍能成功下单,因此较少出现该错误。这类账户与补仓类EA的兼容性较好,但另一方面强平机制不易触发,存在亏损容易扩大的潜在风险,需要注意。经纪商对比请参阅经纪商对比页面


用MQL5代码防止该错误(面向EA开发者)

"解决"只是一方面,更正确的EA设计思路是在下单前就主动规避 ERR_NO_MONEY。关键在于"下单前先计算所需保证金,如果不足则不开仓/缩小手数"。

下单前检查所需保证金

// 下单前的检查关卡:确认 所需保证金 <= 可用保证金 后再执行 OrderSend
bool HasEnoughMargin(ENUM_ORDER_TYPE type, double lots)
{
   double price = (type == ORDER_TYPE_BUY)
                  ? SymbolInfoDouble(_Symbol, SYMBOL_ASK)
                  : SymbolInfoDouble(_Symbol, SYMBOL_BID);

   double margin = 0.0;
   if(!OrderCalcMargin(type, _Symbol, lots, price, margin))
   {
      Print("OrderCalcMargin failed: ", GetLastError()); // 134 等
      return false;
   }
   double freeMargin = AccountInfoDouble(ACCOUNT_MARGIN_FREE);
   if(margin > freeMargin)
   {
      PrintFormat("Skip: need %.2f > free %.2f (ERR_NO_MONEY guard)", margin, freeMargin);
      return false;   // 不开仓 = 提前防止 ERR_NO_MONEY
   }
   return true;
}

将手数归一化为最小手数与手数步长的倍数

如果直接发送按风险百分比计算出的原始数值,可能不符合最小手数、手数步长的要求而被拒绝(未做归一化处理是下单被拒的典型原因)。当手数不符合要求时,与其放弃,不如缩小到可执行的范围,这样可以减少错失交易机会的情况。

double NormalizeLot(double lots)
{
   double minLot  = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
   double maxLot  = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
   double step    = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
   lots = MathFloor(lots / step) * step;          // 按步长取整
   lots = MathMax(minLot, MathMin(maxLot, lots)); // 限定在最小~最大范围内
   return NormalizeDouble(lots, 2);
}

务必检查 OrderSend 的 retcode

不要只看 OrderSend() 的返回值(bool),还要检查 result.retcode,对10019(TRADE_RETCODE_NO_MONEY)进行单独处理。

MqlTradeRequest req; MqlTradeResult res;
ZeroMemory(req); ZeroMemory(res);
// ... 组装 req ...
if(!OrderSend(req, res) || res.retcode != TRADE_RETCODE_DONE)
{
   if(res.retcode == TRADE_RETCODE_NO_MONEY)   // 10019
      Print("Not enough money. 需要缩小手数或追加入金。");
   else
      PrintFormat("OrderSend failed: retcode=%d, lastError=%d", res.retcode, GetLastError());
}

如果使用CTrade类,可以通过 trade.ResultRetcode() 判断是否为10019,或用 trade.ResultRetcodeDescription() 查看具体说明。

基于保证金比例的紧急停止机制

设置一个安全机制:当保证金比例低于某个百分比时停止新开仓/全部平仓,可以同时防止 ERR_NO_MONEY 连续出现和账户爆仓。

double level = AccountInfoDouble(ACCOUNT_MARGIN_LEVEL); // 保证金比例%
if(level > 0 && level < EmergencyMarginLevel)          // 例如: 150%
{
   // 停止新开仓/如有必要可部分平仓
}

FXEA365提供的EA,标准配备了"风险百分比自动手数计算"、"下单前保证金检查"、"基于保证金比例的紧急停止(UseMarginEmergencyClose)"这三项机制,因此可以从较小资金起稳健运行。


优先级检查清单

优先级确认项对策
🚨 首先可用保证金 < 所需保证金 吗入金 或 部分平仓 或 降低手数
🚨 首先固定手数相对余额是否过大降至0.01/改为风险百分比自动计算
⚠️ 其次账户杠杆是否过低・是否受周末限制换高杠杆账户/周末平仓/降低手数
⚠️ 其次是否因已有持仓・其他EA占用保证金整理同一账户内的持仓
✅ 确认美分/标准账户的合约大小是否不同改用符合账户类型的手数
🛠 开发是否在下单前用 OrderCalcMargin 进行防护实现上述代码

总结

  • ERR_NO_MONEY 有**134(GetLastError)10019(OrderSend的retcode = TRADE_RETCODE_NO_MONEY)**两种表现形式,但根本原因都是"所需保证金 > 可用保证金"。
  • 即使账户有余额,也可能因手数过大、杠杆过低(含周末限制)、已有持仓占用保证金、账户类型不同而出现该错误。
  • EA使用者应通过"风险百分比自动手数"、"选择合适的账户类型"来预防;EA开发者则应通过"下单前 OrderCalcMargin 检查关卡"、"手数归一化"、"处理 retcode 10019"来实现长期根治。

关于所有错误代码,请参阅MQL5 / MT5 错误代码处理综合指南;若想使用能在稳健资金设置下运行的免费EA,请参阅EA一览。如果您正在使用本站的EA,且调整设置后问题仍未解决,请通过支持表单附上账户保证金状况的截图与我们联系。


常见问题

Q: 明明余额充足,却出现 ERR_NO_MONEY,这是为什么?

因为判断依据不是账户余额(Balance),而是可用保证金(Free Margin)。如果因浮亏或已有持仓占用保证金而导致Free Margin减少,即使余额充足也无法建立新仓位。请检查"交易"标签页中的Free Margin。

Q: 134 和 10019 有什么区别?

134(ERR_NO_MONEY)是 GetLastError() 返回的运行时错误,10019(TRADE_RETCODE_NO_MONEY)是 OrderSend() 的结果(retcode)。两者只是出现的位置不同,原因(资金不足)是相同的。

Q: 回测时没有出现,但实盘却出现了。

这是因为实盘账户的杠杆、账户类型(美分/标准)、已有持仓等与测试环境不同。特别是杠杆差异和合约大小差异影响较大。

Q: 补仓/网格类EA的层数变深后出现 ERR_NO_MONEY。

这已经接近正常现象的边缘了。层数越多,保证金消耗速度越快。建议降低层数上限、降低手数倍率,并务必启用 UseMarginEmergencyClose 等紧急平仓功能,同时只用可以承受损失的资金来运行。

Q: 可以通过EA代码自动规避这个问题吗?

可以。可以在下单前用 OrderCalcMargin() 计算所需保证金,如果超过 AccountInfoDouble(ACCOUNT_MARGIN_FREE),则不开仓(或缩小手数)。具体实现请参考正文中的代码示例。

Q: 最低需要多少资金才能稳健运行?

10万日元(≈$670)标准账户、最小手数0.01起步是较为稳妥的基准。如果资金更少,或希望更安全地运行,可以使用美分(迷你)账户,这样即使最小手数,实际敞口也会更小,更容易避免出现 ERR_NO_MONEY。

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

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

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

评论与提问