Edgoro
Trade server return code 10019 · MQL5

MT5 error 10019 Not enough money: causes and fix

Why an MT5 Expert Advisor gets retcode 10019 (not enough money) and how to check margin with OrderCalcMargin() before sending. Broken and fixed MQL5 code.

Trade server return code · MqlTradeResult.retcode
10019 TRADE_RETCODE_NO_MONEY
“There is not enough money to complete the request”
Experts tab · line printed by CTrade (example values)
CTrade::OrderSend: market buy 2.00 XAUUSD [not enough money]

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 (or trade.ResultRetcode()) is 10019; the Experts tab shows [not enough money] after the request.
  • Before sending, OrderCalcMargin() gives the margin a volume needs, to compare with AccountInfoDouble(ACCOUNT_MARGIN_FREE).
  • OrderCheck() runs the same checks as the server without sending; its MqlTradeCheckResult holds 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.

MQL5
#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.

MQL5
#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.

Working code that avoids it

All MQL5 examples

Rather not write the error handling yourself?

Edgoro's MT5 EA generator writes complete MQL5 Expert Advisors from plain English and compiles each one in MetaEditor before you get it. A clean build proves the code compiles, not that a strategy works: test it on a demo account.