1use std::{collections::HashMap, fmt::Display};
19
20use indexmap::IndexMap;
21use nautilus_core::{UnixNanos, serialization::Serializable};
22use serde::{Deserialize, Serialize};
23
24use super::{GetTsInit, order::BookOrder};
25use crate::{identifiers::InstrumentId, types::fixed::FIXED_SIZE_BINARY};
26
27pub const DEPTH10_LEN: usize = 10;
28
29#[repr(C)]
39#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
40#[cfg_attr(
41 feature = "python",
42 pyo3::pyclass(module = "nautilus_trader.core.nautilus_pyo3.model")
43)]
44pub struct OrderBookDepth10 {
45 pub instrument_id: InstrumentId,
47 pub bids: [BookOrder; DEPTH10_LEN],
49 pub asks: [BookOrder; DEPTH10_LEN],
51 pub bid_counts: [u32; DEPTH10_LEN],
53 pub ask_counts: [u32; DEPTH10_LEN],
55 pub flags: u8,
57 pub sequence: u64,
59 pub ts_event: UnixNanos,
61 pub ts_init: UnixNanos,
63}
64
65impl OrderBookDepth10 {
66 #[allow(clippy::too_many_arguments)]
68 #[must_use]
69 pub fn new(
70 instrument_id: InstrumentId,
71 bids: [BookOrder; DEPTH10_LEN],
72 asks: [BookOrder; DEPTH10_LEN],
73 bid_counts: [u32; DEPTH10_LEN],
74 ask_counts: [u32; DEPTH10_LEN],
75 flags: u8,
76 sequence: u64,
77 ts_event: UnixNanos,
78 ts_init: UnixNanos,
79 ) -> Self {
80 Self {
81 instrument_id,
82 bids,
83 asks,
84 bid_counts,
85 ask_counts,
86 flags,
87 sequence,
88 ts_event,
89 ts_init,
90 }
91 }
92
93 #[must_use]
95 pub fn get_metadata(
96 instrument_id: &InstrumentId,
97 price_precision: u8,
98 size_precision: u8,
99 ) -> HashMap<String, String> {
100 let mut metadata = HashMap::new();
101 metadata.insert("instrument_id".to_string(), instrument_id.to_string());
102 metadata.insert("price_precision".to_string(), price_precision.to_string());
103 metadata.insert("size_precision".to_string(), size_precision.to_string());
104 metadata
105 }
106
107 #[must_use]
109 pub fn get_fields() -> IndexMap<String, String> {
110 let mut metadata = IndexMap::new();
111 metadata.insert("bid_price_0".to_string(), FIXED_SIZE_BINARY.to_string());
112 metadata.insert("bid_price_1".to_string(), FIXED_SIZE_BINARY.to_string());
113 metadata.insert("bid_price_2".to_string(), FIXED_SIZE_BINARY.to_string());
114 metadata.insert("bid_price_3".to_string(), FIXED_SIZE_BINARY.to_string());
115 metadata.insert("bid_price_4".to_string(), FIXED_SIZE_BINARY.to_string());
116 metadata.insert("bid_price_5".to_string(), FIXED_SIZE_BINARY.to_string());
117 metadata.insert("bid_price_6".to_string(), FIXED_SIZE_BINARY.to_string());
118 metadata.insert("bid_price_7".to_string(), FIXED_SIZE_BINARY.to_string());
119 metadata.insert("bid_price_8".to_string(), FIXED_SIZE_BINARY.to_string());
120 metadata.insert("bid_price_9".to_string(), FIXED_SIZE_BINARY.to_string());
121 metadata.insert("ask_price_0".to_string(), FIXED_SIZE_BINARY.to_string());
122 metadata.insert("ask_price_1".to_string(), FIXED_SIZE_BINARY.to_string());
123 metadata.insert("ask_price_2".to_string(), FIXED_SIZE_BINARY.to_string());
124 metadata.insert("ask_price_3".to_string(), FIXED_SIZE_BINARY.to_string());
125 metadata.insert("ask_price_4".to_string(), FIXED_SIZE_BINARY.to_string());
126 metadata.insert("ask_price_5".to_string(), FIXED_SIZE_BINARY.to_string());
127 metadata.insert("ask_price_6".to_string(), FIXED_SIZE_BINARY.to_string());
128 metadata.insert("ask_price_7".to_string(), FIXED_SIZE_BINARY.to_string());
129 metadata.insert("ask_price_8".to_string(), FIXED_SIZE_BINARY.to_string());
130 metadata.insert("ask_price_9".to_string(), FIXED_SIZE_BINARY.to_string());
131 metadata.insert("bid_size_0".to_string(), FIXED_SIZE_BINARY.to_string());
132 metadata.insert("bid_size_1".to_string(), FIXED_SIZE_BINARY.to_string());
133 metadata.insert("bid_size_2".to_string(), FIXED_SIZE_BINARY.to_string());
134 metadata.insert("bid_size_3".to_string(), FIXED_SIZE_BINARY.to_string());
135 metadata.insert("bid_size_4".to_string(), FIXED_SIZE_BINARY.to_string());
136 metadata.insert("bid_size_5".to_string(), FIXED_SIZE_BINARY.to_string());
137 metadata.insert("bid_size_6".to_string(), FIXED_SIZE_BINARY.to_string());
138 metadata.insert("bid_size_7".to_string(), FIXED_SIZE_BINARY.to_string());
139 metadata.insert("bid_size_8".to_string(), FIXED_SIZE_BINARY.to_string());
140 metadata.insert("bid_size_9".to_string(), FIXED_SIZE_BINARY.to_string());
141 metadata.insert("ask_size_0".to_string(), FIXED_SIZE_BINARY.to_string());
142 metadata.insert("ask_size_1".to_string(), FIXED_SIZE_BINARY.to_string());
143 metadata.insert("ask_size_2".to_string(), FIXED_SIZE_BINARY.to_string());
144 metadata.insert("ask_size_3".to_string(), FIXED_SIZE_BINARY.to_string());
145 metadata.insert("ask_size_4".to_string(), FIXED_SIZE_BINARY.to_string());
146 metadata.insert("ask_size_5".to_string(), FIXED_SIZE_BINARY.to_string());
147 metadata.insert("ask_size_6".to_string(), FIXED_SIZE_BINARY.to_string());
148 metadata.insert("ask_size_7".to_string(), FIXED_SIZE_BINARY.to_string());
149 metadata.insert("ask_size_8".to_string(), FIXED_SIZE_BINARY.to_string());
150 metadata.insert("ask_size_9".to_string(), FIXED_SIZE_BINARY.to_string());
151 metadata.insert("bid_count_0".to_string(), "UInt32".to_string());
152 metadata.insert("bid_count_1".to_string(), "UInt32".to_string());
153 metadata.insert("bid_count_2".to_string(), "UInt32".to_string());
154 metadata.insert("bid_count_3".to_string(), "UInt32".to_string());
155 metadata.insert("bid_count_4".to_string(), "UInt32".to_string());
156 metadata.insert("bid_count_5".to_string(), "UInt32".to_string());
157 metadata.insert("bid_count_6".to_string(), "UInt32".to_string());
158 metadata.insert("bid_count_7".to_string(), "UInt32".to_string());
159 metadata.insert("bid_count_8".to_string(), "UInt32".to_string());
160 metadata.insert("bid_count_9".to_string(), "UInt32".to_string());
161 metadata.insert("ask_count_0".to_string(), "UInt32".to_string());
162 metadata.insert("ask_count_1".to_string(), "UInt32".to_string());
163 metadata.insert("ask_count_2".to_string(), "UInt32".to_string());
164 metadata.insert("ask_count_3".to_string(), "UInt32".to_string());
165 metadata.insert("ask_count_4".to_string(), "UInt32".to_string());
166 metadata.insert("ask_count_5".to_string(), "UInt32".to_string());
167 metadata.insert("ask_count_6".to_string(), "UInt32".to_string());
168 metadata.insert("ask_count_7".to_string(), "UInt32".to_string());
169 metadata.insert("ask_count_8".to_string(), "UInt32".to_string());
170 metadata.insert("ask_count_9".to_string(), "UInt32".to_string());
171 metadata.insert("flags".to_string(), "UInt8".to_string());
172 metadata.insert("sequence".to_string(), "UInt64".to_string());
173 metadata.insert("ts_event".to_string(), "UInt64".to_string());
174 metadata.insert("ts_init".to_string(), "UInt64".to_string());
175 metadata
176 }
177}
178
179impl Display for OrderBookDepth10 {
181 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
182 write!(
183 f,
184 "{},flags={},sequence={},ts_event={},ts_init={}",
185 self.instrument_id, self.flags, self.sequence, self.ts_event, self.ts_init
186 )
187 }
188}
189
190impl Serializable for OrderBookDepth10 {}
191
192impl GetTsInit for OrderBookDepth10 {
193 fn ts_init(&self) -> UnixNanos {
194 self.ts_init
195 }
196}
197
198#[cfg(test)]
202mod tests {
203 use rstest::rstest;
204
205 use super::*;
206 use crate::data::stubs::*;
207
208 #[rstest]
209 fn test_new(stub_depth10: OrderBookDepth10) {
210 let depth = stub_depth10;
211 let instrument_id = InstrumentId::from("AAPL.XNAS");
212 let flags = 0;
213 let sequence = 0;
214 let ts_event = 1;
215 let ts_init = 2;
216
217 assert_eq!(depth.instrument_id, instrument_id);
218 assert_eq!(depth.bids.len(), 10);
219 assert_eq!(depth.asks.len(), 10);
220 assert_eq!(depth.asks[9].price.as_f64(), 109.0);
221 assert_eq!(depth.asks[0].price.as_f64(), 100.0);
222 assert_eq!(depth.bids[0].price.as_f64(), 99.0);
223 assert_eq!(depth.bids[9].price.as_f64(), 90.0);
224 assert_eq!(depth.bid_counts.len(), 10);
225 assert_eq!(depth.ask_counts.len(), 10);
226 assert_eq!(depth.bid_counts[0], 1);
227 assert_eq!(depth.ask_counts[0], 1);
228 assert_eq!(depth.flags, flags);
229 assert_eq!(depth.sequence, sequence);
230 assert_eq!(depth.ts_event, ts_event);
231 assert_eq!(depth.ts_init, ts_init);
232 }
233
234 #[rstest]
236 fn test_display(stub_depth10: OrderBookDepth10) {
237 let depth = stub_depth10;
238 assert_eq!(
239 format!("{depth}"),
240 "AAPL.XNAS,flags=0,sequence=0,ts_event=1,ts_init=2".to_string()
241 );
242 }
243}