Implementing OCO Order Placement in a Mobile Exchange App
OCO (One-Cancels-the-Other) is a linked pair of limit and stop-limit orders: when one executes, the other is automatically cancelled. Classic use: bought BTC at 40,000, set Take Profit at 45,000 (limit) and Stop Loss at 38,000 (stop-limit). Whichever triggers first, the other disappears.
On Binance API, OCO is a separate endpoint: POST /api/v3/order/oco. It takes seven parameters at once, with its own error logic. The interface should help users fill all seven fields correctly.
OCO Parameters and Their Order
| Parameter | Description |
|---|---|
symbol |
Trading pair |
side |
BUY or SELL |
quantity |
Volume (same for both orders) |
price |
Limit price (Take Profit / Buy Limit) |
stopPrice |
Stop order activation price |
stopLimitPrice |
Limit execution price after activation |
stopLimitTimeInForce |
GTC / IOC / FOK for stop order |
quantity is shared by both orders. This must be clear in the UI: one quantity field, not two.
Price Logic Validation for SELL OCO
On sell: price > currentPrice > stopPrice > stopLimitPrice.
// Android — validating SELL OCO price logic
data class OcoValidationError(val field: String, val message: String)
fun validateOcoSell(
currentPrice: BigDecimal,
limitPrice: BigDecimal,
stopPrice: BigDecimal,
stopLimitPrice: BigDecimal
): List<OcoValidationError> {
val errors = mutableListOf<OcoValidationError>()
if (limitPrice <= currentPrice)
errors += OcoValidationError("price", "Take Profit must be above current price")
if (stopPrice >= currentPrice)
errors += OcoValidationError("stopPrice", "Stop price must be below current price")
if (stopLimitPrice >= stopPrice)
errors += OcoValidationError("stopLimitPrice", "Stop limit must be below activation price")
return errors
}
For BUY OCO, logic is mirrored: stopLimitPrice > stopPrice > currentPrice > price.
UI Concept: One Card — Two Levels
Display OCO as a single card with three price levels on a mini-scale:
▲ Take Profit: 45,000 USDT (limit order)
│
● Current Price: ~41,500 USDT
│
▼ Stop: 38,500 → Limit: 38,200 USDT (stop-limit)
Color: green for Take Profit, red for Stop Loss. This reduces cognitive load and order-filling errors.
Cancellation and Statuses
OCO on Binance has orderListId — group ID. When displaying in order history, group both orders under one orderListId. If one executes, the other is marked CANCELED with reason OTHER_SIDE_CANCELED.
WebSocket event: listOrderStatus with type OCO. On ALL_DONE transition — send notification showing which of the two orders triggered.
Timeline: 3–5 days for seven-parameter form, mini-scale price visualization, BUY/SELL logic validation, grouping in order history, push on execution.







