rusty_feeder/exchange/bybit/data/
orderbook.rs

1use rust_decimal::Decimal;
2use serde::{Deserialize, Serialize};
3use smallvec::SmallVec;
4use smartstring::alias::String;
5
6/// Bybit orderbook response
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct OrderbookResponse {
9    /// WebSocket topic (e.g., "orderbook.50.BTCUSDT")
10    pub topic: String,
11    /// Message type (e.g., "snapshot" or "delta")
12    pub type_field: Option<String>,
13    /// Timestamp in milliseconds
14    pub ts: u64,
15    /// Orderbook data payload
16    pub data: OrderbookData,
17}
18
19/// Orderbook data structure
20#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct OrderbookData {
22    /// Trading pair symbol
23    pub symbol: String,
24    /// Bid price levels: [price, size]
25    pub b: SmallVec<[[String; 2]; 32]>,
26    /// Ask price levels: [price, size]
27    pub a: SmallVec<[[String; 2]; 32]>,
28    /// Update ID
29    pub u: u64,
30    /// Sequence number
31    pub seq: u64,
32}
33
34/// Parsed orderbook data optimized for performance
35#[derive(Debug, Clone)]
36pub struct ParsedOrderbookData {
37    /// Trading pair symbol
38    pub symbol: String,
39    /// Timestamp in milliseconds
40    pub timestamp: u64,
41    /// Update ID
42    pub update_id: u64,
43    /// Sequence number
44    pub sequence: u64,
45    /// Bid levels as (price, size) tuples
46    pub bids: SmallVec<[(Decimal, Decimal); 16]>,
47    /// Ask levels as (price, size) tuples
48    pub asks: SmallVec<[(Decimal, Decimal); 16]>,
49}
50
51impl ParsedOrderbookData {
52    /// Parse from the raw orderbook response
53    pub fn from_response(response: &OrderbookResponse) -> Option<Self> {
54        let data = &response.data;
55
56        // Parse bids
57        let bids = data
58            .b
59            .iter()
60            .filter_map(|bid| {
61                if bid.len() != 2 {
62                    return None;
63                }
64
65                let price = bid[0].parse::<Decimal>().ok()?;
66                let size = bid[1].parse::<Decimal>().ok()?;
67
68                Some((price, size))
69            })
70            .collect();
71
72        // Parse asks
73        let asks = data
74            .a
75            .iter()
76            .filter_map(|ask| {
77                if ask.len() != 2 {
78                    return None;
79                }
80
81                let price = ask[0].parse::<Decimal>().ok()?;
82                let size = ask[1].parse::<Decimal>().ok()?;
83
84                Some((price, size))
85            })
86            .collect();
87
88        Some(Self {
89            symbol: data.symbol.clone(),
90            timestamp: response.ts,
91            update_id: data.u,
92            sequence: data.seq,
93            bids,
94            asks,
95        })
96    }
97}