Inventory and risk
Every fill moves your inventory. Read it from the fill stream (futures) and your positions (options), and let it drive your next ladder.Skew quotes as inventory builds
Skew quotes as inventory builds
As you accumulate a long position, lower both sides of your ladder slightly so
you are more likely to sell and less likely to buy more (and vice versa when
short). This mean-reverts inventory toward flat without crossing the
spread.
Shrink size near limits
Shrink size near limits
Reduce quoted quantity — or widen — as your position approaches your
own risk limit, so you stop adding to a one-sided book.
Use reduceOnly for exits
Use reduceOnly for exits
Tag exit-only orders
reduceOnly so they can only shrink a position. On futures, POST {API_BASE}/fut/positions/close flattens a position fully or partially.Track your own margin headroom
Track your own margin headroom
OCX enforces portfolio margin server-side: every order passes a margin check before acceptance, and a rejected order returns
INSUFFICIENT_MARGIN — handle it, don’t retry blindly. Watch NLV and margin in GET {API_BASE}/portfolio/balances and de-risk proactively. Accounts whose requirement exceeds their NLV are reduced by the exchange, and accounts at the liquidation floor are liquidated — see Margin & liquidations.A margin rejection is a business answer, not a transport failure. Distinguish it from network and
5xx errors in your client — a margin reject is a signal to de-risk, not to reconnect.Kill switch
Pull all your orders the moment your bot can no longer be sure they reflect a live price — feed loss, an unhandled error, or shutdown. Futures and options orders are cancelled separately, so call both:1
Detect the trigger
Your reference feed goes stale, the fill stream stops heartbeating, a
place or replace call errors repeatedly, or you receive SIGTERM.
2
Cancel everything immediately
Fire both cancel-alls before doing anything else, so no stale order can be hit while you are blind.
3
Stand down until healthy
Do not re-quote until your feed is fresh and your streams are reconnected and
re-snapshotted.
Reconnect and heartbeat
SSE streams are long-lived. Build your client to survive drops without leaving orphaned orders.Snapshot then updates
Snapshot then updates
On connect you get a full snapshot; thereafter fold in
delta events (or, on the book and board streams, replace your copy with each full update).Detect gaps on the account stream
Detect gaps on the account stream
GET /fut/stream/user carries an eventSeq that increases by exactly one per event. If it jumps, close and reconnect — you will get a fresh snapshot to re-sync from. Other streams’ sequence numbers are not contiguous; rely on reconnect-on-drop there.Watch the heartbeat
Watch the heartbeat
Idle streams send comment heartbeats —
: heartbeat on the futures account stream (after 5s idle), :heartbeat on the futures book stream (after 15s idle), and :keepalive on the balances stream (every 15s). If expected heartbeats stop arriving, treat the connection as dead and reconnect.Reconnect with backoff
Reconnect with backoff
On any disconnect, reconnect with exponential backoff and jitter. Re-snapshot before trusting local state, and resume quoting only once state is consistent.
Idempotency and identifiers
clientOrderId
Attach a
clientOrderId to each order or quote level. A retried request with the same id and parameters returns the original result instead of placing a duplicate.quoteId
Tag each quoting cycle with a
quoteId to group a batch of quotes.Rate limits
The gateway allows 600 requests per minute per client on most endpoints and returnsx-ratelimit-* headers; futures market data and futures streams are not rate-limited at the gateway. The engines also limit order placement per account (RATE_LIMITED). Back off on 429 and on RATE_LIMITED rather than retrying tightly. See Errors & rate limits.
Session hygiene
One wallet per bot
One wallet per bot
Sign each bot in with its own wallet so its positions, margin, and kill switch are isolated from your other accounts.
Renew before expiry
Renew before expiry
Sessions last 7 days. Sign in again ahead of expiry, and handle
401 by re-authenticating, then re-snapshotting.Protect the token
Protect the token
The session token can trade the account. Keep it in a secret store, never in code or logs, and revoke it with
POST {API_BASE}/auth/logout if it leaks.A resilient maker loop
1
Start up
Sign in, load the market lists, contract terms, and fee schedules, connect the futures account stream, and re-snapshot state.
2
Each cycle
Compute fair value → (optionally) preview →
quotes/bulk per option market; amend or re-place post-only orders per futures market.3
On fill
Update inventory from the position delta (futures) or a positions read (options), then skew or shrink and re-quote.
4
On trouble
Stale feed, disconnect, repeated errors, or shutdown → both cancel-alls, back off, reconnect, re-snapshot, and only then resume.