MT5 error 10016: Invalid stops (TRADE_RETCODE_INVALID_STOPS)

The stop loss or take profit is on the wrong side or too close to the price. Nothing was executed; move the stops and resend.

10016TRADE_RETCODE_INVALID_STOPS
After a fixSafe to retry?
NoCould it have executed?

What it means

You see this code in the retcode of a trade result, from OrderSend() in MQL5 or order_send() in Python.

10016 is about sl and tp. Each must sit on the correct side of the price the position would close at, and at least the symbol's stops level away from it.

For a buy, the check uses the Bid: the stop loss must be below it and the take profit above it. For a sell, it uses the Ask: the stop loss above, the take profit below.

Common causes

  • A stop loss closer to the market than trade_stops_level points.
  • Stops computed from the Ask for a buy, when the check uses the Bid. The spread is enough to break it.
  • Stops swapped between buy and sell logic.
  • Prices not rounded to the symbol's digits.
  • A spread that widened, which moves the Bid or Ask closer to your stop.

How to fix it

  • Read trade_stops_level and point from symbol_info(). A stops level of 0 can still mean a floating minimum, so leave a small margin.
  • Measure buy stops from the Bid and sell stops from the Ask.
  • Round with round(price, digits) before sending.
  • If the market is too close to your stop right now, send the order without stops and add them with TRADE_ACTION_SLTP once there is room.

Example in Python:

import MetaTrader5 as mt5

s = mt5.symbol_info("EURUSD")
tick = mt5.symbol_info_tick("EURUSD")
min_gap = (s.trade_stops_level + 5) * s.point     # a little extra room

# A buy closes at the Bid, so stops are measured from the Bid.
sl = round(min(tick.bid - min_gap, tick.bid - 0.0020), s.digits)
tp = round(max(tick.bid + min_gap, tick.bid + 0.0040), s.digits)

r = mt5.order_send({
    "action": mt5.TRADE_ACTION_DEAL, "symbol": "EURUSD", "volume": 0.1,
    "type": mt5.ORDER_TYPE_BUY, "price": tick.ask, "sl": sl, "tp": tp,
    "deviation": 20,
})

Is it safe to retry?

After you move the stops. With the same values it fails again.

Could the order have executed?

No. When the stops are refused, the whole order is refused. No position was opened without them.

How Tickwire handles it

Tickwire checks the side of each stop and the symbol's stops level before sending. A bad stop is refused with 10016 and nothing is sent.

MT4 error 130 comes back as 10016, with the MT4 code in the message.

Related MT5 Python functions

All MetaTrader error codes

One API for MT4 and MT5

Clear trade outcomes, idempotent orders and an audit log. Read the error reference or the quickstart.