Edgoro
Trade server return code 10015 · MQL5

MT5 error 10015 Invalid price: causes and fix

Why MetaTrader 5 returns 10015 (invalid price), most often a pending order on the wrong side of the market, and how to place limit and stop orders in MQL5.

Trade server return code · MqlTradeResult.retcode
10015 TRADE_RETCODE_INVALID_PRICE
“Invalid price in the request”
Experts tab · line printed by CTrade (example values)
CTrade::OrderSend: buy limit 0.10 EURUSD at 1.08520 [invalid price]

What it means

The price in the request isn't one the server accepts for that order. With pending orders it almost always means the order is on the wrong side of the market, or too close to it.

Usual causes

  • A pending order on the wrong side. A buy limit must be below the Ask and a buy stop above it; a sell limit must be above the Bid and a sell stop below it. A buy limit placed at or above the Ask is refused.
  • Too close to the market. A pending order closer to the current price than the broker allows. Keep it beyond the symbol's SYMBOL_TRADE_STOPS_LEVEL.
  • An unrounded price. A price with more decimals than the symbol's digits, or off the tick size. Round it before sending.
  • The market moved past it. The price was valid when computed, but the market crossed it before the request arrived.

How to detect it

  • result.retcode (or trade.ResultRetcode()) is 10015; the Experts tab shows the order, its price and [invalid price].
  • Log the Bid, the Ask and the order price together: the wrong side is visible at a glance.

Broken code

This script compiles. The buy limit is above the market, where only a buy stop can go, so the server returns 10015.

MQL5
#include <Trade/Trade.mqh>

input int InpOffsetPoints = 50; // Distance of the limit order, points

CTrade trade;

void OnStart()
  {
   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   // Sign error: a buy limit ABOVE the Ask
   double price = ask + InpOffsetPoints * _Point;
   trade.BuyLimit(0.10, price);
  }

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 int InpOffsetPoints = 50; // Distance of the limit order, points

CTrade trade;

// Rounds a price to the symbol's tick size
double RoundToTick(const double price)
  {
   double tick = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
   if(tick <= 0.0)
      return NormalizeDouble(price, _Digits);
   return NormalizeDouble(MathRound(price / tick) * tick, _Digits);
  }

void OnStart()
  {
   MqlTick tick;
   if(!SymbolInfoTick(_Symbol, tick))
      return;
   // A buy limit waits BELOW the Ask, at least the stops level away
   double minDist = (double)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * _Point;
   double price   = RoundToTick(tick.ask - InpOffsetPoints * _Point);
   if(tick.ask - price < minDist)
     {
      PrintFormat("Skipped: a buy limit must be at least %d points below the Ask", (int)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL));
      return;
     }
   if(!trade.BuyLimit(0.10, price))
      PrintFormat("BuyLimit failed: retcode %u (%s)", trade.ResultRetcode(), trade.ResultRetcodeDescription());
  }

Why the fix works

The buy limit now sits below the Ask, rounded to the tick size, and the script checks the broker's minimum distance before sending. To buy above the current price, the order type to use is a buy stop, not a buy limit.

Where each pending order goes

OrderPlacedMeasured from
Buy limitBelow the marketAsk
Buy stopAbove the marketAsk
Sell limitAbove the marketBid
Sell stopBelow the marketBid

Stop-loss and take-profit levels of a pending order are measured from the order's own price; when they're too close, the code is 10016, invalid stops.

Questions

Why is my buy limit rejected with invalid price?

Most often because it's at or above the Ask: a buy limit must wait below the current price. If it's below but very close, it can still be refused; keep it beyond SYMBOL_TRADE_STOPS_LEVEL and round it to the tick size.

What's the difference between 10015 and 10016?

10015 is about the order's price itself. 10016 is about its stop-loss or take-profit levels.

Is MT5 error 10015 the same as MT4 error 129?

Yes. MQL4's error 129 (ERR_INVALID_PRICE) is trade server return code 10015 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.