rusty_feeder/exchange/binance/spot/data/
orderbook.rs1use rust_decimal::Decimal;
7use rust_decimal_macros::dec;
8use serde::{Deserialize, Serialize};
9use smallvec::SmallVec;
10use smartstring::alias::String;
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
14#[repr(align(16))] pub struct OrderbookMessage {
16 #[serde(rename = "e")]
18 pub event_type: String,
19
20 #[serde(rename = "E")]
22 pub event_time: u64,
23
24 #[serde(rename = "s")]
26 pub symbol: String,
27
28 #[serde(rename = "U")]
30 pub first_update_id: u64,
31
32 #[serde(rename = "u")]
34 pub final_update_id: u64,
35
36 #[serde(rename = "b")]
38 pub bids: SmallVec<[SmallVec<[String; 2]>; 32]>,
39
40 #[serde(rename = "a")]
42 pub asks: SmallVec<[SmallVec<[String; 2]>; 32]>,
43}
44
45#[derive(Debug, Clone)]
47#[repr(align(16))] pub struct ParsedOrderbookData {
49 pub symbol: String,
51
52 pub first_update_id: u64,
54
55 pub final_update_id: u64,
57
58 pub event_time: u64,
60
61 pub bids: SmallVec<[(Decimal, Decimal); 32]>,
63
64 pub asks: SmallVec<[(Decimal, Decimal); 32]>,
66}
67
68impl From<OrderbookMessage> for ParsedOrderbookData {
69 fn from(msg: OrderbookMessage) -> Self {
70 let mut bids = SmallVec::with_capacity(msg.bids.len());
71 let mut asks = SmallVec::with_capacity(msg.asks.len());
72
73 for bid in msg.bids {
75 if bid.len() >= 2 {
76 let price = bid[0].parse().unwrap_or(dec!(0));
77 let quantity = bid[1].parse().unwrap_or(dec!(0));
78
79 let insert_pos = match bids.binary_search_by(|existing: &(Decimal, Decimal)| {
82 existing.0.cmp(&price).reverse()
83 }) {
84 Ok(pos) => pos, Err(pos) => pos, };
87
88 bids.insert(insert_pos, (price, quantity));
89 }
90 }
91
92 for ask in msg.asks {
94 if ask.len() >= 2 {
95 let price = ask[0].parse().unwrap_or(dec!(0));
96 let quantity = ask[1].parse().unwrap_or(dec!(0));
97
98 let insert_pos = match asks
101 .binary_search_by(|existing: &(Decimal, Decimal)| existing.0.cmp(&price))
102 {
103 Ok(pos) => pos, Err(pos) => pos, };
106
107 asks.insert(insert_pos, (price, quantity));
108 }
109 }
110
111 ParsedOrderbookData {
112 symbol: msg.symbol,
113 first_update_id: msg.first_update_id,
114 final_update_id: msg.final_update_id,
115 event_time: msg.event_time,
116 bids,
117 asks,
118 }
119 }
120}
121
122#[derive(Debug, Clone, Serialize, Deserialize)]
124pub struct OrderbookSnapshot {
125 #[serde(rename = "lastUpdateId")]
127 pub last_update_id: u64,
128
129 pub bids: SmallVec<[SmallVec<[String; 2]>; 32]>,
131
132 pub asks: SmallVec<[SmallVec<[String; 2]>; 32]>,
134}
135
136#[derive(Debug, Clone)]
138#[repr(align(16))] pub struct ParsedOrderbookSnapshot {
140 pub last_update_id: u64,
142
143 pub bids: SmallVec<[(Decimal, Decimal); 32]>,
145
146 pub asks: SmallVec<[(Decimal, Decimal); 32]>,
148}
149
150impl From<OrderbookSnapshot> for ParsedOrderbookSnapshot {
151 fn from(snapshot: OrderbookSnapshot) -> Self {
152 let mut bids = SmallVec::with_capacity(snapshot.bids.len());
153 let mut asks = SmallVec::with_capacity(snapshot.asks.len());
154
155 for bid in snapshot.bids {
157 if bid.len() >= 2 {
158 let price = bid[0].parse().unwrap_or(dec!(0));
159 let quantity = bid[1].parse().unwrap_or(dec!(0));
160
161 let insert_pos = match bids.binary_search_by(|existing: &(Decimal, Decimal)| {
164 existing.0.cmp(&price).reverse()
165 }) {
166 Ok(pos) => pos, Err(pos) => pos, };
169
170 bids.insert(insert_pos, (price, quantity));
171 }
172 }
173
174 for ask in snapshot.asks {
176 if ask.len() >= 2 {
177 let price = ask[0].parse().unwrap_or(dec!(0));
178 let quantity = ask[1].parse().unwrap_or(dec!(0));
179
180 let insert_pos = match asks
183 .binary_search_by(|existing: &(Decimal, Decimal)| existing.0.cmp(&price))
184 {
185 Ok(pos) => pos, Err(pos) => pos, };
188
189 asks.insert(insert_pos, (price, quantity));
190 }
191 }
192
193 ParsedOrderbookSnapshot {
194 last_update_id: snapshot.last_update_id,
195 bids,
196 asks,
197 }
198 }
199}