Skip to main content

Module matching_core

Module matching_core 

Source
Expand description

Order matching core shared by the OrderMatchingEngine and other components.

Evaluates resting orders against a market-price snapshot and returns fill or trigger actions without removing orders from the books.

§Book Layout

Each side has separate limit and stop books, keyed by price in a BTreeMap:

  • Limit book: keyed by limit price. Holds orders with a limit price and no trigger price, including converted MARKET_TO_LIMIT orders and triggered stop-limit orders whose trigger price has been cleared.
  • Stop book: keyed by trigger price. Holds STOP_*, *_IF_TOUCHED, and TRAILING_STOP_* orders that require trigger checks.

A per-side pending SmallVec holds orders with neither price, such as MARKET_TO_LIMIT orders before conversion. These orders remain visible in lookups and snapshots but are excluded from matching.

§Ordering Invariant

OrderMatchingCore::iterate processes bids before asks. On each side, limits precede stops, with the following price order:

  • Bid limits: highest price first.
  • Ask limits: lowest price first.
  • Bid stops: lowest trigger first, following the crossing order as the ask rises through buy-stop levels.
  • Ask stops: highest trigger first, following the crossing order as the bid falls through sell-stop levels.

Each price level stores orders in a SmallVec in insertion order, preserving time priority (FIFO at the same price). Traversing the BTreeMap forward or backward supplies price order without a separate sort. Order snapshots use the same book order and append pending orders after the stops on each side.

§Modify Semantics

The core has no in-place modify API. To change a resting order, call OrderMatchingCore::delete_order followed by OrderMatchingCore::add_order. The order joins the back of its price level, even if the price is unchanged. This models loss of queue position on price changes, but also loses position for quantity-only changes. Preserving position for quantity-only changes would require an in-place update API.

§Snapshot Ordering Limitation

OrderMatchingCore::iterate_bids and OrderMatchingCore::iterate_asks emit all matchable limits before triggered stops on their side. This emission order is deterministic, but it does not reconstruct the order in which prices cross levels. A stop can trigger during a price move and then aggress against the limit book; a snapshot alone cannot recover that sequence when both limits and stops are matchable.

Callers must not interpret the limits-then-stops sequence as price-path order, particularly when a gap crosses several limit and stop levels on the same side. The engine supplies the snapshot. Replaying crossings would require additional price-path information, such as previous bid/ask values, and an engine/core change to emit fills and triggers in crossing order.

§Duplicate Inserts

Each client_order_id must appear at most once across both sides. OrderMatchingCore::add_order panics on duplicate IDs when debug assertions are enabled. Without debug assertions, adding the same ID twice without an intervening OrderMatchingCore::delete_order leaves duplicate entries that can both match.

§Performance

Each price-level SmallVec stores up to four orders inline, covering the common case of 1-3 orders without a per-bucket heap allocation. The bucket spills to the heap when it exceeds that capacity.

For L distinct price levels and B orders at a level, insertion requires an O(log L) tree lookup and an amortized O(1) append. A bucket allocation can move O(B) orders. Deletion requires an O(log L) tree lookup and an O(B) scan and shift. Both L and B are expected to be small in typical use.

An AHashMap maps each ClientOrderId to its side and optional book location. OrderMatchingCore::order_exists uses only this index. OrderMatchingCore::get_order and OrderMatchingCore::delete_order use the index to locate the book, then perform a tree lookup and bucket scan. Pending orders require only the per-side pending-bucket scan after the index lookup. The index serves only point queries and is never iterated, so its randomized hash seed does not affect ordering.

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.