diff --git a/nautilus_core/model/src/data/deltas.rs b/nautilus_core/model/src/data/deltas.rs index 1d8bdd0e4aee..b7ed835dab7a 100644 --- a/nautilus_core/model/src/data/deltas.rs +++ b/nautilus_core/model/src/data/deltas.rs @@ -13,7 +13,10 @@ // limitations under the License. // ------------------------------------------------------------------------------------------------- -use std::fmt::{Display, Formatter}; +use std::{ + fmt::{Display, Formatter}, + hash::{Hash, Hasher}, +}; use nautilus_core::time::UnixNanos; use pyo3::prelude::*; @@ -66,6 +69,21 @@ impl OrderBookDeltas { } } +impl PartialEq for OrderBookDeltas { + fn eq(&self, other: &Self) -> bool { + self.instrument_id == other.instrument_id && self.sequence == other.sequence + } +} + +impl Eq for OrderBookDeltas {} + +impl Hash for OrderBookDeltas { + fn hash(&self, state: &mut H) { + self.instrument_id.hash(state); + self.sequence.hash(state); + } +} + // TODO: Implement // impl Serializable for OrderBookDeltas {} diff --git a/nautilus_core/model/src/data/mod.rs b/nautilus_core/model/src/data/mod.rs index e354fb78e182..e4f256330aae 100644 --- a/nautilus_core/model/src/data/mod.rs +++ b/nautilus_core/model/src/data/mod.rs @@ -23,6 +23,8 @@ pub mod trade; use nautilus_core::time::UnixNanos; +use crate::ffi::data::deltas::OrderBookDeltas_API; + use self::{ bar::Bar, delta::OrderBookDelta, deltas::OrderBookDeltas, depth::OrderBookDepth10, quote::QuoteTick, trade::TradeTick, @@ -33,6 +35,7 @@ use self::{ #[allow(clippy::large_enum_variant)] // TODO: Optimize this (largest variant 1008 vs 136 bytes) pub enum Data { Delta(OrderBookDelta), + Deltas(OrderBookDeltas_API), Depth10(OrderBookDepth10), Quote(QuoteTick), Trade(TradeTick), @@ -47,6 +50,7 @@ impl HasTsInit for Data { fn get_ts_init(&self) -> UnixNanos { match self { Data::Delta(d) => d.ts_init, + Data::Deltas(d) => d.ts_init, Data::Depth10(d) => d.ts_init, Data::Quote(q) => q.ts_init, Data::Trade(t) => t.ts_init, @@ -61,13 +65,13 @@ impl HasTsInit for OrderBookDelta { } } -impl HasTsInit for OrderBookDepth10 { +impl HasTsInit for OrderBookDeltas { fn get_ts_init(&self) -> UnixNanos { self.ts_init } } -impl HasTsInit for OrderBookDeltas { +impl HasTsInit for OrderBookDepth10 { fn get_ts_init(&self) -> UnixNanos { self.ts_init } @@ -102,6 +106,12 @@ impl From for Data { } } +impl From for Data { + fn from(value: OrderBookDeltas_API) -> Self { + Self::Deltas(value) + } +} + impl From for Data { fn from(value: OrderBookDepth10) -> Self { Self::Depth10(value) diff --git a/nautilus_core/model/src/ffi/data/deltas.rs b/nautilus_core/model/src/ffi/data/deltas.rs index f52632de71e2..69cfb237453d 100644 --- a/nautilus_core/model/src/ffi/data/deltas.rs +++ b/nautilus_core/model/src/ffi/data/deltas.rs @@ -32,6 +32,7 @@ use crate::{ /// dereferenced to `OrderBookDeltas`, providing access to `OrderBookDeltas`'s methods without /// having to manually access the underlying `OrderBookDeltas` instance. #[repr(C)] +#[derive(Debug, Clone)] #[allow(non_camel_case_types)] pub struct OrderBookDeltas_API(Box); diff --git a/nautilus_core/model/src/python/data/deltas.rs b/nautilus_core/model/src/python/data/deltas.rs index fcd7b8acfb81..290f34568bc9 100644 --- a/nautilus_core/model/src/python/data/deltas.rs +++ b/nautilus_core/model/src/python/data/deltas.rs @@ -13,13 +13,10 @@ // limitations under the License. // ------------------------------------------------------------------------------------------------- -// use std::{ -// collections::{hash_map::DefaultHasher, HashMap}, -// hash::{Hash, Hasher}, -// }; +use std::hash::{DefaultHasher, Hash, Hasher}; use nautilus_core::time::UnixNanos; -use pyo3::prelude::*; +use pyo3::{prelude::*, pyclass::CompareOp}; use crate::{ data::{delta::OrderBookDelta, deltas::OrderBookDeltas}, @@ -34,21 +31,19 @@ impl OrderBookDeltas { Self::new(instrument_id, deltas) } - // TODO: Implement - // fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py { - // match op { - // CompareOp::Eq => self.eq(other).into_py(py), - // CompareOp::Ne => self.ne(other).into_py(py), - // _ => py.NotImplemented(), - // } - // } + fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py { + match op { + CompareOp::Eq => self.eq(other).into_py(py), + CompareOp::Ne => self.ne(other).into_py(py), + _ => py.NotImplemented(), + } + } - // TODO: Implement - // fn __hash__(&self) -> isize { - // let mut h = DefaultHasher::new(); - // self.hash(&mut h); - // h.finish() as isize - // } + fn __hash__(&self) -> isize { + let mut h = DefaultHasher::new(); + self.hash(&mut h); + h.finish() as isize + } fn __str__(&self) -> String { self.to_string() diff --git a/nautilus_trader/core/includes/model.h b/nautilus_trader/core/includes/model.h index 3b9172b2f8a5..c95d3b273fc2 100644 --- a/nautilus_trader/core/includes/model.h +++ b/nautilus_trader/core/includes/model.h @@ -780,6 +780,20 @@ typedef struct OrderBookDelta_t { uint64_t ts_init; } OrderBookDelta_t; +/** + * Provides a C compatible Foreign Function Interface (FFI) for an underlying [`OrderBookDeltas`]. + * + * This struct wraps `OrderBookDeltas` in a way that makes it compatible with C function + * calls, enabling interaction with `OrderBookDeltas` in a C environment. + * + * It implements the `Deref` trait, allowing instances of `OrderBookDeltas_API` to be + * dereferenced to `OrderBookDeltas`, providing access to `OrderBookDeltas`'s methods without + * having to manually access the underlying `OrderBookDeltas` instance. + */ +typedef struct OrderBookDeltas_API { + struct OrderBookDeltas_t *_0; +} OrderBookDeltas_API; + /** * Represents a self-contained order book update with a fixed depth of 10 levels per side. * @@ -991,6 +1005,7 @@ typedef struct Bar_t { typedef enum Data_t_Tag { DELTA, + DELTAS, DEPTH10, QUOTE, TRADE, @@ -1003,6 +1018,9 @@ typedef struct Data_t { struct { struct OrderBookDelta_t delta; }; + struct { + struct OrderBookDeltas_API deltas; + }; struct { struct OrderBookDepth10_t depth10; }; @@ -1018,20 +1036,6 @@ typedef struct Data_t { }; } Data_t; -/** - * Provides a C compatible Foreign Function Interface (FFI) for an underlying [`OrderBookDeltas`]. - * - * This struct wraps `OrderBookDeltas` in a way that makes it compatible with C function - * calls, enabling interaction with `OrderBookDeltas` in a C environment. - * - * It implements the `Deref` trait, allowing instances of `OrderBookDeltas_API` to be - * dereferenced to `OrderBookDeltas`, providing access to `OrderBookDeltas`'s methods without - * having to manually access the underlying `OrderBookDeltas` instance. - */ -typedef struct OrderBookDeltas_API { - struct OrderBookDeltas_t *_0; -} OrderBookDeltas_API; - /** * Represents a valid trader ID. * diff --git a/nautilus_trader/core/nautilus_pyo3.pyi b/nautilus_trader/core/nautilus_pyo3.pyi index e405dad95404..832101da0f15 100644 --- a/nautilus_trader/core/nautilus_pyo3.pyi +++ b/nautilus_trader/core/nautilus_pyo3.pyi @@ -496,6 +496,25 @@ class OrderBookDelta: @staticmethod def get_fields() -> dict[str, str]: ... +class OrderBookDeltas: + def __init__( + self, + instrument_id: InstrumentId, + deltas: list[OrderBookDelta], + ) -> None: ... + @property + def instrument_id(self) -> InstrumentId: ... + @property + def deltas(self) -> list[OrderBookDelta]: ... + @property + def flags(self) -> int: ... + @property + def sequence(self) -> int: ... + @property + def ts_event(self) -> int: ... + @property + def ts_init(self) -> int: ... + class OrderBookDepth10: def __init__( self, diff --git a/nautilus_trader/core/rust/model.pxd b/nautilus_trader/core/rust/model.pxd index 165a60ed703a..a0ad361f5784 100644 --- a/nautilus_trader/core/rust/model.pxd +++ b/nautilus_trader/core/rust/model.pxd @@ -425,6 +425,17 @@ cdef extern from "../includes/model.h": # The UNIX timestamp (nanoseconds) when the data object was initialized. uint64_t ts_init; + # Provides a C compatible Foreign Function Interface (FFI) for an underlying [`OrderBookDeltas`]. + # + # This struct wraps `OrderBookDeltas` in a way that makes it compatible with C function + # calls, enabling interaction with `OrderBookDeltas` in a C environment. + # + # It implements the `Deref` trait, allowing instances of `OrderBookDeltas_API` to be + # dereferenced to `OrderBookDeltas`, providing access to `OrderBookDeltas`'s methods without + # having to manually access the underlying `OrderBookDeltas` instance. + cdef struct OrderBookDeltas_API: + OrderBookDeltas_t *_0; + # Represents a self-contained order book update with a fixed depth of 10 levels per side. # # This struct is specifically designed for scenarios where a snapshot of the top 10 bid and @@ -539,6 +550,7 @@ cdef extern from "../includes/model.h": cpdef enum Data_t_Tag: DELTA, + DELTAS, DEPTH10, QUOTE, TRADE, @@ -547,22 +559,12 @@ cdef extern from "../includes/model.h": cdef struct Data_t: Data_t_Tag tag; OrderBookDelta_t delta; + OrderBookDeltas_API deltas; OrderBookDepth10_t depth10; QuoteTick_t quote; TradeTick_t trade; Bar_t bar; - # Provides a C compatible Foreign Function Interface (FFI) for an underlying [`OrderBookDeltas`]. - # - # This struct wraps `OrderBookDeltas` in a way that makes it compatible with C function - # calls, enabling interaction with `OrderBookDeltas` in a C environment. - # - # It implements the `Deref` trait, allowing instances of `OrderBookDeltas_API` to be - # dereferenced to `OrderBookDeltas`, providing access to `OrderBookDeltas`'s methods without - # having to manually access the underlying `OrderBookDeltas` instance. - cdef struct OrderBookDeltas_API: - OrderBookDeltas_t *_0; - # Represents a valid trader ID. # # Must be correctly formatted with two valid strings either side of a hyphen. diff --git a/nautilus_trader/model/data.pyx b/nautilus_trader/model/data.pyx index 084a37cafe75..b76d9c4c87fa 100644 --- a/nautilus_trader/model/data.pyx +++ b/nautilus_trader/model/data.pyx @@ -2243,7 +2243,7 @@ cdef class OrderBookDeltas(Data): @property def flags(self) -> uint8_t: """ - Return the flags for the delta. + Return the flags for the last delta. Returns ------- @@ -2255,7 +2255,7 @@ cdef class OrderBookDeltas(Data): @property def sequence(self) -> uint64_t: """ - Return the sequence number for the delta. + Return the sequence number for the last delta. Returns -------