Skip to main content

OrderBook

Struct OrderBook 

Source
pub struct OrderBook { /* private fields */ }
Expand description

Live order book for a single symbol.

Implementations§

Source§

impl OrderBook

Source

pub fn new(symbol: impl Into<String>) -> Self

Create an empty order book for the given symbol.

Source

pub fn apply(&mut self, delta: BookDelta) -> Result<(), StreamError>

Apply an incremental delta. quantity == 0 removes the level.

§Errors
Source

pub fn reset( &mut self, bids: Vec<PriceLevel>, asks: Vec<PriceLevel>, ) -> Result<(), StreamError>

Reset the book from a full snapshot, also resetting the sequence counter.

Source

pub fn best_bid(&self) -> Option<PriceLevel>

Best bid (highest).

Source

pub fn best_ask(&self) -> Option<PriceLevel>

Best ask (lowest).

Source

pub fn best_bid_qty(&self) -> Option<Decimal>

Resting quantity at the best bid level.

Shorthand for self.best_bid().map(|l| l.quantity).

Source

pub fn best_ask_qty(&self) -> Option<Decimal>

Resting quantity at the best ask level.

Shorthand for self.best_ask().map(|l| l.quantity).

Source

pub fn mid_price(&self) -> Option<Decimal>

Mid price.

Source

pub fn weighted_mid_price(&self) -> Option<Decimal>

Quantity-weighted mid price.

(bid_price × ask_qty + ask_price × bid_qty) / (bid_qty + ask_qty).

Gives a better estimate of fair value than the arithmetic mid when the best-bid and best-ask have very different resting quantities. Returns None if either side is empty or total quantity is zero.

Source

pub fn top_of_book(&self) -> Option<(PriceLevel, PriceLevel)>

Returns (best_bid, best_ask) in a single call, or None if either side is absent.

Source

pub fn price_range(&self) -> Option<Decimal>

Full displayed price range: best_ask - worst_displayed_bid.

Wider than spread() which only uses the top-of-book. Returns None if either side is empty.

Source

pub fn spread(&self) -> Option<Decimal>

Spread.

Source

pub fn is_empty(&self) -> bool

Returns true if both sides of the book have no resting orders.

Source

pub fn total_notional_both_sides(&self) -> Decimal

Combined notional value (price × quantity) across both bid and ask sides.

Source

pub fn price_level_exists(&self, side: BookSide, price: Decimal) -> bool

Returns true if a resting order exists at price on side.

Source

pub fn clear(&mut self)

Remove all price levels from both sides of the book.

Also clears the last seen sequence number. Useful when reconnecting to an exchange feed and waiting for a fresh snapshot before applying deltas.

Source

pub fn bid_depth(&self) -> usize

Number of bid levels.

Source

pub fn ask_depth(&self) -> usize

Number of ask levels.

Source

pub fn bid_volume_total(&self) -> Decimal

Total resting quantity across all bid levels.

Source

pub fn ask_volume_total(&self) -> Decimal

Total resting quantity across all ask levels.

Source

pub fn total_notional(&self, side: BookSide) -> Decimal

Total notional value (Σ price × quantity) across all levels on the given side.

Useful for comparing the dollar value committed to each side of the book, rather than just the raw quantity.

Source

pub fn is_one_sided(&self) -> bool

Returns true if exactly one side (bids or asks) has levels and the other is empty. An empty book returns false.

Source

pub fn level_count_imbalance(&self) -> Option<f64>

Imbalance between number of bid and ask price levels.

Returns (bid_levels - ask_levels) / (bid_levels + ask_levels) as f64 in the range [-1.0, 1.0]. Returns None when the book is empty.

Source

pub fn bid_ask_spread_bps(&self) -> Option<f64>

Bid-ask spread in basis points: (ask − bid) / mid × 10_000.

Returns None if either side of the book is empty or the mid-price is zero.

Source

pub fn total_bid_volume(&self) -> Decimal

👎Deprecated since 2.2.0:

Use bid_volume_total() instead

Total resting quantity across all bid levels.

Alias for bid_volume_total.

Source

pub fn total_ask_volume(&self) -> Decimal

👎Deprecated since 2.2.0:

Use ask_volume_total() instead

Total resting quantity across all ask levels.

Alias for ask_volume_total.

Source

pub fn cumulative_bid_volume(&self, n: usize) -> Decimal

Sum of the top n bid levels’ quantities (best n bids).

