MT5「Not enough money」(134/10019)报错的7个原因及解决方法
目录
- ERR_NO_MONEY 是什么(134 与 10019 的区别)
- ① ERR_NO_MONEY = 134(`GetLastError()` 返回的运行时错误)
- ② TRADE_RETCODE_NO_MONEY = 10019(`OrderSend()` 的返回代码)
- 先用30秒完成初步排查
- 原因与对策(6种模式)
- ① 单纯资金不足
- ② 手数过大(相对于账户余额而言)
- ③ 杠杆过低/周末或重大事件导致杠杆被限制
- ④ 已有持仓占用了保证金
- ⑤ 将赠金/信用额度计入了保证金
- ⑥ 账户类型的合约大小不同(标准账户 vs 美分/迷你账户)
- 各经纪商的注意事项
- 用MQL5代码防止该错误(面向EA开发者)
- 下单前检查所需保证金
- 将手数归一化为最小手数与手数步长的倍数
- 务必检查 OrderSend 的 retcode
- 基于保证金比例的紧急停止机制
- 优先级检查清单
- 总结
- 常见问题
- Q: 明明余额充足,却出现 ERR_NO_MONEY,这是为什么?
- Q: 134 和 10019 有什么区别?
- Q: 回测时没有出现,但实盘却出现了。
- Q: 补仓/网格类EA的层数变深后出现 ERR_NO_MONEY。
- Q: 可以通过EA代码自动规避这个问题吗?
- Q: 最低需要多少资金才能稳健运行?
彻底解决 ERR_NO_MONEY(MT5/MQL5)
运行EA时,如果在Expert标签页或日志中看到 ERR_NO_MONEY 或 not 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.retcode | 10019 (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 已低于新开仓所需数额。多见于连续亏损后或补仓(马丁)层数较深时。
对策:
- 追加入金,或
- 手动平掉部分持仓以回收保证金
- 调低EA的
RiskPercent,减小后续手数
如果这种情况反复出现,说明手数相对于资金本身就过大。请参见②。
② 手数过大(相对于账户余额而言)
症状: 余额明明充足,但从第一笔订单开始就出现 ERR_NO_MONEY。多见于固定手数运行方式。
原因: FixedLot 与账户余额、杠杆不匹配。例如在10万日元(≈$670)的账户上,以0.1手建立 XAUUSD 仓位时,根据杠杆不同,所需保证金可能超过账户余额。
对策:
- 先将固定手数降至最小(0.01),确认能否成功下单
- 切换为风险百分比自动计算(
UseFixedLot=false/RiskPercent) - 若0.01手仍无法建仓,说明账户杠杆或资金不足 → 请参见③・⑥
参考标准:以10万日元(≈$670)标准账户、最小手数0.01起步是较为稳妥的设计基准。若资金低于此额度,或希望更安全地以小额运行,可考虑下文的"迷你(美分)账户"。
③ 杠杆过低/周末或重大事件导致杠杆被限制
症状: 同一个EA、同样的手数,在另一个账户上可以正常建仓,唯独这个账户出现 ERR_NO_MONEY。或者错误集中出现在周五傍晚到周一早上之间。
原因: 账户杠杆过低(例如1:30的欧盟监管账户 vs 1:1000的海外账户)会使所需保证金相差数十倍。此外,部分经纪商会在周末或重要经济数据公布前后下调杠杆(例如XM在周末会将杠杆限制为200:1),这会导致持仓期间所需保证金突然增加从而触发该错误。黄金和加密货币等品种有时还会单独设置更低的杠杆上限。
对策:
- 确认账户杠杆(经纪商会员页面/MT5账户信息)
- 确认品种规格中的"保证金比率"(部分品种可能单独设置较低比率)
- 使用周末前不持仓的设置(如
CloseAllBeforeWeekend=true),或改用没有周末杠杆限制的经纪商 - 切换至高杠杆账户,或降低手数
④ 已有持仓占用了保证金
症状: 第一笔仓位可以正常建立,但第二笔及以后、或补仓(马丁)时出现 ERR_NO_MONEY。
原因: 已持有的仓位占用了保证金,导致Free Margin低于新开仓所需数额。在同一账户上同时运行多个货币对或多个EA时容易出现此情况。
对策:
- 在"交易"标签页确认已用保证金(Margin)和 Free Margin
- 确认多个EA是否在同一账户中争夺保证金(多EA运行时)
- 通过EA参数限制同时持仓数量上限
- 补仓/网格类EA层数越深,保证金消耗越快 → 重新审视层数上限、手数倍率、紧急平仓等设置
⑤ 将赠金/信用额度计入了保证金
症状: 按"余额 + 赠金"计算本应足够,却仍出现 ERR_NO_MONEY。
原因: 部分经纪商的信用额度(赠金)不计入或仅部分计入保证金计算。这会导致显示余额与服务器实际使用的保证金出现偏差。
对策: 查阅经纪商的赠金条款,确认"信用额度是否计入保证金"。如果不计入,请仅按实际入金部分来设定能满足所需保证金的手数。
⑥ 账户类型的合约大小不同(标准账户 vs 美分/迷你账户)
症状: 同样是"0.01手",换了账户后突然出现 ERR_NO_MONEY;或者相反,变成手数过大。
原因: 美分(迷你)账户与标准账户的合约大小相差约100倍。 美分账户的0.01手,实际敞口约为标准账户的1/100。如果EA不区分账户类型而统一使用固定手数,可能在其中一种账户上出现保证金不足。
对策:
- 若资金较少、希望稳健运行,可使用美分/迷你账户,即使最小手数也不会形成过大风险
- 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目前均为首发价,并将随销量阶梯式上调。在每次涨价前收到通知,另有每日一封邮件:自动交易本质、正确解读回测、券商选择技巧。
※ 严格保护隐私。可随时取消订阅。