nautilus_databento/python/
types.rs1use std::{
17 collections::hash_map::DefaultHasher,
18 hash::{Hash, Hasher},
19};
20
21use nautilus_core::python::{
22 IntoPyObjectNautilusExt,
23 serialization::{from_dict_pyo3, to_dict_pyo3},
24};
25use nautilus_model::{
26 enums::OrderSide,
27 identifiers::InstrumentId,
28 types::{Price, Quantity},
29};
30use pyo3::{basic::CompareOp, prelude::*, types::PyDict};
31
32use crate::{
33 enums::{DatabentoStatisticType, DatabentoStatisticUpdateAction},
34 types::{DatabentoImbalance, DatabentoStatistics},
35};
36
37#[pymethods]
38#[pyo3_stub_gen::derive::gen_stub_pymethods]
39impl DatabentoImbalance {
40 fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py<PyAny> {
41 match op {
42 CompareOp::Eq => self.eq(other).into_py_any_unwrap(py),
43 CompareOp::Ne => self.ne(other).into_py_any_unwrap(py),
44 _ => py.NotImplemented(),
45 }
46 }
47
48 fn __hash__(&self) -> isize {
49 let mut hasher = DefaultHasher::new();
50 self.hash(&mut hasher);
51 hasher.finish() as isize
52 }
53
54 fn __repr__(&self) -> String {
55 format!(
56 "{}(instrument_id={}, ref_price={}, cont_book_clr_price={}, auct_interest_clr_price={}, paired_qty={}, total_imbalance_qty={}, side={}, significant_imbalance={}, ts_event={}, ts_recv={}, ts_init={})",
57 stringify!(DatabentoImbalance),
58 self.instrument_id,
59 self.ref_price,
60 self.cont_book_clr_price,
61 self.auct_interest_clr_price,
62 self.paired_qty,
63 self.total_imbalance_qty,
64 self.side,
65 self.significant_imbalance,
66 self.ts_event,
67 self.ts_recv,
68 self.ts_init,
69 )
70 }
71
72 fn __str__(&self) -> String {
73 self.__repr__()
74 }
75
76 #[getter]
77 #[pyo3(name = "instrument_id")]
78 const fn py_instrument_id(&self) -> InstrumentId {
79 self.instrument_id
80 }
81
82 #[getter]
83 #[pyo3(name = "ref_price")]
84 const fn py_ref_price(&self) -> Price {
85 self.ref_price
86 }
87
88 #[getter]
89 #[pyo3(name = "cont_book_clr_price")]
90 const fn py_cont_book_clr_price(&self) -> Price {
91 self.cont_book_clr_price
92 }
93
94 #[getter]
95 #[pyo3(name = "auct_interest_clr_price")]
96 const fn py_auct_interest_clr_price(&self) -> Price {
97 self.auct_interest_clr_price
98 }
99
100 #[getter]
101 #[pyo3(name = "paired_qty")]
102 const fn py_paired_qty(&self) -> Quantity {
103 self.paired_qty
104 }
105
106 #[getter]
107 #[pyo3(name = "total_imbalance_qty")]
108 const fn py_total_imbalance_qty(&self) -> Quantity {
109 self.total_imbalance_qty
110 }
111
112 #[getter]
113 #[pyo3(name = "side")]
114 const fn py_side(&self) -> OrderSide {
115 self.side
116 }
117
118 #[getter]
119 #[pyo3(name = "significant_imbalance")]
120 fn py_significant_imbalance(&self) -> String {
121 self.significant_imbalance.to_string()
122 }
123
124 #[getter]
125 #[pyo3(name = "ts_event")]
126 const fn py_ts_event(&self) -> u64 {
127 self.ts_event.as_u64()
128 }
129
130 #[getter]
131 #[pyo3(name = "ts_recv")]
132 const fn py_ts_recv(&self) -> u64 {
133 self.ts_recv.as_u64()
134 }
135
136 #[getter]
137 #[pyo3(name = "ts_init")]
138 const fn py_ts_init(&self) -> u64 {
139 self.ts_init.as_u64()
140 }
141
142 #[staticmethod]
143 #[pyo3(name = "from_dict")]
144 fn py_from_dict(py: Python<'_>, values: Py<PyDict>) -> PyResult<Self> {
145 from_dict_pyo3(py, values)
146 }
147
148 #[pyo3(name = "to_dict")]
150 pub fn py_to_dict(&self, py: Python<'_>) -> PyResult<Py<PyDict>> {
151 to_dict_pyo3(py, self)
152 }
153}
154
155#[pymethods]
156#[pyo3_stub_gen::derive::gen_stub_pymethods]
157impl DatabentoStatistics {
158 fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py<PyAny> {
159 match op {
160 CompareOp::Eq => self.eq(other).into_py_any_unwrap(py),
161 CompareOp::Ne => self.ne(other).into_py_any_unwrap(py),
162 _ => py.NotImplemented(),
163 }
164 }
165
166 fn __hash__(&self) -> isize {
167 let mut hasher = DefaultHasher::new();
168 self.hash(&mut hasher);
169 hasher.finish() as isize
170 }
171
172 fn __repr__(&self) -> String {
173 format!(
174 "{}(instrument_id={}, stat_type={}, update_action={}, price={}, quantity={}, channel_id={}, stat_flags={}, sequence={}, ts_ref={}, ts_in_delta={}, ts_event={}, ts_recv={}, ts_init={})",
175 stringify!(DatabentoStatistics),
176 self.instrument_id,
177 self.stat_type,
178 self.update_action,
179 self.price
180 .map_or_else(|| "None".to_string(), |p| format!("{p}")),
181 self.quantity
182 .map_or_else(|| "None".to_string(), |q| format!("{q}")),
183 self.channel_id,
184 self.stat_flags,
185 self.sequence,
186 self.ts_ref,
187 self.ts_in_delta,
188 self.ts_event,
189 self.ts_recv,
190 self.ts_init,
191 )
192 }
193
194 fn __str__(&self) -> String {
195 self.__repr__()
196 }
197
198 #[getter]
199 #[pyo3(name = "instrument_id")]
200 const fn py_instrument_id(&self) -> InstrumentId {
201 self.instrument_id
202 }
203
204 #[getter]
205 #[pyo3(name = "stat_type")]
206 const fn py_stat_type(&self) -> DatabentoStatisticType {
207 self.stat_type
208 }
209
210 #[getter]
211 #[pyo3(name = "update_action")]
212 const fn py_update_action(&self) -> DatabentoStatisticUpdateAction {
213 self.update_action
214 }
215
216 #[getter]
217 #[pyo3(name = "price")]
218 const fn py_price(&self) -> Option<Price> {
219 self.price
220 }
221
222 #[getter]
223 #[pyo3(name = "quantity")]
224 const fn py_quantity(&self) -> Option<Quantity> {
225 self.quantity
226 }
227
228 #[getter]
229 #[pyo3(name = "channel_id")]
230 const fn py_channel_id(&self) -> u16 {
231 self.channel_id
232 }
233
234 #[getter]
235 #[pyo3(name = "stat_flags")]
236 const fn py_stat_flags(&self) -> u8 {
237 self.stat_flags
238 }
239
240 #[getter]
241 #[pyo3(name = "sequence")]
242 const fn py_sequence(&self) -> u32 {
243 self.sequence
244 }
245
246 #[getter]
247 #[pyo3(name = "ts_ref")]
248 const fn py_ts_ref(&self) -> u64 {
249 self.ts_ref.as_u64()
250 }
251
252 #[getter]
253 #[pyo3(name = "ts_in_delta")]
254 const fn py_ts_in_delta(&self) -> i32 {
255 self.ts_in_delta
256 }
257
258 #[getter]
259 #[pyo3(name = "ts_event")]
260 const fn py_ts_event(&self) -> u64 {
261 self.ts_event.as_u64()
262 }
263
264 #[pyo3(name = "ts_recv")]
265 #[getter]
266 const fn py_ts_recv(&self) -> u64 {
267 self.ts_recv.as_u64()
268 }
269
270 #[pyo3(name = "ts_init")]
271 #[getter]
272 const fn py_ts_init(&self) -> u64 {
273 self.ts_init.as_u64()
274 }
275
276 #[staticmethod]
277 #[pyo3(name = "from_dict")]
278 fn py_from_dict(py: Python<'_>, values: Py<PyDict>) -> PyResult<Self> {
279 from_dict_pyo3(py, values)
280 }
281
282 #[pyo3(name = "to_dict")]
284 pub fn py_to_dict(&self, py: Python<'_>) -> PyResult<Py<PyDict>> {
285 to_dict_pyo3(py, self)
286 }
287}
288
289#[cfg_attr(
291 feature = "python",
292 pyo3::pyclass(
293 module = "nautilus_trader.core.nautilus_pyo3.databento",
294 from_py_object
295 )
296)]
297#[cfg_attr(
298 feature = "python",
299 pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.adapters.databento")
300)]
301#[derive(Debug, Clone)]
302pub struct DatabentoSubscriptionAck {
303 #[pyo3(get)]
304 pub schema: String,
305 #[pyo3(get)]
306 pub message: String,
307 #[pyo3(get)]
308 pub ts_received: u64,
309}
310
311impl From<crate::types::SubscriptionAckEvent> for DatabentoSubscriptionAck {
312 fn from(event: crate::types::SubscriptionAckEvent) -> Self {
313 Self {
314 schema: event.schema,
315 message: event.message,
316 ts_received: event.ts_received.as_u64(),
317 }
318 }
319}