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