new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Quant · Exchange APIs · all subjects

Orders and fills

9 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Market vs limit vs post-only — which order type should my bot use?

Market guarantees a fill, not a price: on thin books you pay slippage, and on futures market orders still have a price-protection band that can leave you partially filled. Limit guarantees a price, not a fill. Post-only (Binance spot `LIMIT_MAKER`, Binance futures timeInForce `GTX`, Bybit v5 `PostOnly`) guarantees you are the maker: the exchange REJECTS the order instead of crossing the spread. Maker orders pay lower (or negative) fees, which is often the whole edge — but your bot must handle post-only rejections by requoting, or it silently stops trading. Taker exits for stop-loss logic are usually still worth the fee: a guaranteed exit beats a maker order that never fills while the market runs away.

What do GTC, IOC, FOK and GTX time-in-force values mean?

GTC rests on the book until filled or canceled. IOC fills what it can immediately and cancels the remainder — partial fills are normal, so always read `executedQty` before assuming your exit happened. FOK is all-or-nothing: fill completely now or cancel entirely. GTX (Binance futures) is 'Good Till Crossing', i.e. post-only GTC; on Binance spot the equivalent is order type `LIMIT_MAKER` rather than a timeInForce. Bybit v5 uses `timeInForce: GTC/IOC/FOK/PostOnly`. OKX uses `ordType` variants (`post_only`, `ioc`, `fok`). Gotcha: default timeInForce differs between exchanges and even between order types on the same exchange — always set it explicitly, never rely on the default.

How do stop orders work and which trigger price should I use?

A stop-market order fires a market order at the trigger: guaranteed execution, no guaranteed price — in a cascade it can fill far through your stop. A stop-limit fires a limit order: in a gap it may never fill, leaving you naked. Trigger price source matters as much: exchanges can trigger off last trade, mark price, or index price. Binance futures uses `workingType: MARK_PRICE` or `CONTRACT_PRICE` (last); Bybit v5 uses `triggerBy: MarkPrice/LastPrice/IndexPrice`. Prefer mark-price triggers for protective stops so a single wick or liquidation print on one venue does not stop you out. On Binance spot, stop orders are `STOP_LOSS`/`STOP_LOSS_LIMIT`/`TAKE_PROFIT(_LIMIT)` types with `stopPrice`; there is no mark price on spot.

How do I place an OCO order on Binance spot?

OCO (one-cancels-the-other) on Binance spot is an order LIST: `POST /api/v3/orderList/oco` (the older `/api/v3/order/oco` endpoint is deprecated as of early 2026 — verify current docs). You pass `price` (limit-maker take-profit leg), `stopPrice` and `stopLimitPrice` (stop-limit leg) plus `stopLimitTimeInForce`. When one leg fills, the exchange cancels the other automatically. Track the list status, not just individual order ids — both legs appear as separate orders. OCO does not exist on Binance futures; emulate it with two reduceOnly conditional orders and cancel the sibling when one fills. Beware the race: if a fill event arrives during a reconnect gap, both legs can execute — reconcile position via REST before assuming the hedge worked.

How are partial fills and avgPrice reported?

A 200 response never means 'filled'. Read `status` (`NEW`, `PARTIALLY_FILLED`, `FILLED`) and `executedQty` every time. On Binance spot the response carries `cummulativeQuoteQty` — your volume-weighted average price is `cummulativeQuoteQty / executedQty`; with `newOrderRespType=FULL` you also get a `fills[]` array with per-fill price, qty, commission and `commissionAsset` (fees may be in BNB, so net received quantity is less than executed). Binance futures returns `avgPrice` directly. Bybit v5 reports `avgPrice`, `cumExecQty`, `cumExecFee` on the order. For PnL and position sizing always accumulate from fills/executed quantities, never from your requested quantity — this is the single most common accounting bug in retail bots.

How do I safely retry a timed-out order without double-filling?

Always attach a client order id: `newClientOrderId` (Binance), `orderLinkId` (Bybit v5), `clOrdId` (OKX). If a place-order request times out, the outcome is unknown — the exchange may have accepted it. Recovery pattern: query the order BY CLIENT ID (`GET /api/v3/order` with `origClientOrderId`, Bybit `/v5/order/realtime?orderLinkId=`, OKX `GET /api/v5/trade/order?clOrdId=`). If it exists, adopt its real status and stop retrying. If it does not exist, resubmit — on most exchanges a duplicate client id of a still-open order is rejected, which makes the retry idempotent; on resubmit after a confirmed miss you may reuse or rotate the id per exchange semantics. Generate ids deterministically (hash of strategy+signal) so crashes survive restarts.

What is reduceOnly and when must I set it?

`reduceOnly` is a futures-only flag guaranteeing the order can only shrink (or close) your position; the exchange rejects or adjusts it if it would open/increase one. Set it on every stop-loss and take-profit leg. Without it, the classic disaster is: TP fills, your cancel of the SL is lost in a reconnect, the SL later fires and OPENS an opposite position you never intended. On Binance futures set `reduceOnly=true` (or `closePosition=true` on stop-market/take-profit-market to close the whole position without a quantity — note `closePosition` cannot be combined with quantity). In hedge mode also pass the matching `positionSide`. Bybit v5: `reduceOnly: true`. OKX: `reduceOnly: true` on the order. There is no reduceOnly on spot — selling more than you hold is just rejected for insufficient balance.

How do stop orders work on Binance SPOT, and which trigger price applies?

Spot stop orders use dedicated order types: STOP_LOSS (triggers a MARKET sell when the last trade price falls to stopPrice), STOP_LOSS_LIMIT (triggers a LIMIT sell at your price), and TAKE_PROFIT / TAKE_PROFIT_LIMIT mirrored upward. Key facts that differ from futures: spot has NO mark price — the trigger is always the last traded price, there is no workingType parameter; STOP_LOSS (market) gives no guaranteed execution price — in a fast dump the fill can be far below stopPrice, while the _LIMIT variant can fail to fill at all and leave you holding through the drop. For combined take-profit + stop-loss on one position use an OCO order (orderList/oco): a limit-maker leg plus a stop-limit leg, where filling one cancels the other. Place stops via the same order endpoints with stopPrice in the request; verify the order is resting as a working conditional order, not executed immediately (stopPrice on the wrong side of the market triggers instantly).

My market order didn't fill immediately — is that normal?

Usually yes, and the causes are diagnosable. Partial fill: book depth at the top levels is smaller than your size — the remainder of a spot MARKET order either fills walking the book or expires (Binance spot market orders fill what liquidity allows; check executedQty vs origQty, and the fills array for per-trade prices). Rejected outright: notional below the pair's minNotional/MIN_NOTIONAL filter — a $3 order on a $5-minimum pair never reaches the book, and this is the most common 'nothing happened' cause; also price/quantity precision filters. Delayed: during volatility spikes the matching engine and API gateway queue — REST ack can lag seconds while the order is actually live, which is why you must never blind-retry: query the order by clientOrderId first. Slippage: a large market order walks multiple levels — read avgPrice from fills, not the ticker price you saw when sending.

Give your agent this brain