Automatically cancel take profit and stop loss orders when closing position

With the UI, if I click on the “Market” button to close the position at market price, the position close but the TP/SL orders still open in the “Open Orders” tab.
The same thing happen if I close the position with a market order through the API.

Usually, with a position opened manually with a TP/SL set, when the position is closed the TP/SL orders are canceled automatically.

  • API doesn’t support TP/SL unless following this logic (How to implement OTOCO(TP/SL) orders using API) using websocket.
  • When price hits stop price of one of TP/SL orders, one order is canceled and another is set to update the open position (can be for closing it). This is an orders affecting the position and not position affecting orders flow, so it’s normal that when you create a 3rd (market) order, it closes the position but doesn’t affect the TP/SL orders.

@aisling Everything is working fine. I’m able to place TP/SL with the API. The orders are executed if they have to. But like I said there is a bug that does’t cancel the remaining order (TP or SL) even if the position is closed. Placing TP/SL using the UI it will works. Placing TP/SL using the API works too but doesn’t cancel remaining order. This is a bug for me.

2 Likes

I’m not fully understanding your answer aisling, but I’m facing similar issues as Elon_cryptoman.

When I place a TP/SL (‘closePosition’ set to true) through the API using the same parameters as the website, nothing can tell them apart visually nor from the information we can retrieve through the API. Yet, when either the TP or the SL is hit, the other one remains active even though there aren’t any position left open. However, if the TP/SL is placed through the GUI, then when either the TP or the SL is hit, the other one is automatically cancelled.

2 Likes

With the API, when you place a TP and a SL order, they’re seen as two individual orders, so once an order is executed, another one won’t be automatically canceled as it happens through the UI. Hence, using the websocket to know when one of the orders is filled for you to manually cancel the remaining open one.

1 Like

Alright then the question is how can you place a TP/SL order combined as one like in the UI? Since all it does is send a post request as well with the same components.

Also even if you place the TP and SL separately using the UI, it still cancels the remaining one. But it got placed using two separate requests and thus two orders…

So I really don’t get the logic you’re mentioning.

1 Like

There’s some implementations in the UI that’s not supported in the public trading API yet, this is one of the cases, for now, if you want to resemble similar behaviour, the only option is the previously shared: How to implement OTOCO(TP/SL) orders using API

Alright, it makes more sense now, even though I’m not sure why it’s required to make a public API version that differs from the production one. Could you please provide us with further information such as if we can expect this feature to be added to the public API? If yes when and if not, is it allowed to plug onto the same API as the GUI?

From what I tested recently, it seems like if we use GTE_GTC as “time in force” and “closePosition” is set to true, then when either the SL or the TP is triggered, the other one is automatically removed like expected.

1 Like

hello, how did you implement it? i keep getting this error. “AttributeError: type object ‘TimeInForce’ has no attribute ‘GTE_GTC’”

Just checked what @ren0d1 wrote and it works perfect. Thanks for sharing that.

2 Likes

hello, how were you able to implement it successfully? i keep getting this error. “AttributeError: type object ‘TimeInForce’ has no attribute ‘GTE_GTC’”

@kasahh I do not know which language you are using to interact with the API, so all I can offer you are the GET parameters I used for my request in the Coin-M futures.

symbol: *ANY*
side : BUY/SELL
type: STOP_MARKET/TAKE_PROFIT_MARKET
stopPrice: *YOUR CHOICE*
closePosition: true
timeInForce: GTE_GTC
timestamp: *CURRENT TIMESTAMP*
positionSide: LONG/SHORT

hi, thanks for the response. i am using python. i tried your parameters but it still doesn’t work. i use the binance futures python library i got from here https://github.com/Binance-docs/Binance_Futures_python could it be that the library doesn’t support GTE_GTC? Also what library do you use?

Yes it can be that the library doesn’t support it since your error message doesn’t remind me of any standard message returned by the API itself. Also, GTE_GTC isn’t listed on the official API docs, I only happened to find it through my own research and tests. Thus, I would assume that “official” libraries don’t include it either. Especially given that even moderators here didn’t seem to be aware of this option.

My advice would be for you to try by sending your own request directly with something like the requests library in Python or something like curl/postman depending on what you’re most confortable with.

N.B.: I haven’t used any of the premade library so far and I don’t use python so I can’t affirm it though.

FYI: I use C# and I created my own system because the one I could find wasn’t matching my expectations (and also I only found out half-way through tbh ahah).

1 Like

It general Time in Force strings should be mapped to Enums (as per Binance documentation) and in my library GTE_GTC string is being mapped to 4 so you can try to post just pure 4 number.

what library do you use? can you help with a link to it? i cant find any library that supports GTE_GTC

I can’t help you with a link. I just did some researches across different sites and implemented what I needed on my own.

By default Binance doesn’t close the TAKE_PROFIT_MARKET or STOP_MARKET after position is closed… you need to manually close those orders, you can pull the current opened orders and filter them based on the positionSide (SELL / LONG / BOTH) and origType (TAKE_PROFIT_MARKET / STOP_MARKET) and you can get the orderId for those orders and batch cancel them or cancel them one by one

you check my original answer here.

const position = 'LONG' // LONG, SHORT, BOTH

axios
.get('https://fapi.binance.com/fapi/v1/openOrders', {
  params: {
    symbol: 'BTCUSDT'
  }
})
.then(({ data }) => {
  const orderIds = data
    .filter(
      ({ positionSide, origType }) =>
        positionSide === position &&
        ['TAKE_PROFIT_MARKET', 'STOP_MARKET'].includes(origType)
    )
    .map(({ orderId }) => orderId)

  // Use batch cancel or cancel order one by one
  console.log('orderIds', orderIds)
})

ordemSaidaCompraGain = client.futures_create_order(
symbol = symbol,
side = ‘SELL’,
positionSide=‘LONG’,
type=‘TAKE_PROFIT_MARKET’,
closePosition=True,
stopPrice = round(entradaComprado+pips, 3),
timeInForce=‘GTE_GTC’
)

    ordemSaidaCompraLoss = client.futures_create_order(
        symbol = symbol,
        side = 'SELL',
        positionSide='LONG',
        type='STOP_MARKET',
        closePosition=True,
        stopPrice = round(entradaComprado-2*pips, 3),
        timeInForce='GTE_GTC'
    )