rusty_feeder/exchange/binance/futures/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 = "T")]
26 pub transaction_time: u64,
27
28 #[serde(rename = "s")]
30 pub symbol: String,
31
32 #[serde(rename = "U")]
34 pub first_update_id: u64,
35
36 #[serde(rename = "u")]
38 pub final_update_id: u64,
39
40 #[serde(rename = "b")]
42 pub bids: SmallVec<[SmallVec<[String; 2]>; 32]>,
43
44 #[serde(rename = "a")]
46 pub asks: SmallVec<[SmallVec<[String; 2]>; 32]>,
47}
48
49#[derive(Debug, Clone)]
51#[repr(align(16))] pub struct ParsedOrderbookData {
53 pub symbol: String,
55
56 pub first_update_id: u64,
58
59 pub final_update_id: u64,
61
62 pub event_time: u64,
64
65 pub transaction_time: u64,
67
68 pub bids: SmallVec<[(Decimal, Decimal); 32]>,
70
71 pub asks: SmallVec<[(Decimal, Decimal); 32]>,
73}
74
75impl From<OrderbookMessage> for ParsedOrderbookData {
76 fn from(msg: OrderbookMessage) -> Self {
77 let mut bids = SmallVec::with_capacity(msg.bids.len());
78 let mut asks = SmallVec::with_capacity(msg.asks.len());
79
80 for bid in msg.bids {
82 if bid.len() >= 2 {
83 let price = bid[0].parse().unwrap_or(dec!(0));
84 let quantity = bid[1].parse().unwrap_or(dec!(0));
85
86 let insert_pos = match bids.binary_search_by(|existing: &(Decimal, Decimal)| {
89 existing.0.cmp(&price).reverse()
90 }) {
91 Ok(pos) => pos, Err(pos) => pos, };
94
95 bids.insert(insert_pos, (price, quantity));
96 }
97 }
98
99 for ask in msg.asks {
101 if ask.len() >= 2 {
102 let price = ask[0].parse().unwrap_or(dec!(0));
103 let quantity = ask[1].parse().unwrap_or(dec!(0));
104
105 let insert_pos = match asks
108 .binary_search_by(|existing: &(Decimal, Decimal)| existing.0.cmp(&price))
109 {
110 Ok(pos) => pos, Err(pos) => pos, };
113
114 asks.insert(insert_pos, (price, quantity));
115 }
116 }
117
118 ParsedOrderbookData {
119 symbol: msg.symbol,
120 first_update_id: msg.first_update_id,
121 final_update_id: msg.final_update_id,
122 event_time: msg.event_time,
123 transaction_time: msg.transaction_time,
124 bids,
125 asks,
126 }
127 }
128}
129
130#[derive(Debug, Clone, Serialize, Deserialize)]
132pub struct OrderbookSnapshot {
133 #[serde(rename = "lastUpdateId")]
135 pub last_update_id: u64,
136
137 #[serde(rename = "E")]
139 pub event_time: u64,
140
141 #[serde(rename = "T")]
143 pub transaction_time: u64,
144
145 pub bids: SmallVec<[SmallVec<[String; 2]>; 32]>,
147
148 pub asks: SmallVec<[SmallVec<[String; 2]>; 32]>,
150}
151
152#[derive(Debug, Clone)]
154#[repr(align(16))] pub struct ParsedOrderbookSnapshot {
156 pub last_update_id: u64,
158
159 pub event_time: u64,
161
162 pub transaction_time: u64,
164
165 pub bids: SmallVec<[(Decimal, Decimal); 32]>,
167
168 pub asks: SmallVec<[(Decimal, Decimal); 32]>,
170}
171
172impl From<OrderbookSnapshot> for ParsedOrderbookSnapshot {
173 fn from(snapshot: OrderbookSnapshot) -> Self {
174 let mut bids = SmallVec::with_capacity(snapshot.bids.len());
175 let mut asks = SmallVec::with_capacity(snapshot.asks.len());
176
177 for bid in snapshot.bids {
179 if bid.len() >= 2 {
180 let price = bid[0].parse().unwrap_or(dec!(0));
181 let quantity = bid[1].parse().unwrap_or(dec!(0));
182
183 let insert_pos = match bids.binary_search_by(|existing: &(Decimal, Decimal)| {
186 existing.0.cmp(&price).reverse()
187 }) {
188 Ok(pos) => pos, Err(pos) => pos, };
191
192 bids.insert(insert_pos, (price, quantity));
193 }
194 }
195
196 for ask in snapshot.asks {
198 if ask.len() >= 2 {
199 let price = ask[0].parse().unwrap_or(dec!(0));
200 let quantity = ask[1].parse().unwrap_or(dec!(0));
201
202 let insert_pos = match asks
205 .binary_search_by(|existing: &(Decimal, Decimal)| existing.0.cmp(&price))
206 {
207 Ok(pos) => pos, Err(pos) => pos, };
210
211 asks.insert(insert_pos, (price, quantity));
212 }
213 }
214
215 ParsedOrderbookSnapshot {
216 last_update_id: snapshot.last_update_id,
217 event_time: snapshot.event_time,
218 transaction_time: snapshot.transaction_time,
219 bids,
220 asks,
221 }
222 }
223}
224
225#[derive(Debug, Clone, Serialize, Deserialize)]
227#[repr(align(16))] pub struct MarkPriceMessage {
229 #[serde(rename = "e")]
231 pub event_type: String,
232
233 #[serde(rename = "E")]
235 pub event_time: u64,
236
237 #[serde(rename = "s")]
239 pub symbol: String,
240
241 #[serde(rename = "p")]
243 pub mark_price: String,
244
245 #[serde(rename = "i")]
247 pub index_price: String,
248
249 #[serde(rename = "r")]
251 pub funding_rate: String,
252
253 #[serde(rename = "T")]
255 pub next_funding_time: u64,
256}
257
258#[derive(Debug, Clone)]
260#[repr(align(16))] pub struct ParsedMarkPrice {
262 pub symbol: String,
264
265 pub mark_price: Decimal,
267
268 pub index_price: Decimal,
270
271 pub funding_rate: Decimal,
273
274 pub next_funding_time: u64,
276
277 pub event_time: u64,
279}
280
281impl From<MarkPriceMessage> for ParsedMarkPrice {
282 fn from(msg: MarkPriceMessage) -> Self {
283 ParsedMarkPrice {
284 symbol: msg.symbol,
285 mark_price: msg.mark_price.parse().unwrap_or(dec!(0)),
286 index_price: msg.index_price.parse().unwrap_or(dec!(0)),
287 funding_rate: msg.funding_rate.parse().unwrap_or(dec!(0)),
288 next_funding_time: msg.next_funding_time,
289 event_time: msg.event_time,
290 }
291 }
292}