rustrade_data/exchange/bybit/book/
mod.rs1use crate::{
2 books::{Level, OrderBook, OrderBookTimes},
3 event::{MarketEvent, MarketIter},
4 subscription::book::OrderBookEvent,
5};
6use chrono::Utc;
7use rust_decimal::Decimal;
8use rustrade_instrument::exchange::ExchangeId;
9use serde::{Deserialize, Serialize};
10
11use super::message::{BybitPayload, BybitPayloadKind};
12
13pub mod l1;
15
16pub mod l2;
18
19pub 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 time_received = Utc::now();
44 let time_exchange = message.time;
48 let orderbook = OrderBook::new(
49 message.data.sequence,
50 OrderBookTimes {
53 time_engine: None,
54 time_exchange: Some(time_exchange),
55 time_received,
56 },
57 message.data.bids,
58 message.data.asks,
59 );
60
61 let kind = match message.kind {
62 BybitPayloadKind::Snapshot => OrderBookEvent::Snapshot(orderbook),
63 BybitPayloadKind::Delta => OrderBookEvent::Update(orderbook),
64 };
65
66 Self(vec![Ok(MarketEvent {
67 time_exchange,
68 time_received,
69 exchange,
70 instrument,
71 kind,
72 })])
73 }
74}
75
76#[derive(Clone, Copy, PartialEq, PartialOrd, Debug, Deserialize, Serialize)]
85pub struct BybitLevel {
86 #[serde(with = "rust_decimal::serde::str")]
87 pub price: Decimal,
88 #[serde(with = "rust_decimal::serde::str")]
89 pub amount: Decimal,
90}
91
92impl From<BybitLevel> for Level {
93 fn from(level: BybitLevel) -> Self {
94 Self {
95 price: level.price,
96 amount: level.amount,
97 }
98 }
99}
100
101#[cfg(test)]
102#[allow(clippy::unwrap_used)] mod tests {
104 use super::*;
105
106 mod de {
107 use super::*;
108 use rust_decimal_macros::dec;
109
110 #[test]
111 fn test_bybit_level() {
112 let input = r#"["16493.50", "0.006"]"#;
113 assert_eq!(
114 serde_json::from_str::<BybitLevel>(input).unwrap(),
115 BybitLevel {
116 price: dec!(16493.50),
117 amount: dec!(0.006)
118 },
119 )
120 }
121 }
122}