How to implement OTOCO(TP/SL) orders using API

Q: In Futures web page/App, you can check “TP/SL” box to place a limit/market order followed by a TP order and/or an SL order. Is there an API interface to do that?

A:
There’s no direct way to do it but you can leverage on WSS and code logic to get similar effect. Below is the procedure:

  1. Listen to your futures user data stream - https://binance-docs.github.io/apidocs/futures/en/#user-data-streams
  2. Place the limit/market order as you planned and specify a unique client order id to identify it later
  3. If you receive an event from your user data stream indicating that particular order has been filled, place the TP/SL order(s) with unique client order ID. The orders both should be reduce-only and same quantity as your order placed in #2
  4. Keep tracking your TP/SL orders(s) until either one of your TP/SL orders gets filled (it would go through triggering stage and then get filled)
  5. Cancel the other order (might have been triggered and turned to a limit order)

Hey, I am unable to set up a scenario like you described, for my take profit/stoploss orders I keep receiving “-1106: Parameter ‘reduceOnly’ sent when not required.”

Settings I used for testing:
symbol = btcusdt
signal = Signal.BUY; (Buy market order with sell for stoploss/take profit)
quantity = 0.01
takeprofit = 59000
stoploss = 58000

I fetch their unique client order IDs from the result, instead of generating my own as it seemed easier.

I first create a market order, which works fine (the order appears on the testnet platform)
And then create the 2 stoploss/take profit orders (but both of them respond with the same error)
like this:

 Order marketOrder = syncRequestClient.postOrder(
     symbol,
     side == Signal.SELL ? OrderSide.SELL : OrderSide.BUY,
     side == Signal.SELL ? PositionSide.SHORT : PositionSide.LONG,
     OrderType.MARKET,
     null, //TimeInForce
     quantity.toString(), //Quantity
     null, //Price
     null, //Reduce only
     null, //NewClientOrderId
     null, //Stop price
     null, //workingType
     NewOrderRespType.RESULT //NewOrderRespType
 );

 Order stopOrder = syncRequestClient.postOrder(
      symbol,
      side == Signal.SELL ? OrderSide.BUY : OrderSide.SELL,
      side == Signal.SELL ? PositionSide.SHORT : PositionSide.LONG, 
      OrderType.LIMIT,
      TimeInForce.GTC,
      quantity.toString(),
      stoploss.toString(),
      "true", //Reduce only
      null, //NewClientOrderId
      null, //Stop price
      null, //workingType
      NewOrderRespType.RESULT //NewOrderRespType
  );

 Order profitOrder = syncRequestClient.postOrder(
      symbol,
      side == Signal.SELL ? OrderSide.BUY : OrderSide.SELL,
      side == Signal.SELL ? PositionSide.SHORT : PositionSide.LONG, 
      OrderType.LIMIT,
      TimeInForce.GTC,
      quantity.toString(),
      null, //takeprofit.toString(), //Price
      "true", //Reduce only
      null, //NewClientOrderId
      takeprofit.toString(), //Stop price
      null, //workingType
      NewOrderRespType.RESULT //NewOrderRespType
  );

I’ve tried using the stop price instead of price, and also in one-way mode but it I can not get it to work

This is a knowledge sharing topic. Please open your problem with a new one