If fewer than n bid levels exist, sums all available levels. Returns Decimal::ZERO when the bid side is empty.

Source

pub fn cumulative_ask_volume(&self, n: usize) -> Decimal

Sum of the top n ask levels’ quantities (best n asks).

If fewer than n ask levels exist, sums all available levels. Returns Decimal::ZERO when the ask side is empty.

Source

pub fn top_n_bids(&self, n: usize) -> Vec<PriceLevel>

Best n bid levels as PriceLevels, sorted best-first (highest price first).

If fewer than n levels exist, all are returned.

Source

pub fn top_n_asks(&self, n: usize) -> Vec<PriceLevel>

Best n ask levels as PriceLevels, sorted best-first (lowest price first).

If fewer than n levels exist, all are returned.

Source

pub fn depth_ratio(&self, n: usize) -> Option<f64>

Ratio of cumulative bid volume to cumulative ask volume across top n levels.

Returns None when the ask side is empty (avoids division by zero). Values > 1.0 indicate buy-side pressure; values < 1.0 indicate sell-side pressure.

Source

pub fn ask_wall(&self, min_qty: Decimal) -> Option<PriceLevel>

The cheapest ask level with quantity ≥ min_qty, or None if no such level exists.

Scans ask levels from the tightest (best) price outward. Useful for detecting large sell walls sitting near the top of the book.

Source

pub fn bid_wall(&self, min_qty: Decimal) -> Option<PriceLevel>

The highest bid level with quantity ≥ min_qty, or None if no such level exists.

Scans bid levels from the best (highest) price downward. Useful for detecting large buy walls sitting near the top of the book.

Source

pub fn bid_levels_above(&self, price: Decimal) -> usize

Number of bid levels with price strictly above price.

Useful for measuring how much resting bid interest sits above a given reference price (e.g. the last trade price).

Source

pub fn ask_levels_below(&self, price: Decimal) -> usize

Number of ask levels with price strictly below price.

Useful for measuring how much resting ask interest sits below a given reference price (e.g. the last trade price).

Source

pub fn bid_ask_volume_ratio(&self) -> Option<f64>

Ratio of total bid volume to total ask volume.

Returns None when either side has zero volume (avoids division by zero and meaningless ratios on empty books). A value > 1.0 means more buying interest; < 1.0 means more selling pressure.

Source

pub fn top_n_bid_volume(&self, n: usize) -> Decimal

Total volume across the top n bid price levels (best-to-worst order).

If there are fewer than n levels, the volume of all existing levels is returned. Returns Decimal::ZERO for an empty bid side.

Source

pub fn imbalance_ratio(&self) -> Option<f64>

Normalised order-book imbalance: (bid_vol − ask_vol) / (bid_vol + ask_vol).

Returns a value in [-1.0, 1.0]. +1.0 means all volume is on the bid side (strong buying pressure); -1.0 means all volume is on the ask side (strong selling pressure). Returns None when both sides are empty (sum is zero).

Source

pub fn top_n_ask_volume(&self, n: usize) -> Decimal

Total volume across the top n ask price levels (best-to-worst order, i.e. lowest asks first).

If there are fewer than n levels, the volume of all existing levels is returned. Returns Decimal::ZERO for an empty ask side.

Source

pub fn has_ask_at(&self, price: Decimal) -> bool

Returns true if there is a non-zero ask entry at exactly price.

Source

pub fn bid_ask_depth(&self) -> (usize, usize)

Returns (bid_levels, ask_levels) — the number of distinct price levels on each side of the book.

Source

pub fn total_book_volume(&self) -> Decimal

Total volume across all bid and ask levels combined.

Alias for total_volume.

Source

pub fn price_range_bids(&self) -> Option<Decimal>

Price distance from the best bid to the worst (lowest) bid.

Returns None if there are fewer than 2 bid levels.

Source

pub fn spread_pct(&self) -> Option<f64>

Spread as a percentage of the mid-price: spread / mid × 100.

Returns None if either best bid or best ask is absent, or if the mid-price is zero.

Source

pub fn is_tight_spread(&self, threshold: Decimal) -> bool

Returns true if the bid-ask spread is at or below threshold.

Returns false when either side is empty (no spread to compare).

Source

pub fn total_depth(&self) -> usize

Total number of price levels across both sides of the book.

Equivalent to bid_depth() + ask_depth().

Source

pub fn total_volume(&self) -> Decimal

