ccxt: bybit stoploss handling inconsistent / broken

Operating System

No response

Programming Languages

python

CCXT Version

3.0.50

Description

Placing a bybit futures stoploss order is a bit of a challange at the moment.

Placing the order with stopPrice fails with wrong direction. Placing the order with stopLossPrice works - but the response doesn’t contain this field - making usage of this quite odd an non-unified.

As it’s important with bybit - my account is NOT unified - and the create-order requests therefore go through the v3 api.

Code

import ccxt
exchange = ccxt.bybit({'apiKey': '<yourApiKey>', 'secret': '<yoursecret>', 'options': {'defaultType': 'swap'}})
params = {
    'stopPrice': 1600,

}
o = exchange.create_order(pair, 'limit', 'sell', amount=0.01, price=1600, params=params)

Fails with

BadRequest: bybit {"retCode":10001,"retMsg":"expect Rising, but trigger_price[16010000] \u003c= current[17985500]??1","result":{},"retExtInfo":{},"time":1680544529422}

Now from past experience, i know that using stopLossPrice is an alternative if one doesn’t work.

import ccxt
exchange = ccxt.bybit({'apiKey': '<yourApiKey>', 'secret': '<yoursecret>', 'options': {'defaultType': 'swap'}})
params = {
    'stopLossPrice': 1600,

}
o = exchange.create_order(pair, 'limit', 'sell', amount=0.01, price=1600, params=params)
print(o)

print(exchange.fetch_order(o['id'], pair))

This works - and the response is Okish - However - i’d expect stopLossPrice in the response - but stopPrice is used (which is wrong).

{'info': {'orderId': '44a665de-1a3e-4573-8cf8-dc403725147f',
  'orderLinkId': ''},
 'id': '44a665de-1a3e-4573-8cf8-dc403725147f',
 'clientOrderId': None,
 'timestamp': None,
 'datetime': None,
 'lastTradeTimestamp': None,
 'symbol': None,
 'type': None,
 'timeInForce': None,
 'postOnly': None,
 'reduceOnly': None,
 'side': None,
 'price': None,
 'stopPrice': None,
 'triggerPrice': None,
 'amount': None,
 'cost': None,
 'average': None,
 'filled': None,
 'remaining': None,
 'status': None,
 'fee': None,
 'trades': [],
 'fees': []}

// Fetch_order reslt
{'info': {'orderId': '44a665de-1a3e-4573-8cf8-dc403725147f',
  'orderLinkId': '',
  'blockTradeId': '',
  'symbol': 'ETHUSDT',
  'price': '1601.00',
  'qty': '0.01',
  'side': 'Sell',
  'isLeverage': '',
  'positionIdx': '0',
  'orderStatus': 'Untriggered',
  'cancelType': 'UNKNOWN',
  'rejectReason': 'EC_NoError',
  'avgPrice': '0',
  'leavesQty': '0.01',
  'leavesValue': '16.01',
  'cumExecQty': '0.00',
  'cumExecValue': '0',
  'cumExecFee': '0',
  'timeInForce': 'GTC',
  'orderType': 'Limit',
  'stopOrderType': 'Stop',
  'orderIv': '',
  'triggerPrice': '1601.00',
  'takeProfit': '0.00',
  'stopLoss': '0.00',
  'tpTriggerBy': 'UNKNOWN',
  'slTriggerBy': 'UNKNOWN',
  'triggerDirection': '2',
  'triggerBy': 'LastPrice',
  'lastPriceOnCreated': '0.00',
  'reduceOnly': True,
  'closeOnTrigger': False,
  'createdTime': '1680544580692',
  'updatedTime': '1680544580692'},
 'id': '44a665de-1a3e-4573-8cf8-dc403725147f',
 'clientOrderId': None,
 'timestamp': 1680544580692,
 'datetime': '2023-04-03T17:56:20.692Z',
 'lastTradeTimestamp': 1680544580692,
 'symbol': 'ETH/USDT:USDT',
 'type': 'limit',
 'timeInForce': 'GTC',
 'postOnly': False,
 'reduceOnly': True,
 'side': 'sell',
 'price': 1601.0,
 'stopPrice': 1601.0,
 'triggerPrice': 1601.0,
 'amount': 0.01,
 'cost': 0.0,
 'average': None,
 'filled': 0.0,
 'remaining': 0.01,
 'status': 'open',
 'fee': {'cost': 0.0, 'currency': 'USDT'},
 'trades': [],
 'fees': [{'cost': 0.0, 'currency': 'USDT'}]}

edit seems to have been introduced in #17262 - which dropped the fallback to triggerPrice from the assignment of stopLossTriggerPrice.

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 16 (14 by maintainers)

Most upvoted comments

Hi @carlosmiei,

Stoploss orders do work again now 👍 Thanks a lot for your help!

@xmatthias I will try to take a look asap, just to recap, providing stopPrice using a non-unified account fails, right?

Hi @xmatthias

The stopLoss and takeProfit was exchange specific sl/tp value, and they are tied to some position. When createOrder with these value, exchange would check price value (that’s why you got BadRequest: bybit {“retCode”:10001,“retMsg”:“sl:16010000 set for Sell position should greater base_price:18577300??LastPrice”,“result”:{},“retExtInfo”:{},“time”:1680624978500}).

For the triggerDirection issue, when use the stopPrice with buy order, I think the expected behavior might be that create order when price fall to the triggerPrice (buy the dip). If you want to use different direction, you can set triggerPrice or set the stopLossPrice.

Let me know if you have any other issues.