nautilus_serialization/sbe/market/
book.rs1use nautilus_model::{
17 data::{BookOrder, OrderBookDelta, OrderBookDeltas, OrderBookDepth},
18 enums::OrderSide,
19};
20
21use super::{
22 super::{SbeCursor, SbeDecodeError, SbeEncodeError, SbeWriter},
23 FromSbeReuse, MarketSbeMessage,
24 common::{
25 BOOK_ORDER_BLOCK_LENGTH, DEPTH10_COUNTS_BLOCK_LENGTH, DEPTH10_LEVEL_BLOCK_LENGTH,
26 DEPTH10_LEVEL_COUNT, GROUP_HEADER_16_LENGTH, ORDER_BOOK_DELTA_GROUP_BLOCK_LENGTH,
27 decode_book_action, decode_header, decode_instrument_id, decode_order_side, decode_price,
28 decode_quantity, decode_unix_nanos, encode_group_header_16, encode_instrument_id,
29 encode_price, encode_quantity, encode_unix_nanos, encoded_instrument_id_size,
30 validate_header,
31 },
32 template_id,
33};
34
35impl MarketSbeMessage for BookOrder {
36 const TEMPLATE_ID: u16 = template_id::BOOK_ORDER;
37 const BLOCK_LENGTH: u16 = BOOK_ORDER_BLOCK_LENGTH;
38
39 fn encode_body(&self, writer: &mut SbeWriter<'_>) -> Result<(), SbeEncodeError> {
40 encode_book_order(writer, self);
41 Ok(())
42 }
43
44 fn decode_body(cursor: &mut SbeCursor<'_>) -> Result<Self, SbeDecodeError> {
45 decode_book_order(cursor)
46 }
47}
48
49impl MarketSbeMessage for OrderBookDelta {
50 const TEMPLATE_ID: u16 = template_id::ORDER_BOOK_DELTA;
51 const BLOCK_LENGTH: u16 = ORDER_BOOK_DELTA_GROUP_BLOCK_LENGTH;
52
53 fn encode_body(&self, writer: &mut SbeWriter<'_>) -> Result<(), SbeEncodeError> {
54 encode_order_book_delta_fields(writer, self);
55 encode_instrument_id(writer, &self.instrument_id)
56 }
57
58 fn decode_body(cursor: &mut SbeCursor<'_>) -> Result<Self, SbeDecodeError> {
59 let action = decode_book_action(cursor)?;
60 let order = decode_book_order(cursor)?;
61 let flags = cursor.read_u8()?;
62 let sequence = cursor.read_u64_le()?;
63 let ts_event = decode_unix_nanos(cursor)?;
64 let ts_init = decode_unix_nanos(cursor)?;
65 let instrument_id = decode_instrument_id(cursor)?;
66
67 Ok(Self {
68 instrument_id,
69 action,
70 order,
71 flags,
72 sequence,
73 ts_event,
74 ts_init,
75 })
76 }
77
78 fn encoded_body_size(&self) -> usize {
79 usize::from(Self::BLOCK_LENGTH) + encoded_instrument_id_size(&self.instrument_id)
80 }
81}
82
83impl MarketSbeMessage for OrderBookDeltas {
84 const TEMPLATE_ID: u16 = template_id::ORDER_BOOK_DELTAS;
85 const BLOCK_LENGTH: u16 = 25;
86
87 fn encode_body(&self, writer: &mut SbeWriter<'_>) -> Result<(), SbeEncodeError> {
88 writer.write_u8(self.flags);
89 writer.write_u64_le(self.sequence);
90 encode_unix_nanos(writer, self.ts_event);
91 encode_unix_nanos(writer, self.ts_init);
92 encode_instrument_id(writer, &self.instrument_id)?;
93 encode_group_header_16(
94 writer,
95 "OrderBookDeltas.deltas",
96 self.deltas.len(),
97 ORDER_BOOK_DELTA_GROUP_BLOCK_LENGTH,
98 )?;
99
100 for delta in &self.deltas {
101 <OrderBookDelta as MarketSbeMessage>::encode_body(delta, writer)?;
102 }
103 Ok(())
104 }
105
106 fn decode_body(cursor: &mut SbeCursor<'_>) -> Result<Self, SbeDecodeError> {
107 let mut scratch = Vec::new();
108 decode_order_book_deltas_body(cursor, &mut scratch)
109 }
110
111 fn encoded_body_size(&self) -> usize {
112 usize::from(Self::BLOCK_LENGTH)
113 + encoded_instrument_id_size(&self.instrument_id)
114 + GROUP_HEADER_16_LENGTH
115 + self
116 .deltas
117 .iter()
118 .map(MarketSbeMessage::encoded_body_size)
119 .sum::<usize>()
120 }
121}
122
123impl FromSbeReuse for OrderBookDeltas {
124 type Scratch = Vec<OrderBookDelta>;
125
126 fn from_sbe_reuse(
127 bytes: &[u8],
128 scratch: &mut Vec<OrderBookDelta>,
129 ) -> Result<Self, SbeDecodeError> {
130 let mut cursor = SbeCursor::new(bytes);
131 let header = decode_header(&mut cursor)?;
132 validate_header(
133 header,
134 <Self as MarketSbeMessage>::TEMPLATE_ID,
135 <Self as MarketSbeMessage>::BLOCK_LENGTH,
136 )?;
137 decode_order_book_deltas_body(&mut cursor, scratch)
138 }
139}
140
141fn decode_order_book_deltas_body(
142 cursor: &mut SbeCursor<'_>,
143 scratch: &mut Vec<OrderBookDelta>,
144) -> Result<OrderBookDeltas, SbeDecodeError> {
145 let flags = cursor.read_u8()?;
146 let sequence = cursor.read_u64_le()?;
147 let ts_event = decode_unix_nanos(cursor)?;
148 let ts_init = decode_unix_nanos(cursor)?;
149 let instrument_id = decode_instrument_id(cursor)?;
150 let (block_length, count) = cursor.read_group_header_16()?;
151
152 if block_length != ORDER_BOOK_DELTA_GROUP_BLOCK_LENGTH {
153 return Err(SbeDecodeError::InvalidBlockLength {
154 expected: ORDER_BOOK_DELTA_GROUP_BLOCK_LENGTH,
155 actual: block_length,
156 });
157 }
158
159 let count = usize::from(count);
160 scratch.clear();
161 scratch.reserve(count);
162
163 for _ in 0..count {
164 scratch.push(<OrderBookDelta as MarketSbeMessage>::decode_body(cursor)?);
165 }
166
167 Ok(OrderBookDeltas {
168 instrument_id,
169 deltas: std::mem::take(scratch),
170 flags,
171 sequence,
172 ts_event,
173 ts_init,
174 })
175}
176
177impl MarketSbeMessage for OrderBookDepth {
178 const TEMPLATE_ID: u16 = template_id::ORDER_BOOK_DEPTH;
179 const BLOCK_LENGTH: u16 =
180 (DEPTH10_LEVEL_BLOCK_LENGTH * 20) + (DEPTH10_COUNTS_BLOCK_LENGTH as u16 * 2) + 25;
181
182 fn encode_body(&self, writer: &mut SbeWriter<'_>) -> Result<(), SbeEncodeError> {
183 for (group, count) in [
184 ("bids", self.bids.len()),
185 ("asks", self.asks.len()),
186 ("bid_counts", self.bid_counts.len()),
187 ("ask_counts", self.ask_counts.len()),
188 ] {
189 if count != DEPTH10_LEVEL_COUNT {
190 return Err(SbeEncodeError::InvalidGroupSize {
191 group,
192 count,
193 expected: DEPTH10_LEVEL_COUNT,
194 });
195 }
196 }
197
198 for bid in &self.bids {
199 encode_price(writer, &bid.price);
200 encode_quantity(writer, &bid.size);
201 }
202
203 for ask in &self.asks {
204 encode_price(writer, &ask.price);
205 encode_quantity(writer, &ask.size);
206 }
207
208 for count in &self.bid_counts {
209 writer.write_u32_le(*count);
210 }
211
212 for count in &self.ask_counts {
213 writer.write_u32_le(*count);
214 }
215 writer.write_u8(self.flags);
216 writer.write_u64_le(self.sequence);
217 encode_unix_nanos(writer, self.ts_event);
218 encode_unix_nanos(writer, self.ts_init);
219 encode_instrument_id(writer, &self.instrument_id)
220 }
221
222 fn decode_body(cursor: &mut SbeCursor<'_>) -> Result<Self, SbeDecodeError> {
223 let mut bids = [BookOrder::default(); DEPTH10_LEVEL_COUNT];
224 let mut asks = [BookOrder::default(); DEPTH10_LEVEL_COUNT];
225
226 for bid in &mut bids {
227 *bid = BookOrder::new(
228 OrderSide::Buy,
229 decode_price(cursor)?,
230 decode_quantity(cursor)?,
231 0,
232 );
233 }
234
235 for ask in &mut asks {
236 *ask = BookOrder::new(
237 OrderSide::Sell,
238 decode_price(cursor)?,
239 decode_quantity(cursor)?,
240 0,
241 );
242 }
243
244 let mut bid_counts = [0u32; DEPTH10_LEVEL_COUNT];
245 let mut ask_counts = [0u32; DEPTH10_LEVEL_COUNT];
246
247 for count in &mut bid_counts {
248 *count = cursor.read_u32_le()?;
249 }
250
251 for count in &mut ask_counts {
252 *count = cursor.read_u32_le()?;
253 }
254
255 let flags = cursor.read_u8()?;
256 let sequence = cursor.read_u64_le()?;
257 let ts_event = decode_unix_nanos(cursor)?;
258 let ts_init = decode_unix_nanos(cursor)?;
259 let instrument_id = decode_instrument_id(cursor)?;
260
261 Ok(Self {
262 instrument_id,
263 bids: bids.into(),
264 asks: asks.into(),
265 bid_counts: bid_counts.into(),
266 ask_counts: ask_counts.into(),
267 flags,
268 sequence,
269 ts_event,
270 ts_init,
271 })
272 }
273
274 fn encoded_body_size(&self) -> usize {
275 usize::from(Self::BLOCK_LENGTH) + encoded_instrument_id_size(&self.instrument_id)
276 }
277}
278
279fn encode_book_order(writer: &mut SbeWriter<'_>, order: &BookOrder) {
280 encode_price(writer, &order.price);
281 encode_quantity(writer, &order.size);
282 writer.write_u8(order.side.map_or(0, |side| side as u8));
283 writer.write_u64_le(order.order_id);
284}
285
286fn decode_book_order(cursor: &mut SbeCursor<'_>) -> Result<BookOrder, SbeDecodeError> {
287 let price = decode_price(cursor)?;
288 let size = decode_quantity(cursor)?;
289 let side = decode_order_side(cursor)?;
290 let order_id = cursor.read_u64_le()?;
291 Ok(BookOrder {
292 side,
293 price,
294 size,
295 order_id,
296 })
297}
298
299fn encode_order_book_delta_fields(writer: &mut SbeWriter<'_>, delta: &OrderBookDelta) {
300 writer.write_u8(delta.action as u8);
301 encode_book_order(writer, &delta.order);
302 writer.write_u8(delta.flags);
303 writer.write_u64_le(delta.sequence);
304 encode_unix_nanos(writer, delta.ts_event);
305 encode_unix_nanos(writer, delta.ts_init);
306}