What it means
The account's free margin can't cover the margin the new position would need, so the server refuses the order. It's about margin, the collateral the broker holds while the position is open, not about how much the trade could lose.
Usual causes
- A volume too large for the account. A fixed lot set for a bigger account, or a lot size computed without any margin check.
- More margin per lot than you assume. Margin depends on the symbol, its price, its contract size and the account's leverage. A lot of gold, an index or a crypto CFD can need much more margin than a lot of a forex pair.
- Margin already in use. Open positions reduce free margin, and on some accounts pending orders do too.
- A small test deposit. A Strategy Tester run with a small deposit and a fixed lot. MetaQuotes' own checklist for Market products suggests testing with a very small deposit precisely to catch this.
How to detect it
result.retcode(ortrade.ResultRetcode()) is10019; the Experts tab shows[not enough money]after the request.- Before sending,
OrderCalcMargin()gives the margin a volume needs, to compare withAccountInfoDouble(ACCOUNT_MARGIN_FREE). OrderCheck()runs the same checks as the server without sending; itsMqlTradeCheckResultholds the retcode, the margin required and the free margin that would remain.
Broken code
This EA compiles. On an account whose free margin can't hold 5 lots of the symbol, every attempt fails with 10019, on every tick.
#include <Trade/Trade.mqh>
input double InpLots = 5.0; // Volume
CTrade trade;
void OnTick()
{
if(PositionSelect(_Symbol))
return;
// No margin check: the account decides, with 10019
trade.Buy(InpLots);
}Fixed code
The same program with the check that prevents the error. It compiles in MetaEditor with 0 errors and 0 warnings.
#include <Trade/Trade.mqh>
input double InpLots = 5.0; // Volume
CTrade trade;
// True if free margin covers a market order of this volume
bool MarginAllows(const ENUM_ORDER_TYPE type, const double volume)
{
double price = (type == ORDER_TYPE_BUY) ? SymbolInfoDouble(_Symbol, SYMBOL_ASK) : SymbolInfoDouble(_Symbol, SYMBOL_BID);
double margin = 0.0;
if(!OrderCalcMargin(type, _Symbol, volume, price, margin))
{
PrintFormat("OrderCalcMargin failed: error %d", GetLastError());
return false;
}
double freeMargin = AccountInfoDouble(ACCOUNT_MARGIN_FREE);
if(margin > freeMargin)
{
PrintFormat("Skipped: %.2f lots need %.2f margin, free margin is %.2f", volume, margin, freeMargin);
return false;
}
return true;
}
void OnTick()
{
// Once per new bar, so a refused trade isn't retried on every tick
static datetime lastBar = 0;
datetime bar = iTime(_Symbol, PERIOD_CURRENT, 0);
if(bar == lastBar)
return;
lastBar = bar;
if(PositionSelect(_Symbol))
return;
if(!MarginAllows(ORDER_TYPE_BUY, InpLots))
return;
if(!trade.Buy(InpLots))
PrintFormat("Buy failed: retcode %u (%s)", trade.ResultRetcode(), trade.ResultRetcodeDescription());
}Why the fix works
OrderCalcMargin() asks the terminal how much margin this volume of this symbol needs at the current price, using the account's own leverage and the symbol's settings. The EA compares it with free margin and skips the trade with a clear message instead of sending a request the server will refuse. Checking once per bar also stops the EA from hammering the server with the same refused order on every tick.
Margin isn't risk. A trade can pass this check and still risk far more than you meant to. Size the position from the stop distance first, as in MQL5 lot size from risk percent, then check the margin.
Questions
How do I check margin before opening a trade in MQL5?
Call OrderCalcMargin() with the order type, symbol, volume and price, and compare the result with AccountInfoDouble(ACCOUNT_MARGIN_FREE). OrderCheck() goes further: it runs the server's checks on a full request without sending it.
Why do I get not enough money when my balance looks large?
The check uses free margin, not balance: equity minus the margin already used by open positions. And the margin per lot depends on the symbol and the leverage the broker applies to it, which can be much higher for metals, indices or crypto than for forex pairs.
Is MT5 error 10019 the same as MT4 error 134?
Yes. MQL4's error 134 (ERR_NOT_ENOUGH_MONEY) is trade server return code 10019 in MQL5.
The programs on this page are minimal examples written to show the error and its fix, not trading systems. Some of them send orders when they run: try them on a demo account. Trading involves substantial risk of loss and is not suitable for every investor. Edgoro is a software tool, not a broker or financial adviser: nothing it produces is investment advice, and past or backtested performance does not guarantee future results.