barter_data/exchange/bybit/book/
mod.rs

1use crate::{
2    books::{Level, OrderBook},
3    event::{MarketEvent, MarketIter},
4    subscription::book::OrderBookEvent,
5};
6use barter_instrument::exchange::ExchangeId;
7use chrono::Utc;
8use rust_decimal::Decimal;
9use serde::{Deserialize, Serialize};
10
11use super::message::{BybitPayload, BybitPayloadKind};
12
13/// Level 1 OrderBook types.
14pub mod l1;
15
16/// Level 2 OrderBook types.
17pub mod l2;
18
19/// Terse type alias for an [`BybitOrderBookMessage`] OrderBook WebSocket message.
20pub type BybitOrderBookMessage = BybitPayload<BybitOrderBookInner>;
21
22#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
23pub struct BybitOrderBookInner {
24    #[serde(rename = "b")]
25    pub bids: Vec<BybitLevel>,
26
27    #[serde(rename = "a")]
28    pub asks: Vec<BybitLevel>,
29
30    #[serde(rename = "u")]
31    pub update_id: u64,
32
33    #[serde(rename = "seq")]
34    pub sequence: u64,
35}
36
37impl<InstrumentKey> From<(ExchangeId, InstrumentKey, BybitOrderBookMessage)>
38    for MarketIter<InstrumentKey, OrderBookEvent>
39{
40    fn from(
41        (exchange, instrument, message): (ExchangeId, InstrumentKey, BybitOrderBookMessage),
42    ) -> Self {
43        let orderbook = OrderBook::new(
44            message.data.sequence,
45            Some(message.time),
46            message.data.bids,
47            message.data.asks,
48        );
49
50        let kind = match message.kind {
51            BybitPayloadKind::Snapshot => OrderBookEvent::Snapshot(orderbook),
52            BybitPayloadKind::Delta => OrderBookEvent::Update(orderbook),
53        };
54
55        Self(vec![Ok(MarketEvent {
56            time_exchange: message.time,
57            time_received: Utc::now(),
58            exchange,
59            instrument,
60            kind,
61        })])
62    }
63}
64
65/// [`Bybit`](super::Bybit) OrderBook level.
66///
67/// #### Raw Payload Examples
68/// See docs: <https://bybit-exchange.github.io/docs/v5/websocket/public/orderbook#response-parameters>
69///
70/// ```json
71/// ["16493.50", "0.006"]
72/// ```
73#[derive(Clone, Copy, PartialEq, PartialOrd, Debug, Deserialize, Serialize)]
74pub struct BybitLevel {
75    #[serde(with = "rust_decimal::serde::str")]
76    pub price: Decimal,
77    #[serde(with = "rust_decimal::serde::str")]
78    pub amount: Decimal,
79}
80
81impl From<BybitLevel> for Level {
82    fn from(level: BybitLevel) -> Self {
83        Self {
84            price: level.price,
85            amount: level.amount,
86        }
87    }
88}
89
90#[cfg(test)]
91mod tests {
92    use super::*;
93
94    mod de {
95        use super::*;
96        use rust_decimal_macros::dec;
97
98        #[test]
99        fn test_bybit_level() {
100            let input = r#"["16493.50", "0.006"]"#;
101            assert_eq!(
102                serde_json::from_str::<BybitLevel>(input).unwrap(),
103                BybitLevel {
104                    price: dec!(16493.50),
105                    amount: dec!(0.006)
106                },
107            )
108        }
109    }
110}