rusty_model/data/
best_bid_ask.rs

1//! Best bid/ask (top-of-book) quotes
2//!
3//! This module provides structures for representing the best bid and ask prices
4//! in the market, commonly used for quick price references and spread calculations.
5
6use crate::instruments::InstrumentId;
7use rust_decimal::Decimal;
8
9/// Best bid and ask prices (top-of-book quote)
10///
11/// Represents the current best bid and ask prices available in the market.
12/// This is the most basic market data structure, showing the tightest spread.
13#[derive(Debug, Clone, PartialEq, Eq, Hash)]
14pub struct BestBidAsk {
15    /// The instrument this quote is for
16    pub instrument_id: InstrumentId,
17
18    /// Best bid price (highest buy price)
19    pub bid_price: Decimal,
20
21    /// Best bid size
22    pub bid_size: Decimal,
23
24    /// Best ask price (lowest sell price)
25    pub ask_price: Decimal,
26
27    /// Best ask size
28    pub ask_size: Decimal,
29
30    /// Exchange timestamp (nanoseconds)
31    pub exchange_timestamp_ns: u64,
32
33    /// Local receive timestamp (nanoseconds)
34    pub local_timestamp_ns: u64,
35}
36
37impl BestBidAsk {
38    /// Create a new best bid/ask quote
39    #[must_use]
40    pub const fn new(
41        instrument_id: InstrumentId,
42        bid_price: Decimal,
43        bid_size: Decimal,
44        ask_price: Decimal,
45        ask_size: Decimal,
46        exchange_timestamp_ns: u64,
47        local_timestamp_ns: u64,
48    ) -> Self {
49        Self {
50            instrument_id,
51            bid_price,
52            bid_size,
53            ask_price,
54            ask_size,
55            exchange_timestamp_ns,
56            local_timestamp_ns,
57        }
58    }
59
60    /// Calculate the spread (ask - bid)
61    #[inline]
62    #[must_use]
63    pub fn spread(&self) -> Decimal {
64        self.ask_price - self.bid_price
65    }
66
67    /// Calculate the mid price ((ask + bid) / 2)
68    #[inline]
69    #[must_use]
70    pub fn mid_price(&self) -> Decimal {
71        (self.ask_price + self.bid_price) / Decimal::TWO
72    }
73
74    /// Calculate the spread as a percentage of mid price
75    #[inline]
76    #[must_use]
77    pub fn spread_percentage(&self) -> Option<Decimal> {
78        let mid = self.mid_price();
79        if mid.is_zero() {
80            None
81        } else {
82            Some(self.spread() / mid * Decimal::from(100))
83        }
84    }
85}