Skip to content

PendingOrderManager

Handles pending order lifecycle for market and close orders when price data is not immediately available.

High-Level Design

The Problem

Orders use deterministic pricing: every order targets a specific Unix timestamp (Math.floor(Date.now() / 1000)). When the user submits a market or close order, the price for that exact second may not yet exist in PriceCollector. The order cannot execute without it.

The Solution: Reserve-Then-Execute

PendingOrderManager implements a reserve-then-execute pattern that decouples order submission from order execution:

User submits order


Price available? ──yes──▶ Execute immediately 
  │                       (handled by OrderExecutionManager)
  no


Create PENDING order ──▶ Reserve margin upfront ──▶ Register price arrival alert
                          (MARKET only)              (with PriceAlert DO)


... time passes (typically < 2 seconds) ...


PriceAlert calls onPriceArrival()


Execute order with exact timestamp's price


EXECUTED or FAILED

Key Concepts

"Eventually Correct" Margin Reservation — Margin is locked at creation time, not execution time. This guarantees the order can execute when the price arrives without re-checking balance. MARKET orders reserve sizeUsd / leverage; CLOSE orders reserve nothing (they release margin).

Implicit Margin ReleasegetTotalReservedMargin() only sums PENDING orders. When an order transitions to EXECUTED or FAILED, its reserved margin is automatically excluded from the total — no explicit release step needed.

Stale Alert Guard — Each pending order is scoped to an accountId. When the user resets their account, the accountId increments. Callbacks arriving for old accounts are rejected (STALE_ALERT), preventing ghost orders from executing against a fresh account.

No Separate CANCELLED Status — Cancellation marks orders as FAILED with error message "Cancelled by user". This keeps the state machine simple: PENDING → EXECUTED | FAILED.

Edge Cases

  • No margin re-check at execution — margin was reserved at creation. Execution failures come from trading logic (e.g., position validation, liquidation check), not insufficient margin.
  • Price missing for symbol — if the arrived PriceData doesn't contain the order's symbol, the order is marked FAILED immediately.
  • Multiple orders same timestampexecutePendingOrdersForTimestamp loops through all matching orders sequentially. Each executes independently.
  • CLOSE order type — uses opposite direction of the existing position. Reserves no margin.

See Also