Order Book

StockMarketABM.OrderBookMod combines price levels into a full limit order book with bid/ask maps, indexed order locations, and utilities for depth inspection and liquidity checks. The core structure, LimitOrderBook, contains:

  • bids / asks: SortedDict{Price,PriceLevel{LiveOrder}} collections from DataStructures.jl. Their ordering guarantees that first/last give the best prices without additional sorting.
  • loc: a Dict{OrderId,OrderLoc} mapping each resting order to its side and price so cancellation and consumption can jump directly to the correct level.
  • reg: a Dict{OrderId,OrderSpec} storing the full specification of resting orders (including the traded instrument) for logging, audit, and reconstruction.

The public API orchestrates the price levels as follows:

  1. add_order! creates a lightweight LiveOrder, inserts it into the corresponding PriceLevel, updates loc, and records the full OrderSpec. Market orders are rejected here because they bypass the book entirely.
  2. cancel_order! uses loc to find the relevant price level and delegates to cancel! in PriceLevelMod. Empty levels are pruned from the sorted map.
  3. best_bid, best_ask, and is_crossed read the extremal entries of the sorted dictionaries to surface top-of-book prices and detect crossed states.
  4. get_depth iterates levels in price order, aggregating level_qty until an optional top limit is reached. Bids are traversed in reverse so the output is naturally descending.
  5. available_qty scans the opposite side up to a price_limit, computing how much liquidity is executable for IOC/FOK orders. An optional stop_at keyword lets callers short-circuit once enough quantity is found.
  6. consume! removes quantity from the best opposing level, returning both the resting order (as a LiveOrder) and the original OrderSpec so the matching engine can record fills and residuals.

Together these operations provide the matching engine with O(1) access to the best prices and predictable iteration over depth, while deferring per-price mutations to the specialised PriceLevel queue. Complexity highlights:

  • add_order! / cancel_order!: amortised O(1) for updates, plus O(log N) when inserting or removing entries from the sorted price maps (N = number of price levels).
  • best_bid / best_ask / is_crossed: O(1) lookups of map extremal entries.
  • get_depth: O(min(top, L)) where L is the number of levels on the queried side; relies on level_qty being O(1).
  • available_qty: same O(min(levels, requested span)) behaviour, with stop_at allowing early exit once sufficient liquidity is accumulated.
  • consume!: O(1) to fetch the best level and adjust a single order, with an additional O(1) cleanup when a price level becomes empty.
StockMarketABM.OrderBookMod.LimitOrderBookType
mutable struct LimitOrderBook

Bid and ask sides are stored as SortedDicts keyed by price. Each key maps to a PriceLevel{LiveOrder}. loc maps order IDs to their location for O(1) cancel. reg stores the full order specs for logging/replay.

source
StockMarketABM.OrderBookMod.OrderSpecType
struct OrderSpec

Full specification of an order as submitted by a trader. Captures ownership (trader), side/price/size, policy settings (TIF/otype), timing metadata, and the traded instrument. Useful for logging, analysis and reconstructing the book.

source
StockMarketABM.OrderBookMod.add_order!Method
add_order!(ob, spec::OrderSpec) -> Bool

Insert a limit order described by spec into the appropriate side of the book. Market orders (spec.price === nothing) are rejected because they bypass the book and should be handled directly by the matching engine.

source
StockMarketABM.OrderBookMod.available_qtyMethod
available_qty(ob, side, price_limit; stop_at=zero(Qty)) -> Qty

Return the total executable quantity on the opposite side of the book up to and including price_limit (<= when lifting asks, >= when hitting bids). Setting stop_at > 0 short-circuits the scan once at least that much quantity is accumulated, which keeps FOK-style checks linear in the requested size.

source
StockMarketABM.OrderBookMod.consume!Method
consume!(ob, side, qty; price_limit=nothing)

Remove up to qty from the best resting order on the opposite side of side. Returns nothing when no liquidity matches the optional price_limit constraint, otherwise a named tuple (price, order, spec, filled, remaining) where order is the original resting LiveOrder, spec is the pre-consumption OrderSpec, filled is the executed quantity and remaining the leftover on that order.

source
StockMarketABM.OrderBookMod.get_depthMethod
get_depth(ob, side; top=0) -> Vector{Tuple{Price,Qty}}

Return the aggregated depth for side as (price, qty) tuples ordered from best to worst (bids descending, asks ascending). When top > 0, only that many levels are returned. The reported quantities are the current level_qty for each price level, so cancelled slots that have not yet been compacted are excluded. Runtime scales linearly with the number of traversed levels (O(min(top, n_levels(side)))), making the operation inexpensive for small top and proportional to book depth otherwise.

source
StockMarketABM.OrderBookMod.get_levelMethod
get_level(ob, side, price) -> PriceLevel

Fetch the price level for side at price, creating a fresh PriceLevel when the level does not yet exist. Subsequent calls reuse the cached instance, so callers can freely push/cancel without re-checking for presence.

source