nautilus_binance/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 data::bar::BarType,
24 identifiers::InstrumentId,
25 types::{Price, Quantity},
26};
27use pyo3::{
28 IntoPyObjectExt,
29 basic::CompareOp,
30 prelude::*,
31 types::{PyDict, PyList},
32};
33use rust_decimal::Decimal;
34
35use crate::{
36 common::bar::BinanceBar,
37 data_types::{
38 BinanceFuturesMarkPriceUpdate, BinanceFuturesOpenInterestHist,
39 BinanceFuturesOpenInterestHistPoint, BinanceSpotTicker,
40 },
41};
42
43#[pymethods]
44#[pyo3_stub_gen::derive::gen_stub_pymethods]
45impl BinanceBar {
46 fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py<PyAny> {
47 match op {
48 CompareOp::Eq => self.eq(other).into_py_any_unwrap(py),
49 CompareOp::Ne => self.ne(other).into_py_any_unwrap(py),
50 _ => py.NotImplemented(),
51 }
52 }
53
54 fn __hash__(&self) -> isize {
55 let mut hasher = DefaultHasher::new();
56 self.bar_type.hash(&mut hasher);
57 self.ts_event.hash(&mut hasher);
58 hasher.finish() as isize
59 }
60
61 fn __repr__(&self) -> String {
62 format!(
63 "{}(bar_type={}, open={}, high={}, low={}, close={}, volume={}, quote_volume={}, count={}, taker_buy_base_volume={}, taker_buy_quote_volume={}, ts_event={}, ts_init={})",
64 stringify!(BinanceBar),
65 self.bar_type,
66 self.open,
67 self.high,
68 self.low,
69 self.close,
70 self.volume,
71 self.quote_volume,
72 self.count,
73 self.taker_buy_base_volume,
74 self.taker_buy_quote_volume,
75 self.ts_event,
76 self.ts_init,
77 )
78 }
79
80 fn __str__(&self) -> String {
81 self.__repr__()
82 }
83
84 #[getter]
85 #[pyo3(name = "bar_type")]
86 fn py_bar_type(&self) -> BarType {
87 self.bar_type
88 }
89
90 #[getter]
91 #[pyo3(name = "open")]
92 const fn py_open(&self) -> Price {
93 self.open
94 }
95
96 #[getter]
97 #[pyo3(name = "high")]
98 const fn py_high(&self) -> Price {
99 self.high
100 }
101
102 #[getter]
103 #[pyo3(name = "low")]
104 const fn py_low(&self) -> Price {
105 self.low
106 }
107
108 #[getter]
109 #[pyo3(name = "close")]
110 const fn py_close(&self) -> Price {
111 self.close
112 }
113
114 #[getter]
115 #[pyo3(name = "volume")]
116 const fn py_volume(&self) -> Quantity {
117 self.volume
118 }
119
120 #[getter]
121 #[pyo3(name = "quote_volume")]
122 fn py_quote_volume(&self) -> Decimal {
123 self.quote_volume
124 }
125
126 #[getter]
127 #[pyo3(name = "count")]
128 const fn py_count(&self) -> u64 {
129 self.count
130 }
131
132 #[getter]
133 #[pyo3(name = "taker_buy_base_volume")]
134 fn py_taker_buy_base_volume(&self) -> Decimal {
135 self.taker_buy_base_volume
136 }
137
138 #[getter]
139 #[pyo3(name = "taker_buy_quote_volume")]
140 fn py_taker_buy_quote_volume(&self) -> Decimal {
141 self.taker_buy_quote_volume
142 }
143
144 #[getter]
145 #[pyo3(name = "ts_event")]
146 const fn py_ts_event(&self) -> u64 {
147 self.ts_event.as_u64()
148 }
149
150 #[getter]
151 #[pyo3(name = "ts_init")]
152 const fn py_ts_init(&self) -> u64 {
153 self.ts_init.as_u64()
154 }
155
156 #[staticmethod]
157 #[pyo3(name = "from_dict")]
158 fn py_from_dict(py: Python<'_>, values: Py<PyDict>) -> PyResult<Self> {
159 from_dict_pyo3(py, values)
160 }
161
162 #[pyo3(name = "to_dict")]
166 pub fn py_to_dict(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
167 let dict = PyDict::new(py);
168 dict.set_item("type", stringify!(BinanceBar))?;
169 dict.set_item("bar_type", self.bar_type.to_string())?;
170 dict.set_item("open", self.open.to_string())?;
171 dict.set_item("high", self.high.to_string())?;
172 dict.set_item("low", self.low.to_string())?;
173 dict.set_item("close", self.close.to_string())?;
174 dict.set_item("volume", self.volume.to_string())?;
175 dict.set_item("quote_volume", self.quote_volume.to_string())?;
176 dict.set_item("count", self.count)?;
177 dict.set_item(
178 "taker_buy_base_volume",
179 self.taker_buy_base_volume.to_string(),
180 )?;
181 dict.set_item(
182 "taker_buy_quote_volume",
183 self.taker_buy_quote_volume.to_string(),
184 )?;
185 dict.set_item("ts_event", self.ts_event.as_u64())?;
186 dict.set_item("ts_init", self.ts_init.as_u64())?;
187 Ok(dict.into())
188 }
189}
190
191#[pymethods]
192#[pyo3_stub_gen::derive::gen_stub_pymethods]
193impl BinanceSpotTicker {
194 #[getter]
195 fn instrument_id(&self) -> InstrumentId {
196 self.instrument_id
197 }
198 #[getter]
199 fn price_change(&self) -> Decimal {
200 self.price_change
201 }
202 #[getter]
203 fn price_change_percent(&self) -> Decimal {
204 self.price_change_percent
205 }
206 #[getter]
207 fn weighted_avg_price(&self) -> Decimal {
208 self.weighted_avg_price
209 }
210 #[getter]
211 fn prev_close_price(&self) -> Decimal {
212 self.prev_close_price
213 }
214 #[getter]
215 fn last_price(&self) -> Decimal {
216 self.last_price
217 }
218 #[getter]
219 fn last_qty(&self) -> Decimal {
220 self.last_qty
221 }
222 #[getter]
223 fn bid_price(&self) -> Decimal {
224 self.bid_price
225 }
226 #[getter]
227 fn bid_qty(&self) -> Decimal {
228 self.bid_qty
229 }
230 #[getter]
231 fn ask_price(&self) -> Decimal {
232 self.ask_price
233 }
234 #[getter]
235 fn ask_qty(&self) -> Decimal {
236 self.ask_qty
237 }
238 #[getter]
239 fn open_price(&self) -> Decimal {
240 self.open_price
241 }
242 #[getter]
243 fn high_price(&self) -> Decimal {
244 self.high_price
245 }
246 #[getter]
247 fn low_price(&self) -> Decimal {
248 self.low_price
249 }
250 #[getter]
251 fn volume(&self) -> Decimal {
252 self.volume
253 }
254 #[getter]
255 fn quote_volume(&self) -> Decimal {
256 self.quote_volume
257 }
258 #[getter]
259 fn open_time(&self) -> u64 {
260 self.open_time.as_u64()
261 }
262 #[getter]
263 fn close_time(&self) -> u64 {
264 self.close_time.as_u64()
265 }
266 #[getter]
267 fn first_trade_id(&self) -> i64 {
268 self.first_trade_id
269 }
270 #[getter]
271 fn last_trade_id(&self) -> i64 {
272 self.last_trade_id
273 }
274 #[getter]
275 fn num_trades(&self) -> i64 {
276 self.num_trades
277 }
278 #[getter]
279 fn ts_event(&self) -> u64 {
280 self.ts_event.as_u64()
281 }
282 #[getter]
283 fn ts_init(&self) -> u64 {
284 self.ts_init.as_u64()
285 }
286}
287
288#[pymethods]
289#[pyo3_stub_gen::derive::gen_stub_pymethods]
290impl BinanceFuturesMarkPriceUpdate {
291 #[getter]
292 fn instrument_id(&self) -> InstrumentId {
293 self.instrument_id
294 }
295 #[getter]
296 fn mark_price(&self) -> Price {
297 self.mark_price
298 }
299 #[getter]
300 fn index_price(&self) -> Price {
301 self.index_price
302 }
303 #[getter]
304 fn estimated_settle_price(&self) -> Price {
305 self.estimated_settle_price
306 }
307 #[getter]
308 fn funding_rate(&self) -> Decimal {
309 self.funding_rate
310 }
311 #[getter]
312 fn next_funding_time(&self) -> Option<u64> {
313 self.next_funding_time.map(|time| time.as_u64())
314 }
315 #[getter]
316 fn ts_event(&self) -> u64 {
317 self.ts_event.as_u64()
318 }
319 #[getter]
320 fn ts_init(&self) -> u64 {
321 self.ts_init.as_u64()
322 }
323}
324
325#[pymethods]
326#[pyo3_stub_gen::derive::gen_stub_pymethods]
327impl BinanceFuturesOpenInterestHistPoint {
328 #[getter]
329 #[pyo3(name = "sum_open_interest")]
330 fn py_sum_open_interest(&self) -> Decimal {
331 self.sum_open_interest
332 }
333
334 #[getter]
335 #[pyo3(name = "sum_open_interest_value")]
336 fn py_sum_open_interest_value(&self) -> Decimal {
337 self.sum_open_interest_value
338 }
339
340 #[getter]
341 #[pyo3(name = "ts_event")]
342 fn py_ts_event(&self) -> u64 {
343 self.ts_event.as_u64()
344 }
345}
346
347#[pymethods]
348#[pyo3_stub_gen::derive::gen_stub_pymethods]
349impl BinanceFuturesOpenInterestHist {
350 #[getter]
351 #[pyo3(name = "instrument_id")]
352 fn py_instrument_id(&self) -> InstrumentId {
353 self.instrument_id
354 }
355
356 #[getter]
357 #[pyo3(name = "period")]
358 fn py_period(&self) -> String {
359 self.period.clone()
360 }
361
362 #[getter]
363 #[pyo3(name = "points")]
364 fn py_points(&self, py: Python<'_>) -> PyResult<Py<PyList>> {
365 let points = self
366 .points
367 .iter()
368 .cloned()
369 .map(|point| point.into_py_any(py))
370 .collect::<PyResult<Vec<_>>>()?;
371 Ok(PyList::new(py, points)?.into())
372 }
373
374 #[getter]
375 #[pyo3(name = "ts_event")]
376 fn py_ts_event(&self) -> u64 {
377 self.ts_event.as_u64()
378 }
379
380 #[getter]
381 #[pyo3(name = "ts_init")]
382 fn py_ts_init(&self) -> u64 {
383 self.ts_init.as_u64()
384 }
385}