nautilus_model/python/data/
depth.rsuse std::{
collections::{hash_map::DefaultHasher, HashMap},
hash::{Hash, Hasher},
};
use nautilus_core::{
python::{serialization::from_dict_pyo3, to_pyvalue_err},
serialization::Serializable,
};
use pyo3::{prelude::*, pyclass::CompareOp, types::PyDict};
use super::data_to_pycapsule;
use crate::{
data::{
depth::{OrderBookDepth10, DEPTH10_LEN},
order::BookOrder,
Data,
},
enums::OrderSide,
identifiers::InstrumentId,
python::common::PY_MODULE_MODEL,
types::{price::Price, quantity::Quantity},
};
#[pymethods]
impl OrderBookDepth10 {
#[allow(clippy::too_many_arguments)]
#[new]
fn py_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: u64,
ts_init: u64,
) -> Self {
Self::new(
instrument_id,
bids,
asks,
bid_counts,
ask_counts,
flags,
sequence,
ts_event.into(),
ts_init.into(),
)
}
fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py<PyAny> {
match op {
CompareOp::Eq => self.eq(other).into_py(py),
CompareOp::Ne => self.ne(other).into_py(py),
_ => py.NotImplemented(),
}
}
fn __hash__(&self) -> isize {
let mut h = DefaultHasher::new();
self.hash(&mut h);
h.finish() as isize
}
fn __repr__(&self) -> String {
format!("{self:?}")
}
fn __str__(&self) -> String {
self.to_string()
}
#[getter]
#[pyo3(name = "instrument_id")]
fn py_instrument_id(&self) -> InstrumentId {
self.instrument_id
}
#[getter]
#[pyo3(name = "bids")]
fn py_bids(&self) -> [BookOrder; DEPTH10_LEN] {
self.bids
}
#[getter]
#[pyo3(name = "asks")]
fn py_asks(&self) -> [BookOrder; DEPTH10_LEN] {
self.asks
}
#[getter]
#[pyo3(name = "bid_counts")]
fn py_bid_counts(&self) -> [u32; DEPTH10_LEN] {
self.bid_counts
}
#[getter]
#[pyo3(name = "ask_counts")]
fn py_ask_counts(&self) -> [u32; DEPTH10_LEN] {
self.ask_counts
}
#[getter]
#[pyo3(name = "flags")]
fn py_flags(&self) -> u8 {
self.flags
}
#[getter]
#[pyo3(name = "sequence")]
fn py_sequence(&self) -> u64 {
self.sequence
}
#[getter]
#[pyo3(name = "ts_event")]
fn py_ts_event(&self) -> u64 {
self.ts_event.as_u64()
}
#[getter]
#[pyo3(name = "ts_init")]
fn py_ts_init(&self) -> u64 {
self.ts_init.as_u64()
}
#[staticmethod]
#[pyo3(name = "fully_qualified_name")]
fn py_fully_qualified_name() -> String {
format!("{}:{}", PY_MODULE_MODEL, stringify!(OrderBookDepth10))
}
#[staticmethod]
#[pyo3(name = "get_metadata")]
fn py_get_metadata(
instrument_id: &InstrumentId,
price_precision: u8,
size_precision: u8,
) -> PyResult<HashMap<String, String>> {
Ok(Self::get_metadata(
instrument_id,
price_precision,
size_precision,
))
}
#[staticmethod]
#[pyo3(name = "get_fields")]
fn py_get_fields(py: Python<'_>) -> PyResult<Bound<'_, PyDict>> {
let py_dict = PyDict::new_bound(py);
for (k, v) in Self::get_fields() {
py_dict.set_item(k, v)?;
}
Ok(py_dict)
}
#[staticmethod]
#[pyo3(name = "get_stub")]
fn py_get_stub() -> Self {
let instrument_id = InstrumentId::from("AAPL.XNAS");
let flags = 0;
let sequence = 0;
let ts_event = 1;
let ts_init = 2;
let mut bids: [BookOrder; DEPTH10_LEN] = [BookOrder::default(); DEPTH10_LEN];
let mut asks: [BookOrder; DEPTH10_LEN] = [BookOrder::default(); DEPTH10_LEN];
let mut price = 99.00;
let mut quantity = 100.0;
let mut order_id = 1;
for order in bids.iter_mut().take(DEPTH10_LEN) {
*order = BookOrder::new(
OrderSide::Buy,
Price::new(price, 2),
Quantity::new(quantity, 0),
order_id,
);
price -= 1.0;
quantity += 100.0;
order_id += 1;
}
let mut price = 100.00;
let mut quantity = 100.0;
let mut order_id = 11;
for order in asks.iter_mut().take(DEPTH10_LEN) {
*order = BookOrder::new(
OrderSide::Sell,
Price::new(price, 2),
Quantity::new(quantity, 0),
order_id,
);
price += 1.0;
quantity += 100.0;
order_id += 1;
}
let bid_counts: [u32; 10] = [1; 10];
let ask_counts: [u32; 10] = [1; 10];
Self::new(
instrument_id,
bids,
asks,
bid_counts,
ask_counts,
flags,
sequence,
ts_event.into(),
ts_init.into(),
)
}
#[staticmethod]
#[pyo3(name = "from_dict")]
fn py_from_dict(py: Python<'_>, values: Py<PyDict>) -> PyResult<Self> {
from_dict_pyo3(py, values)
}
#[staticmethod]
#[pyo3(name = "from_json")]
fn py_from_json(data: Vec<u8>) -> PyResult<Self> {
Self::from_json_bytes(&data).map_err(to_pyvalue_err)
}
#[staticmethod]
#[pyo3(name = "from_msgpack")]
fn py_from_msgpack(data: Vec<u8>) -> PyResult<Self> {
Self::from_msgpack_bytes(&data).map_err(to_pyvalue_err)
}
#[pyo3(name = "as_pycapsule")]
fn py_as_pycapsule(&self, py: Python<'_>) -> PyObject {
data_to_pycapsule(py, Data::Depth10(*self))
}
#[pyo3(name = "as_dict")]
fn py_as_dict(&self, py: Python<'_>) -> PyResult<Py<PyDict>> {
let json_str = serde_json::to_string(self).map_err(to_pyvalue_err)?;
let py_dict: Py<PyDict> = PyModule::import_bound(py, "json")?
.call_method("loads", (json_str,), None)?
.extract()?;
Ok(py_dict)
}
#[pyo3(name = "as_json")]
fn py_as_json(&self, py: Python<'_>) -> Py<PyAny> {
self.as_json_bytes().unwrap().into_py(py)
}
#[pyo3(name = "as_msgpack")]
fn py_as_msgpack(&self, py: Python<'_>) -> Py<PyAny> {
self.as_msgpack_bytes().unwrap().into_py(py)
}
}