Total resting quantity across both sides of the book.

Equivalent to bid_volume_total() + ask_volume_total().

Source

pub fn symbol(&self) -> &str

The symbol this order book tracks.

Source

pub fn last_sequence(&self) -> Option<u64>

The sequence number of the most recently applied delta, if any.

Source

pub fn quote_imbalance(&self) -> Option<f64>

Best-bid quantity as a fraction of (best_bid_qty + best_ask_qty).

Values near 1.0 indicate the best bid has dominant size; near 0.0 the best ask dominates. Returns None when either side is empty or both quantities are zero.

Source

pub fn contains_bid(&self, price: Decimal) -> bool

Returns true if a bid level exists at exactly price.

Source

pub fn contains_ask(&self, price: Decimal) -> bool

Returns true if an ask level exists at exactly price.

Source

pub fn volume_at_bid(&self, price: Decimal) -> Option<Decimal>

Returns the resting quantity at price on the bid side, or None if absent.

Source

pub fn volume_at_ask(&self, price: Decimal) -> Option<Decimal>

Returns the resting quantity at price on the ask side, or None if absent.

Source

pub fn level_count(&self, side: BookSide) -> usize

Number of resting price levels on the given side.

Unified version of bid_depth / ask_depth for runtime dispatch by side.

Source

pub fn level_count_both_sides(&self) -> usize

Total number of distinct price levels across both bid and ask sides.

Alias for total_depth.

Source

pub fn ask_price_at_rank(&self, n: usize) -> Option<Decimal>

The nth-best ask price (0 = best/lowest ask).

Returns None if there are fewer than n + 1 ask levels.

Source

pub fn bid_price_at_rank(&self, n: usize) -> Option<Decimal>

The nth-best bid price (0 = best/highest bid).

Returns None if there are fewer than n + 1 bid levels.

Source

pub fn quote_density(&self, side: BookSide) -> Option<Decimal>

Number of distinct price levels per unit of price range on the given side.

quote_density = level_count / (max_price - min_price). Returns None if the side has fewer than 2 levels (range is zero).

Source

pub fn bid_ask_qty_ratio(&self) -> Option<f64>

Ratio of total bid quantity to total ask quantity.

Values > 1 indicate heavier buy-side resting volume; < 1 more sell-side. Returns None if the ask side has zero volume. Alias for bid_ask_ratio.

Source

pub fn top_bid_qty(&self) -> Option<Decimal>

Quantity resting at the best bid price.

Returns None if the bid side is empty. Alias for best_bid_qty.

Source

pub fn top_ask_qty(&self) -> Option<Decimal>

Quantity resting at the best ask price.

Returns None if the ask side is empty. Alias for best_ask_qty.

Source

pub fn cumulative_bid_qty(&self, n: usize) -> Decimal

Sum of quantity across the best n bid levels.

Returns total bid quantity if n >= bid_count. Alias for cumulative_bid_volume.

Source

pub fn cumulative_ask_qty(&self, n: usize) -> Decimal

Sum of quantity across the best n ask levels.

Returns total ask quantity if n >= ask_count. Alias for cumulative_ask_volume.

Source

pub fn ladder_balance(&self, n: usize) -> Option<f64>

Ratio of top-n bid quantity to top-n ask quantity.

Values > 1 indicate more buy-side depth in the top n levels. Returns None if ask side has no volume in top n levels.

Source

pub fn ask_bid_level_ratio(&self) -> Option<f64>

Ratio of ask levels to bid levels: ask_count / bid_count.

Values > 1 indicate more ask granularity; < 1 more bid granularity. Returns None if the bid side is empty.

Source

pub fn depth_at_price(&self, price: Decimal, side: BookSide) -> Option<Decimal>

Resting quantity at an exact price level on the given side.

Returns None if there is no resting order at that price. This is a unified alternative to calling volume_at_bid / volume_at_ask separately when the side is determined at runtime.

Source

pub fn bid_ask_ratio(&self) -> Option<f64>

Ratio of total bid volume to total ask volume: bid_volume_total / ask_volume_total.

Returns None if the ask side is empty (to avoid division by zero). Values > 1.0 indicate more buy-side depth; < 1.0 indicates more sell-side depth.

Source

pub fn all_bids(&self) -> Vec<PriceLevel>

All bid levels, sorted descending by price (highest first).

Equivalent to top_bids(usize::MAX) but more expressive when you want the complete depth without specifying a level count.

