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