A point-in-time normalized order book snapshot.
A MarketSnapshot is the input an execution model uses to simulate a
fill: it carries the resting bids and asks for one
PaperEx.Instrument, in normalized form (price descending for bids,
price ascending for asks).
Adapters produce snapshots from exchange-specific payloads via the
PaperEx.Adapter.normalize_snapshot/2 callback. The engine never fetches a
snapshot itself — this package does no IO. Callers either pass a
snapshot in directly or build one from data their adapter normalized.
Fields
:instrument_id(required) — matches aPaperEx.Instrument.id. The engine uses this to associate the snapshot with the right position bucket.:bids— list of{price, size}tuples, sorted descending by price (best bid first). Defaults to[].:asks— list of{price, size}tuples, sorted ascending by price (best ask first). Defaults to[].:as_of—DateTime.t()when the snapshot was observed. Defaults toDateTime.utc_now/0.:metadata— free-form map. Adapters can stash raw payloads here.
Convenience accessors
best_bid/1,best_ask/1—{price, size}of the top level on each side, ornilif that side is empty.midpoint/1—(best_bid_price + best_ask_price) / 2, ornilif either side is empty.spread/1—best_ask_price - best_bid_price, ornilif either side is empty.
The engine and the default execution model use these accessors rather than indexing the lists directly, so adapters do not need to expose extra helpers.
Sorting invariant
new/1 does not sort the lists for you; it only validates the
shape. Adapters are responsible for producing already-sorted lists.
That keeps new/1 cheap and the data contract explicit: a snapshot
that comes off an exchange WebSocket usually arrives sorted.
Summary
Functions
Best ask level, or nil if there are no asks.
Best bid level, or nil if there are no bids.
Midpoint price (best_bid_price + best_ask_price) / 2, or nil if
either side is empty.
Builds a MarketSnapshot from a map or keyword list.
Bid-ask spread best_ask_price - best_bid_price, or nil if
either side is empty.
Types
Functions
Best ask level, or nil if there are no asks.
Best bid level, or nil if there are no bids.
Midpoint price (best_bid_price + best_ask_price) / 2, or nil if
either side is empty.
Builds a MarketSnapshot from a map or keyword list.
Required: :instrument_id. :bids and :asks default to [].
Each level must be a {price, size} tuple with both numbers
non-negative and size > 0.
Bid-ask spread best_ask_price - best_bid_price, or nil if
either side is empty.