Source

pub fn all_asks(&self) -> Vec<PriceLevel>

All ask levels, sorted ascending by price (lowest first).

Equivalent to top_asks(usize::MAX) but more expressive when you want the complete depth without specifying a level count.

Source

pub fn top_bids(&self, n: usize) -> Vec<PriceLevel>

Top N bids (descending by price).

Source

pub fn top_asks(&self, n: usize) -> Vec<PriceLevel>

Top N asks (ascending by price).

Source

pub fn imbalance(&self) -> Option<f64>

Order-book imbalance at the best bid/ask: (bid_qty - ask_qty) / (bid_qty + ask_qty).

Returns a value in [-1.0, 1.0]:

  • +1.0 means the entire resting quantity is on the bid side (maximum buy pressure).
  • -1.0 means the entire resting quantity is on the ask side (maximum sell pressure).
  • 0.0 means perfectly balanced.

Returns None if either side has no best level.

Source

pub fn bid_ask_imbalance(&self, n: usize) -> Option<f64>

Order-book imbalance using the top n levels on each side.

(Σ bid_qty - Σ ask_qty) / (Σ bid_qty + Σ ask_qty) in [-1.0, 1.0].

Returns None if either side has no levels or total volume is zero.

Source

pub fn vwap(&self, side: BookSide, n: usize) -> Option<Decimal>

Volume-weighted average price (VWAP) of the top n resting levels on side.

Σ(price × qty) / Σ(qty). Returns None if the side has no levels or total volume is zero.

Source

pub fn price_at_volume( &self, side: BookSide, target_volume: Decimal, ) -> Option<Decimal>

Walk the book on side and return the average fill price to absorb target_volume.

Sweeps levels from best to worst until target_volume is consumed, computing the VWAP of the executed portion. If the book has less total volume than target_volume, returns the VWAP of all available liquidity anyway.

Returns None if the side is empty or target_volume is zero.

Source

pub fn depth_imbalance(&self, n: usize) -> Option<f64>

Volume imbalance over the top-n price levels on each side: (bid_vol - ask_vol) / (bid_vol + ask_vol).

Returns a value in [-1, 1]: positive means more resting bid volume, negative means more resting ask volume. Returns None if both sides have zero volume or n == 0.

Unlike imbalance which only uses the best bid/ask quantity, depth_imbalance aggregates across up to n levels providing a broader picture of order book pressure.

Source

pub fn levels(&self, side: BookSide, n: usize) -> Vec<PriceLevel>

Returns the top-n price levels for the given side, sorted best-first.

For bids, levels are sorted descending (highest price first). For asks, levels are sorted ascending (lowest price first). If n exceeds the available levels, all levels are returned.

Source

pub fn bid_volume_at_price(&self, price: Decimal) -> Option<Decimal>

Returns the resting quantity at a specific bid price level, or None if absent.

Source

pub fn ask_volume_at_price(&self, price: Decimal) -> Option<Decimal>

Returns the resting quantity at a specific ask price level, or None if absent.

Source

pub fn snapshot(&self) -> (Vec<PriceLevel>, Vec<PriceLevel>)

Return a full snapshot of all bid and ask levels.

The returned tuple is (bids, asks):

  • bids are sorted descending by price (highest first).
  • asks are sorted ascending by price (lowest first).

Use this after receiving a StreamError::SequenceGap to rebuild the book from a fresh exchange snapshot: call reset with the snapshot levels, then resume applying deltas from the new sequence.

Source

pub fn best_bid_price(&self) -> Option<Decimal>

Returns the best bid price, or None if the bid side is empty.

Source

pub fn best_ask_price(&self) -> Option<Decimal>

Returns the best ask price, or None if the ask side is empty.

Source

pub fn is_crossed(&self) -> bool

Returns true if the book is crossed: best bid ≥ best ask.

A crossed book indicates an invalid state (stale snapshot or missed delta). Under normal operation this should always be false.

Source

pub fn has_bids(&self) -> bool

Returns true if there is at least one bid level in the book.

Source

pub fn has_asks(&self) -> bool

Returns true if there is at least one ask level in the book.

Source

pub fn ask_price_range(&self) -> Option<Decimal>

Price distance from best ask to worst ask (highest ask price - lowest ask price).

Returns None if the ask side is empty.

Source

pub fn bid_price_range(&self) -> Option<Decimal>

