use std::{
collections::HashMap,
fmt::{Display, Formatter},
};
use indexmap::IndexMap;
use nautilus_core::{nanos::UnixNanos, serialization::Serializable};
use serde::{Deserialize, Serialize};
use super::{order::BookOrder, GetTsInit};
use crate::identifiers::InstrumentId;
pub const DEPTH10_LEN: usize = 10;
#[repr(C)]
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[cfg_attr(
feature = "python",
pyo3::pyclass(module = "nautilus_trader.core.nautilus_pyo3.model")
)]
#[cfg_attr(feature = "trivial_copy", derive(Copy))]
pub struct OrderBookDepth10 {
pub instrument_id: InstrumentId,
pub bids: [BookOrder; DEPTH10_LEN],
pub asks: [BookOrder; DEPTH10_LEN],
pub bid_counts: [u32; DEPTH10_LEN],
pub ask_counts: [u32; DEPTH10_LEN],
pub flags: u8,
pub sequence: u64,
pub ts_event: UnixNanos,
pub ts_init: UnixNanos,
}
impl OrderBookDepth10 {
#[allow(clippy::too_many_arguments)]
#[must_use]
pub fn new(
instrument_id: InstrumentId,
bids: [BookOrder; DEPTH10_LEN],
asks: [BookOrder; DEPTH10_LEN],
bid_counts: [u32; DEPTH10_LEN],
ask_counts: [u32; DEPTH10_LEN],
flags: u8,
sequence: u64,
ts_event: UnixNanos,
ts_init: UnixNanos,
) -> Self {
Self {
instrument_id,
bids,
asks,
bid_counts,
ask_counts,
flags,
sequence,
ts_event,
ts_init,
}
}
#[must_use]
pub fn get_metadata(
instrument_id: &InstrumentId,
price_precision: u8,
size_precision: u8,
) -> HashMap<String, String> {
let mut metadata = HashMap::new();
metadata.insert("instrument_id".to_string(), instrument_id.to_string());
metadata.insert("price_precision".to_string(), price_precision.to_string());
metadata.insert("size_precision".to_string(), size_precision.to_string());
metadata
}
#[must_use]
pub fn get_fields() -> IndexMap<String, String> {
let mut metadata = IndexMap::new();
metadata.insert("bid_price_0".to_string(), "Int64".to_string());
metadata.insert("bid_price_1".to_string(), "Int64".to_string());
metadata.insert("bid_price_2".to_string(), "Int64".to_string());
metadata.insert("bid_price_3".to_string(), "Int64".to_string());
metadata.insert("bid_price_4".to_string(), "Int64".to_string());
metadata.insert("bid_price_5".to_string(), "Int64".to_string());
metadata.insert("bid_price_6".to_string(), "Int64".to_string());
metadata.insert("bid_price_7".to_string(), "Int64".to_string());
metadata.insert("bid_price_8".to_string(), "Int64".to_string());
metadata.insert("bid_price_9".to_string(), "Int64".to_string());
metadata.insert("ask_price_0".to_string(), "Int64".to_string());
metadata.insert("ask_price_1".to_string(), "Int64".to_string());
metadata.insert("ask_price_2".to_string(), "Int64".to_string());
metadata.insert("ask_price_3".to_string(), "Int64".to_string());
metadata.insert("ask_price_4".to_string(), "Int64".to_string());
metadata.insert("ask_price_5".to_string(), "Int64".to_string());
metadata.insert("ask_price_6".to_string(), "Int64".to_string());
metadata.insert("ask_price_7".to_string(), "Int64".to_string());
metadata.insert("ask_price_8".to_string(), "Int64".to_string());
metadata.insert("ask_price_9".to_string(), "Int64".to_string());
metadata.insert("bid_size_0".to_string(), "UInt64".to_string());
metadata.insert("bid_size_1".to_string(), "UInt64".to_string());
metadata.insert("bid_size_2".to_string(), "UInt64".to_string());
metadata.insert("bid_size_3".to_string(), "UInt64".to_string());
metadata.insert("bid_size_4".to_string(), "UInt64".to_string());
metadata.insert("bid_size_5".to_string(), "UInt64".to_string());
metadata.insert("bid_size_6".to_string(), "UInt64".to_string());
metadata.insert("bid_size_7".to_string(), "UInt64".to_string());
metadata.insert("bid_size_8".to_string(), "UInt64".to_string());
metadata.insert("bid_size_9".to_string(), "UInt64".to_string());
metadata.insert("ask_size_0".to_string(), "UInt64".to_string());
metadata.insert("ask_size_1".to_string(), "UInt64".to_string());
metadata.insert("ask_size_2".to_string(), "UInt64".to_string());
metadata.insert("ask_size_3".to_string(), "UInt64".to_string());
metadata.insert("ask_size_4".to_string(), "UInt64".to_string());
metadata.insert("ask_size_5".to_string(), "UInt64".to_string());
metadata.insert("ask_size_6".to_string(), "UInt64".to_string());
metadata.insert("ask_size_7".to_string(), "UInt64".to_string());
metadata.insert("ask_size_8".to_string(), "UInt64".to_string());
metadata.insert("ask_size_9".to_string(), "UInt64".to_string());
metadata.insert("bid_count_0".to_string(), "UInt32".to_string());
metadata.insert("bid_count_1".to_string(), "UInt32".to_string());
metadata.insert("bid_count_2".to_string(), "UInt32".to_string());
metadata.insert("bid_count_3".to_string(), "UInt32".to_string());
metadata.insert("bid_count_4".to_string(), "UInt32".to_string());
metadata.insert("bid_count_5".to_string(), "UInt32".to_string());
metadata.insert("bid_count_6".to_string(), "UInt32".to_string());
metadata.insert("bid_count_7".to_string(), "UInt32".to_string());
metadata.insert("bid_count_8".to_string(), "UInt32".to_string());
metadata.insert("bid_count_9".to_string(), "UInt32".to_string());
metadata.insert("ask_count_0".to_string(), "UInt32".to_string());
metadata.insert("ask_count_1".to_string(), "UInt32".to_string());
metadata.insert("ask_count_2".to_string(), "UInt32".to_string());
metadata.insert("ask_count_3".to_string(), "UInt32".to_string());
metadata.insert("ask_count_4".to_string(), "UInt32".to_string());
metadata.insert("ask_count_5".to_string(), "UInt32".to_string());
metadata.insert("ask_count_6".to_string(), "UInt32".to_string());
metadata.insert("ask_count_7".to_string(), "UInt32".to_string());
metadata.insert("ask_count_8".to_string(), "UInt32".to_string());
metadata.insert("ask_count_9".to_string(), "UInt32".to_string());
metadata.insert("flags".to_string(), "UInt8".to_string());
metadata.insert("sequence".to_string(), "UInt64".to_string());
metadata.insert("ts_event".to_string(), "UInt64".to_string());
metadata.insert("ts_init".to_string(), "UInt64".to_string());
metadata
}
}
impl Display for OrderBookDepth10 {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{},flags={},sequence={},ts_event={},ts_init={}",
self.instrument_id, self.flags, self.sequence, self.ts_event, self.ts_init
)
}
}
impl Serializable for OrderBookDepth10 {}
impl GetTsInit for OrderBookDepth10 {
fn ts_init(&self) -> UnixNanos {
self.ts_init
}
}
#[cfg(test)]
mod tests {
use rstest::rstest;
use super::*;
use crate::data::stubs::*;
#[rstest]
fn test_new(stub_depth10: OrderBookDepth10) {
let depth = stub_depth10;
let instrument_id = InstrumentId::from("AAPL.XNAS");
let flags = 0;
let sequence = 0;
let ts_event = 1;
let ts_init = 2;
assert_eq!(depth.instrument_id, instrument_id);
assert_eq!(depth.bids.len(), 10);
assert_eq!(depth.asks.len(), 10);
assert_eq!(depth.asks[9].price.as_f64(), 109.0);
assert_eq!(depth.asks[0].price.as_f64(), 100.0);
assert_eq!(depth.bids[0].price.as_f64(), 99.0);
assert_eq!(depth.bids[9].price.as_f64(), 90.0);
assert_eq!(depth.bid_counts.len(), 10);
assert_eq!(depth.ask_counts.len(), 10);
assert_eq!(depth.bid_counts[0], 1);
assert_eq!(depth.ask_counts[0], 1);
assert_eq!(depth.flags, flags);
assert_eq!(depth.sequence, sequence);
assert_eq!(depth.ts_event, ts_event);
assert_eq!(depth.ts_init, ts_init);
}
#[rstest]
fn test_display(stub_depth10: OrderBookDepth10) {
let depth = stub_depth10;
assert_eq!(
format!("{depth}"),
"AAPL.XNAS,flags=0,sequence=0,ts_event=1,ts_init=2".to_string()
);
}
}