Look at Open Orders. If the take-profit side of your OCO shows a partial fill and the stop side has dropped off the list, the page has not failed to refresh. The stop order has been ended by the system, and whatever is still unsold now rests only at the take-profit price. If the market turns down, nothing is waiting to sell it.
The rule comes from the Binance Spot API documentation. The changelog entry that introduced OCO sets out the execution order: if the limit leg (LIMIT_MAKER) is touched, it is executed first, before the stop-loss leg is canceled. Touched does not mean fully filled; one counterparty taking part of it is enough. The spot glossary puts it this way: if one of the orders executes, the other is automatically expired.
Two orders, one quantity, one survivor
An OCO is a pair. One leg is a limit order of type LIMIT_MAKER, so it can only rest on the book as a maker. The other is a stop order, STOP_LOSS or STOP_LOSS_LIMIT. Both legs must have the same quantity.
The prices have to straddle the last traded price. For a sell OCO: limit price > last price > stop price. For a buy OCO it flips: limit price < last price < stop price. Break the order and the OCO is rejected at placement.
The design assumes one of two endings, all out at the target or all out at the stop. But the limit leg queues on the book, and the buyer who reaches it may want only part of your size. The rule still counts that as the limit leg executing. For what a partial fill means on its own, see Only part filled. Where did the rest go?
A 0.5 ETH sell OCO after 0.2 fills
You hold 0.5 ETH and the last price is 2,450 USDT. You place a sell OCO: take-profit limit 2,600, stop trigger 2,300, stop limit 2,290, both legs 0.5 ETH. Since 2,600 > 2,450 > 2,300, it is accepted.
The price climbs to 2,600. Your sell sits behind orders already resting at that price, and by the time the queue reaches you, the buying on the other side covers only 0.2 ETH. Following the documented order, three things happen:
- the limit leg fills 0.2 ETH, becomes partially filled, and 0.3 ETH keeps resting at 2,600;
- the stop leg is ended, with the status EXPIRED on the API side;
- all that is left of the OCO is that one partially filled limit sell.
Later the price slides to 2,250. The 0.3 ETH is not sold at 2,300, because the order that would have fired there no longer exists. It is still offered at 2,600. At 2,450 that 0.3 ETH is worth about 735 USDT; at 2,250, about 675 USDT. That 60 USDT drop falls entirely on the 0.3 ETH that has no stop.
What open orders, order history and trade history should show
Open Orders should hold a single limit sell. Check its filled and remaining amounts: 0.2 and 0.3 in the example. If a stop order is still listed, the limit leg has not filled yet and the situation above does not apply.
Order History is where the stop order ends up, and its outcome is not a fill. The API records it as EXPIRED, which is kept separate from an order you canceled yourself; EXPIRED: did nothing trade, or did the order end? explains how to tell the two apart.
Trade History contains fills from the limit leg only. There may be one or several, and together they should add up to 0.2 ETH. If they don't, match them one by one as in Order history vs trade history: match one order.
Putting a stop back on the remaining 0.3 ETH
To get the remainder back to a target above and a stop below, cancel the leftover limit sell, wait for the 0.3 ETH to return to your available balance, then place a new 0.3 ETH OCO at current prices. Doing it the other way round fails: the resting order still holds that 0.3 ETH, so a new OCO would run into insufficient balance (see Open orders: why your available balance is lower).
There is a gap between the cancel and the new order. After sending the cancel, confirm in Order History that the old order has ended and its filled amount stayed at 0.2, then size the new OCO from what is truly left. Fills that land while a cancel is in flight are covered in I pressed cancel. Can I place the whole order again?
The new OCO is checked against the last price at the moment you place it. Suppose the price is now 2,590: a 2,600 target is still above it and a 2,300 stop is still below, so the old prices work. Suppose instead it has run to 2,620: a 2,600 target is now below the last price and the order is rejected. The API error list gives the wording as “A limit order in a sell OCO must be above.” (code -1166).
A very small remainder is a different case. Say only 0.001 ETH is left; at 2,300 that is about 2.3 USDT, under the pair's minimum order value (5 USDT is used here for ETH/USDT as an example; the pair's trading rules decide). A new OCO will not go through, and once you cancel, the coin becomes dust you cannot sell on its own, see Binance won't let you sell your whole balance. In that situation, leaving the original limit sell in place saves you a problem.
The other way round: the stop triggers first
If the price falls to the stop trigger first, the sequence reverses. The changelog says the limit maker leg is canceled before the stop-loss leg executes. In the example, a stop-limit sell at 2,290 goes onto the book; if the price drops straight through and nobody buys at 2,290, you are left with an unfilled stop-limit sell and no take-profit. That is the same gap a standalone stop-limit order has, covered in The stop triggered. Why do I still hold the asset?
If what you need is an exit that goes through once triggered, the stop leg can be a plain stop without a limit (STOP_LOSS in the API, which executes at market). The trade-off is that you no longer control the price, and on thin books it can land well below the trigger; see Is the visible depth enough for this market order?
Cancel one leg and the whole OCO goes
The same changelog states that canceling either leg cancels the entire OCO. Keeping the stop while dropping the target is therefore not possible: both legs disappear and the full 0.5 ETH returns to your available balance. If a stop is all you want, cancel the OCO and place a separate stop-limit order.
The execution order and price rules above come from the Binance Spot API documentation published on GitHub (the changelog, the OCO section of the REST API reference, and the error codes). Button and status names on the website and in the app are whatever your screen shows.