Skip to main content

Module matching_core

Module matching_core 

Source
Expand description

A common order matching core for the OrderMatchingEngine and other components.

§Book layout

Each side has two separate books, mirroring real-venue architecture:

  • Limit book: BTreeMap<Price, OrderBucket> keyed by limit price. Holds plain LIMIT orders.
  • Stop book: BTreeMap<Price, OrderBucket> keyed by trigger price. Holds STOP_*, *_IF_TOUCHED, and TRAILING_STOP_* orders that need trigger checking before matching.

Plus a per-side pending SmallVec for orders without a key (e.g. MARKET_TO_LIMIT before conversion).

§Ordering invariant

Orders are matched in price-time priority, with limits processed before stops on each side:

  • Bid limits: best (highest) price first via iter().rev().
  • Ask limits: best (lowest) price first via iter().
  • Bid stops: closest trigger first via iter() (lowest trigger crosses first as ask climbs through resting buy stops).
  • Ask stops: closest trigger first via iter().rev() (highest trigger crosses first as bid drops through resting sell stops).

Within a price level orders are stored in a SmallVec in insertion order, preserving time priority (FIFO at the same price). No active sorting happens; the BTreeMap’s tree shape gives price ordering for free.

§Modify semantics

The core does not expose an in-place modify API. Any change to a resting order must call OrderMatchingCore::delete_order followed by OrderMatchingCore::add_order, which lands the order at the back of its (new or unchanged) price level. This matches real-venue behavior for price-changing modifies but loses queue position on quantity-only modifies. An in-place quantity-update API could be added later if the engine wants to preserve queue position on those.

§Known limitation: limits-then-stops emission

On each side, OrderMatchingCore::iterate_bids and OrderMatchingCore::iterate_asks emit all matchable limits before any triggered stops. In real venues stops trigger as the price crosses them and only then aggress against the limit book, so a snapshot iteration that sees both kinds matchable simultaneously cannot perfectly reconstruct the temporal order. The matching engine drives the snapshot, so a future engine change that feeds the previous bid/ask to the core could replay the price path and emit triggers/fills in cross-time order. Until then, callers that depend on price-path ordering (e.g. multi-level gap scenarios with both matchable limits and matchable stops on the same side) should treat that interleaving as undefined.

§Duplicate inserts

add_order does not deduplicate. Adding the same client_order_id twice without an intervening delete_order puts two RestingOrder entries in the vec and they will both match. Callers must ensure each client_order_id appears at most once across both sides.

§Performance

Per-level buckets are SmallVecs with INLINE_ORDERS_PER_LEVEL inline slots so the common case (1-3 orders per price) avoids heap allocation per bucket. Above that threshold the bucket spills to the heap. Adds and deletes are O(log L) for the BTreeMap lookup plus O(B) for the bucket scan/shift, where L is the number of distinct price levels per book and B is orders at that level: both small in practice.

An AHashMap index from ClientOrderId to (side, BookKind, Price) makes OrderMatchingCore::get_order, OrderMatchingCore::order_exists, and the lookup portion of OrderMatchingCore::delete_order hash-fast; the follow-on bucket scan is O(B). The map is used purely for point queries (never iterated), so its randomized seed does not affect determinism.

Structs§

OrderMatchingCore
A generic order matching core. See module docs for ordering, modify, duplicate, and performance contracts.
RestingOrder
Lightweight order information for matching/trigger checking.

Enums§

MatchAction
An action returned by OrderMatchingCore::iterate when an order matches.

Constants§

INLINE_ORDERS_PER_LEVEL
Inline capacity for orders at a single price level. Sized to cover the typical 1-3 orders per level; above this the per-bucket SmallVec spills to the heap.