Order lifecycle

Types, time-in-force, self-trade prevention, and the status machine — every value generated from the order model so the lists cannot rot.

An order is a BUY or SELL of shares in a specific market outcome. Every table on this page is generated directly from the order model (app/models/order.py) and drift-gated in CI, so it always matches the enums the engine enforces.

Order types

Order typeMeaning
LIMITLimit order with specific price
MARKETMarket order at best available price

Those are the only two order types. Drazill does not support stop, stop-limit, or trailing orders, and scalar (numeric-range) markets are defined but not yet live. If you need conditional exits, implement them in your own client against the price feed.

A MARKET order may carry an optional max_slippage_bps cap — the matcher will not fill any share worse than reference × (1 ± bps/10000). Left null, a market order is unbounded (today’s default).

Time-in-force

GTC is the default. IOC and FOK are taker controls; DAY expires at end of day.

Time-in-forceMeaning
GTCGood till cancelled (default)
DAYCancel at end of day
IOCImmediate or cancel (fill what you can, cancel rest)
FOKFill or kill (fill completely or cancel)

Post-only is a separate maker-only flag (LIMIT orders only): a post-only order that would immediately cross — taking liquidity from the book or the AMM — is rejected at placement rather than executing as a taker.

Self-trade prevention (STP)

When your own resting order would match your own incoming order, the STP mode decides what happens. The default is CANCEL_NEWEST.

STP modeMeaning
CANCEL_NEWESTCancel the incoming (taker) order
CANCEL_OLDESTCancel the resting (maker) order
CANCEL_BOTHCancel both orders
NONEAllow self-trades

NONE (allow self-trades) is locked down for retail and near market close — a manipulation surface. With the retail lockdown enabled, a retail NONE request is coerced to CANCEL_NEWEST, and NONE is blocked within a configured window before close. Source: docs/decisions/0001-unified-price-state.md (STP_NONE_RETAIL_LOCKDOWN_ENABLED).

Status machine

An order moves through these statuses:

StatusMeaning
PENDINGOrder created, awaiting processing
OPENOrder in order book
PARTIALLY_FILLEDSome shares matched
FILLEDFully matched
CANCELLEDCancelled by user
EXPIREDOrder expired
REJECTEDOrder rejected by system

The typical path is PENDING → OPEN → PARTIALLY_FILLED → FILLED. An order can instead end at CANCELLED, EXPIRED, or REJECTED. There is no HALTED order status — trading halts are a market-level state, covered in Markets & settlement.

Bounds

BoundRangeWhat it is
Limit price0.010.99Price per share, in CAD (= implied probability)
Order notional1.0010,000.00Total order value, in CAD

A limit price is bounded to 0.010.99 (an outcome never trades at exactly 0 or 1), and order notional is bounded in CAD. All money fields are decimal strings ("12.50"), never floats.

Idempotent placement

Two independent mechanisms prevent duplicate orders:

  • client_order_id — an application-owned id you attach to an order; a repeat with the same id for your account is de-duplicated.
  • Idempotency-Key header — the platform-wide idempotency guard for retryable mutations. Re-issuing a timed-out order-placement request with the same key hits the server’s replay guarantee instead of placing a second order (Idempotency-Replayed marks a replay).

The SDK quickstarts show the Idempotency-Key pattern end to end — see Quickstart step 4.