Order types
Tplus supports limit and market orders. Time-in-force for limit orders:
Rules:
- All orders expire 30 days after creation, regardless of time-in-force.
- Market orders never rest on the book. Quantity is specified either in base-asset units or in quote/USD terms. Base-sized market buys can carry an optional quote cap; quote-sized market sells can carry an optional base cap.
- Post-only orders are canceled immediately if they would cross the book and be immediately matched.
- Reduce-only orders are rejected if they would increase or flip the position. The OMS pre-checks IOC and market orders with a base quantity; clearing enforces the constraint on every order.
- Fill-or-kill checks that at least one completion dimension can be satisfied before matching or cancels. For capped market orders, either the target quantity/amount or the protective cap can be the completion dimension. The all-or-nothing guarantee holds through clearing (see finality rules).
- Self-trade prevention is an operator opt-in, in cancel-resting mode: when enabled on a market, an incoming order never matches your own resting orders (same signer and sub-account) — the resting order is canceled with reason
SelfTradePreventedand matching continues against other liquidity. A post-only order that crosses only your own resting orders cancels them and books; crossing anyone else’s liquidity still rejects it. Distinct sub-accounts count as distinct owners. On markets without it, your own orders can match — check your open orders before submitting a crossing order.
10,000 USD and matches at a 2,500 USD VWAP, so base_filled = 10,000 USD / 2,500 USD = 4 ETH. A base-sized market buy for 4 ETH with a 9,500 USD quote cap would stop at 3.8 ETH at the same VWAP.
Trigger orders
Conditional orders rest in a separate trigger book and move to the main book when a confirmed trade price crosses the trigger price.PriceAbove: releases when the price rises to the trigger (take-profit).PriceBelow: releases when the price falls to the trigger (stop-loss).
Closing a position
A margin position has two legs (see margin positions), so closing it takes two steps:- Flatten the asset exposure. Place an order on the opposite side - sell to close a long, buy to close a short - sized to the position. A market order flattens immediately; a limit or trigger order (stop-loss / take-profit) flattens at a price. There is no dedicated close order type and no auto-sizing: you submit the quantity. The reduce-only flag guarantees the order can only shrink the position - it is rejected if it would flip or increase exposure.
- Settle the residual quote. Flattening the asset to zero does not remove the position; it lingers as a flat position holding its realized PnL in the quote (USD) leg.
POST /account/transfer/close-positionfolds that quote into the sub-account’s spot balance and removes the position. It is rejected while the asset balance is non-zero, so flatten first. The freed spot balance can then be transferred or withdrawn. If the quote balance is negative the user must have sufficient USD in their account to offset the negative balance.
GET /positions/close-all/{user_id}/{sub_account} returns unsigned suggested close orders for open positions in that sub-account. It is a preview: sign each returned order, submit the signed orders with POST /orders/batch-create, then settle each position’s quote.
Order fields
Orders can carry additional co-signers, validated against the account’s multisig configuration.
Managing orders
- Replace updates price, quantity, or trigger on a resting limit order atomically. It requires a new signature and passes a fresh margin check. Fill state of a partially-filled order is preserved.
- Cancel over REST returns
ORDER_NOT_FOUNDif the OMS cannot find the target order for that user, asset, and order ID; REST does not hold absent orders for later arrival. The order-control channel forwards cancels directly to the orderbook, where a cancel that reaches the fast queue before its create can be held and used to reject the later create. - Batch create accepts up to 50 orders per request and returns per-order statuses.
- Cancel-all (all markets or one market, optional
max_tscutoff) and cancel-batch (by ID) return202on admission: dispatched, not done. Confirm via the orders WebSocket stream or a follow-up query. IDs not owned by the caller are silently excluded.
Advanced edge cases
Order states
A queried order reports one of these states:
A resting order’s reported filled quantity includes an optimistic component from pending fills that can roll back; the confirmed filled quantity counts only clearing-engine-finalized fills.
Validation
Checks run in this order:- OMS: rate limits (global and per token), signer identity, order ID rules, reduce-only pre-check.
- OMS: margin pre-flight - trading capacity including the order pressure of existing open orders, at both oracle and mark price, taking the worse. Failures return
InsufficientInventoryorInsufficientMargin. See Margin. - Clearing Engine: signature, overfill, order parameters, protocol caps, reduce-only, post-trade IM. Failures here arrive as rollbacks on the trade-event stream. Fills that reach clearing more than 5 minutes after matching are rolled back.
CounterpartyAtFault.
Auto-reduce
If price moves make an account’s trading capacity negative, the OMS reduces or cancels its open orders automatically, farthest-from-market first, with a per-sub-account cooldown. IOC/FOK and in-flight orders are never auto-reduced. Server-initiated reductions appear on the orders WebSocket stream. Market-maker accounts are exempt. For normal limit orders in the same market, farthest-from-market means the largest percentage distance from the current market reference:100 USD reference price, normal open buys at 80 USD and 95 USD are 20% and 5% away, so the 80 USD order is reduced first. Trigger orders are prioritized by their trigger-side semantics rather than this simplified normal-order example.
Reading orders and trades
REST reads are paginated (zero-basedpage plus limit): orders per user, per user and market, or by ID lookup, with an open_only filter; confirmed trade history per user. Reads span all of the caller’s sub-accounts. Pending and rolled-back fills are visible only on the WebSocket streams.