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.
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_levelpoints. - 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_levelandpointfromsymbol_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_SLTPonce 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 codes
- MT5 error 10015: Invalid price (TRADE_RETCODE_INVALID_PRICE)
- MT5 error 10029: Order or position frozen (TRADE_RETCODE_FROZEN)
- MT4 error 130: Invalid stops (ERR_INVALID_STOPS)
- MT5 error 10025: No changes in request (TRADE_RETCODE_NO_CHANGES)
Related MT5 Python functions
One API for MT4 and MT5
Clear trade outcomes, idempotent orders and an audit log. Read the error reference or the quickstart.