barter_data/subscription/
book.rs

1use super::SubscriptionKind;
2use crate::books::{Level, OrderBook, mid_price, volume_weighted_mid_price};
3use barter_macro::{DeSubKind, SerSubKind};
4use chrono::{DateTime, Utc};
5use derive_more::Constructor;
6use rust_decimal::Decimal;
7use serde::{Deserialize, Serialize};
8
9/// Barter [`Subscription`](super::Subscription) [`SubscriptionKind`] that yields [`OrderBookL1`]
10/// market events.
11///
12/// Level 1 refers to the best non-aggregated bid and ask [`Level`] on each side of the
13/// [`OrderBook`].
14#[derive(
15    Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default, DeSubKind, SerSubKind,
16)]
17pub struct OrderBooksL1;
18
19impl SubscriptionKind for OrderBooksL1 {
20    type Event = OrderBookL1;
21    fn as_str(&self) -> &'static str {
22        "l1"
23    }
24}
25
26impl std::fmt::Display for OrderBooksL1 {
27    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28        write!(f, "{}", self.as_str())
29    }
30}
31
32/// Normalised Barter [`OrderBookL1`] snapshot containing the latest best bid and ask.
33#[derive(
34    Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default, Deserialize, Serialize, Constructor,
35)]
36pub struct OrderBookL1 {
37    pub last_update_time: DateTime<Utc>,
38    pub best_bid: Option<Level>,
39    pub best_ask: Option<Level>,
40}
41
42impl OrderBookL1 {
43    /// Calculate the mid-price by taking the average of the best bid and ask prices.
44    ///
45    /// See Docs: <https://www.quantstart.com/articles/high-frequency-trading-ii-limit-order-book>
46    pub fn mid_price(&self) -> Option<Decimal> {
47        match (self.best_ask, self.best_bid) {
48            (Some(best_ask), Some(best_bid)) => Some(mid_price(best_bid.price, best_ask.price)),
49            _ => None,
50        }
51    }
52
53    /// Calculate the volume weighted mid-price (micro-price), weighing the best bid and ask prices
54    /// with their associated amount.
55    ///
56    /// See Docs: <https://www.quantstart.com/articles/high-frequency-trading-ii-limit-order-book>
57    pub fn volume_weighed_mid_price(&self) -> Option<Decimal> {
58        match (self.best_ask, self.best_bid) {
59            (Some(best_ask), Some(best_bid)) => Some(volume_weighted_mid_price(best_bid, best_ask)),
60            _ => None,
61        }
62    }
63}
64
65/// Barter [`Subscription`](super::Subscription) [`SubscriptionKind`] that yields L2
66/// [`OrderBookEvent`] market events
67///
68/// Level 2 refers to an [`OrderBook`] with orders at each price level aggregated.
69#[derive(
70    Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default, DeSubKind, SerSubKind,
71)]
72pub struct OrderBooksL2;
73
74impl SubscriptionKind for OrderBooksL2 {
75    type Event = OrderBookEvent;
76    fn as_str(&self) -> &'static str {
77        "l2"
78    }
79}
80
81impl std::fmt::Display for OrderBooksL2 {
82    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83        write!(f, "{}", self.as_str())
84    }
85}
86
87/// Barter [`Subscription`](super::Subscription) [`SubscriptionKind`] that yields
88/// L3 [`OrderBookEvent`] market events.
89///
90/// Level 3 refers to the non-aggregated [`OrderBook`]. This is a direct replication of the exchange
91/// [`OrderBook`].
92#[derive(
93    Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default, DeSubKind, SerSubKind,
94)]
95pub struct OrderBooksL3;
96
97impl SubscriptionKind for OrderBooksL3 {
98    type Event = OrderBookEvent;
99
100    fn as_str(&self) -> &'static str {
101        "l3"
102    }
103}
104
105impl std::fmt::Display for OrderBooksL3 {
106    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107        write!(f, "{}", self.as_str())
108    }
109}
110
111#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
112pub enum OrderBookEvent {
113    Snapshot(OrderBook),
114    Update(OrderBook),
115}