Price distance from best bid to worst bid (highest bid price - lowest bid price).

Returns None if the bid side is empty.

Source

pub fn mid_spread_ratio(&self) -> Option<f64>

Spread as a fraction of the mid price: spread / mid_price.

Returns None if the book has no bid or ask, or mid price is zero.

Source

pub fn volume_imbalance(&self) -> Option<f64>

Bid-ask volume imbalance: (bid_vol - ask_vol) / (bid_vol + ask_vol).

Returns a value in [-1.0, 1.0]. Positive = more bid volume; negative = more ask volume. Returns None if both sides are empty.

Source

pub fn fee_estimate( &self, side: BookSide, qty: Decimal, fee_bps: Decimal, ) -> Option<Decimal>

Estimated trading fee for a market order of qty on side, given a fee in basis points.

fee ≈ fill_price * qty * fee_bps / 10_000. Returns fee in base currency. Returns None if the side is empty, qty ≤ 0, or not enough liquidity to fill.

Source

pub fn spread_ticks(&self, tick_size: Decimal) -> Option<Decimal>

Spread expressed as number of ticks: spread / tick_size.

Returns None if either side is empty or tick_size is zero.

Source

pub fn spread_bps(&self) -> Option<f64>

Spread expressed in basis points relative to mid-price: (ask - bid) / mid × 10_000.

Returns None when either side is empty or mid-price is zero.

Source

pub fn depth_at_pct(&self, side: BookSide, pct: f64) -> Option<Decimal>

Cumulative volume within pct percent of the best price on a given side.

For bids: sums quantity at all levels where price >= best_bid * (1 - pct/100). For asks: sums quantity at all levels where price <= best_ask * (1 + pct/100).

Returns None if the side is empty or pct is negative.

Source

pub fn microprice(&self) -> Option<Decimal>

Microprice: volume-weighted mid using top-of-book quantities.

microprice = (ask_qty * best_bid + bid_qty * best_ask) / (bid_qty + ask_qty)

More accurate than simple mid when the order book is imbalanced. Returns None if either side is empty or total quantity is zero.

Source

pub fn best_n_levels(&self, side: BookSide, n: usize) -> Vec<(Decimal, Decimal)>

Returns the top n price levels on a given side as (price, quantity) pairs.

Bid levels are returned in descending price order (best bid first). Ask levels are returned in ascending price order (best ask first). Returns fewer than n entries if the side has fewer levels.

Source

pub fn price_impact(&self, side: BookSide, qty: Decimal) -> Option<Decimal>

Estimated price impact of a market order of qty on the given side.

Walks the book, consuming levels until qty is filled. Returns the weighted average fill price minus the best price (positive = adverse). Returns None if the side is empty or qty is zero/negative.

Source

pub fn total_value_at_level( &self, side: BookSide, price: Decimal, ) -> Option<Decimal>

Total notional value (price × quantity) at a specific price level on a given side.

Returns None if no level exists at price.

Source

pub fn price_impact_buy(&self, quantity: Decimal) -> Option<Decimal>

Estimated volume-weighted average execution price for a market buy of quantity.

Walks up the ask side. Returns None if insufficient liquidity.

Source

pub fn price_impact_sell(&self, quantity: Decimal) -> Option<Decimal>

Estimated volume-weighted average execution price for a market sell of quantity.

Walks down the bid side. Returns None if insufficient liquidity.

Source

pub fn ask_level_count(&self) -> usize

👎Deprecated:

use ask_depth() instead

Number of distinct price levels on the ask side.

Source

pub fn bid_level_count(&self) -> usize

👎Deprecated:

use bid_depth() instead

Number of distinct price levels on the bid side.

Source

pub fn ask_volume_within(&self, price_range: Decimal) -> Decimal

Cumulative ask volume at levels within price_range of the best ask.

Sums all ask quantities where price <= best_ask + price_range. Returns Decimal::ZERO if the ask side is empty.

Source

pub fn bid_volume_within(&self, price_range: Decimal) -> Decimal

Cumulative bid volume at levels within price_range of the best bid.

Sums all bid quantities where price >= best_bid - price_range. Returns Decimal::ZERO if the bid side is empty.

Source

pub fn ask_volume_above(&self, price: Decimal) -> Decimal

Total ask quantity at price levels strictly above price.

Source

pub fn bid_volume_below(&self, price: Decimal) -> Decimal

Total bid quantity at price levels strictly below price.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more