Orders
TradingOrderDraft is a financial intent. TradingOrder is the broker-owned
record that later appears in controller state. Keep those contracts separate.
Order statuses
TradingOrderStatus describes records in controller state. It is a status
vocabulary, not an SDK-enforced transition graph. Arrows below show common
progressions; a backend may skip a box or publish a record directly in any
status it can report truthfully.
placing, modifying, and cancelling are optional transient statuses; the
controller does not synthesize them before it calls the adapter. inactive
represents a dormant broker order, such as a bracket child waiting for its
parent to fill, and is not terminal.
An accepted placeOrder result is only an acknowledgement. It does not add an
order record or move one to working; publish the broker-owned record through
an orders or state event. The controller applies the confirmed return from
modifyOrder through order-modified, and applies cancelled only after the
adapter's cancellation call resolves.
Draft and broker record
Reuse the exact symbol returned by market-data resolution.
import type {
SdkSymbolInfo,
TradingEvent,
TradingOrder,
TradingOrderDraft,
} from '@tradescript/pro/sdk';
declare const symbol: SdkSymbolInfo;
export const draft = {
accountId: 'acct-1',
symbol,
side: 'buy',
type: 'limit',
quantity: 300,
price: 184.98,
duration: { type: 'day' },
} satisfies TradingOrderDraft;
export const partialOrder: TradingOrder = {
...draft,
id: 'ord-9',
accountId: 'acct-1',
status: 'partially-filled',
filledQuantity: 200,
remainingQuantity: 100,
};
export const update = {
type: 'orders',
orders: [partialOrder],
} satisfies TradingEvent;
An accepted placeOrder result acknowledges the request. Publish the broker
record in an orders or state event before expecting a line or table row.
Transition contract
| Backend fact | Publish | Visible result |
|---|---|---|
| Working order accepted | Complete current orders list | Working row and chart line appear. |
| Partial fill | Updated order plus execution and position facts | Remaining quantity and exposure update. |
| Final fill | Terminal order, final execution, resulting position | Working line disappears. |
| Cancellation | Current orders update or order-cancelled | Working line disappears; a focused cancellation also upserts the cached order into history. |
| Expiry | Expired record with stable event identity | History shows the expiry. |
Use one full state event when a fill must update orders, executions, and
positions atomically. See State and events.
Mutations and support
previewOrdervalidates a draft without placement.placeOrderis required and returns acceptance or rejection.previewModifyOrderandmodifyOrderuseTradingOrderPatch.cancelOrder,cancelOrders, andcancelAllOrdersare optional.getOrdersHistoryloads broker-owned history.
Render an action only when trading.getOperationSupport() declares it.
cancelAllOrders is an atomic broker operation; the SDK never reconstructs it
as a client-side list-and-loop fallback.
Mutation completion
Controller-generated events complete local mutation handling. Broker streams remain authoritative for reconnects and replacement snapshots.
| Method | Completion behavior |
|---|---|
placeOrder | Returns acceptance or rejection. The controller emits order-accepted or order-rejected; acceptance does not add an order. Publish the broker record separately. |
modifyOrder | Returns the updated order. The controller applies it through order-modified. |
cancelOrder | Resolves after confirmation. The controller applies order-cancelled. |
cancelOrders | Uses the batch method when supplied, otherwise confirmed single cancels, then applies one order-cancelled event per id. |
cancelAllOrders | Returns the cancelled count. The controller immediately calls getState() and applies that snapshot. |
Your backend stream may independently report the same mutation. Reconcile it with stable ids and replacement snapshots; do not emit a duplicate focused event merely to mirror a method return.
Order-history windows
getOrdersHistory(request) passes the requested account, symbol, status, time,
limit, and cursor filters to the adapter. The returned array becomes the
controller's entire cached ordersHistory slice. A later call with another
scope replaces that slice; consumers do not receive independent caches.
The current result has no nextCursor. Treat each adapter response as one
complete documented history window. Use a backend-owned paginated Account
Manager table when the product needs independent or long-running pagination.
Identity and retries
Reuse one stable order id for every version, and make it globally unique within
the controller. Prefix a provider id with its account or venue when the native
id is only scoped there. previewOrder may return a confirmId, which the
caller can copy to the draft. When
placeOrder receives an operationId, the controller uses it as the outgoing
draft's confirmId and also passes it in the mutation options; it therefore
takes precedence over a preview confirmId. The current contract has no
separate adapter field that preserves both values. Supplying an operationId
also requires origin; both remain mutation metadata.
Give every mutation a backend idempotency or correlation key. A timeout or transport failure has an unknown outcome, not a rejected outcome. Reconcile by that key and the order stream before retrying, and reuse the same key rather than issuing a blind retry with a new identity. The SDK does not make ordinary retries exactly-once.
Verify the contract
- Rejection creates no working order.
- Acceptance alone creates no order row or line.
- A partial fill retains the same order id and correct remaining quantity.
- Cancelling a remainder preserves completed executions.
- Reconnect restores the same logical orders without duplicate ids.
Next steps
- Executions — publish the prints linked to filled quantity.
- Positions — publish resulting exposure without client-side netting.
- Order Ticket — submit the drafts described here.