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 enums::OrderSide,
25 identifiers::InstrumentId,
26 types::{Price, Quantity},
27};
28use pyo3::{
29 IntoPyObjectExt,
30 basic::CompareOp,
31 prelude::*,
32 types::{PyDict, PyList},
33};
34use rust_decimal::Decimal;
35
36use crate::{
37 common::bar::BinanceBar,
38 data_types::{
39 BinanceFuturesLiquidation, BinanceFuturesMarkPriceUpdate, BinanceFuturesOpenInterest,
40 BinanceFuturesOpenInterestHist, BinanceFuturesOpenInterestHistPoint, BinanceFuturesTicker,
41 BinanceSpotTicker,
42 },
43};
44
45#[pymethods]
46#[pyo3_stub_gen::derive::gen_stub_pymethods]
47impl BinanceBar {
48 fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py<PyAny> {
49 match op {
50 CompareOp::Eq => self.eq(other).into_py_any_unwrap(py),
51 CompareOp::Ne => self.ne(other).into_py_any_unwrap(py),
52 _ => py.NotImplemented(),
53 }
54 }
55
56 fn __hash__(&self) -> isize {
57 let mut hasher = DefaultHasher::new();
58 self.bar_type.hash(&mut hasher);
59 self.ts_event.hash(&mut hasher);
60 hasher.finish() as isize
61 }
62
63 fn __repr__(&self) -> String {
64 format!(
65 "{}(bar_type={}, open={}, high={}, low={}, close={}, volume={}, quote_volume={}, count={}, taker_buy_base_volume={}, taker_buy_quote_volume={}, ts_event={}, ts_init={})",
66 stringify!(BinanceBar),
67 self.bar_type,
68 self.open,
69 self.high,
70 self.low,
71 self.close,
72 self.volume,
73 self.quote_volume,
74 self.count,
75 self.taker_buy_base_volume,
76 self.taker_buy_quote_volume,
77 self.ts_event,
78 self.ts_init,
79 )
80 }
81
82 fn __str__(&self) -> String {
83 self.__repr__()
84 }
85
86 #[getter]
87 #[pyo3(name = "bar_type")]
88 fn py_bar_type(&self) -> BarType {
89 self.bar_type
90 }
91
92 #[getter]
93 #[pyo3(name = "open")]
94 const fn py_open(&self) -> Price {
95 self.open
96 }
97
98 #[getter]
99 #[pyo3(name = "high")]
100 const fn py_high(&self) -> Price {
101 self.high
102 }
103
104 #[getter]
105 #[pyo3(name = "low")]
106 const fn py_low(&self) -> Price {
107 self.low
108 }
109
110 #[getter]
111 #[pyo3(name = "close")]
112 const fn py_close(&self) -> Price {
113 self.close
114 }
115
116 #[getter]
117 #[pyo3(name = "volume")]
118 const fn py_volume(&self) -> Quantity {
119 self.volume
120 }
121
122 #[getter]
123 #[pyo3(name = "quote_volume")]
124 fn py_quote_volume(&self) -> Decimal {
125 self.quote_volume
126 }
127
128 #[getter]
129 #[pyo3(name = "count")]
130 const fn py_count(&self) -> u64 {
131 self.count
132 }
133
134 #[getter]
135 #[pyo3(name = "taker_buy_base_volume")]
136 fn py_taker_buy_base_volume(&self) -> Decimal {
137 self.taker_buy_base_volume
138 }
139
140 #[getter]
141 #[pyo3(name = "taker_buy_quote_volume")]
142 fn py_taker_buy_quote_volume(&self) -> Decimal {
143 self.taker_buy_quote_volume
144 }
145
146 #[getter]
147 #[pyo3(name = "ts_event")]
148 const fn py_ts_event(&self) -> u64 {
149 self.ts_event.as_u64()
150 }
151
152 #[getter]
153 #[pyo3(name = "ts_init")]
154 const fn py_ts_init(&self) -> u64 {
155 self.ts_init.as_u64()
156 }
157
158 #[staticmethod]
159 #[pyo3(name = "from_dict")]
160 fn py_from_dict(py: Python<'_>, values: Py<PyDict>) -> PyResult<Self> {
161 from_dict_pyo3(py, values)
162 }
163
164 #[pyo3(name = "to_dict")]
168 pub fn py_to_dict(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
169 let dict = PyDict::new(py);
170 dict.set_item("type", stringify!(BinanceBar))?;
171 dict.set_item("bar_type", self.bar_type.to_string())?;
172 dict.set_item("open", self.open.to_string())?;
173 dict.set_item("high", self.high.to_string())?;
174 dict.set_item("low", self.low.to_string())?;
175 dict.set_item("close", self.close.to_string())?;
176 dict.set_item("volume", self.volume.to_string())?;
177 dict.set_item("quote_volume", self.quote_volume.to_string())?;
178 dict.set_item("count", self.count)?;
179 dict.set_item(
180 "taker_buy_base_volume",
181 self.taker_buy_base_volume.to_string(),
182 )?;
183 dict.set_item(
184 "taker_buy_quote_volume",
185 self.taker_buy_quote_volume.to_string(),
186 )?;
187 dict.set_item("ts_event", self.ts_event.as_u64())?;
188 dict.set_item("ts_init", self.ts_init.as_u64())?;
189 Ok(dict.into())
190 }
191}
192
193#[pymethods]
194#[pyo3_stub_gen::derive::gen_stub_pymethods]
195impl BinanceFuturesLiquidation {
196 #[getter]
197 #[pyo3(name = "instrument_id")]
198 fn py_instrument_id(&self) -> InstrumentId {
199 self.instrument_id
200 }
201
202 #[getter]
203 #[pyo3(name = "side")]
204 fn py_side(&self) -> OrderSide {
205 self.side
206 }
207
208 #[getter]
209 #[pyo3(name = "price")]
210 fn py_price(&self) -> Price {
211 self.price
212 }
213
214 #[getter]
215 #[pyo3(name = "average_price")]
216 fn py_average_price(&self) -> Price {
217 self.average_price
218 }
219
220 #[getter]
221 #[pyo3(name = "last_filled_qty")]
222 fn py_last_filled_qty(&self) -> Quantity {
223 self.last_filled_qty
224 }
225
226 #[getter]
227 #[pyo3(name = "accumulated_qty")]
228 fn py_accumulated_qty(&self) -> Quantity {
229 self.accumulated_qty
230 }
231
232 #[getter]
233 #[pyo3(name = "ts_event")]
234 fn py_ts_event(&self) -> u64 {
235 self.ts_event.as_u64()
236 }
237
238 #[getter]
239 #[pyo3(name = "ts_init")]
240 fn py_ts_init(&self) -> u64 {
241 self.ts_init.as_u64()
242 }
243}
244
245#[pymethods]
246#[pyo3_stub_gen::derive::gen_stub_pymethods]
247impl BinanceFuturesTicker {
248 #[getter]
249 #[pyo3(name = "instrument_id")]
250 fn py_instrument_id(&self) -> InstrumentId {
251 self.instrument_id
252 }
253
254 #[getter]
255 #[pyo3(name = "price_change")]
256 fn py_price_change(&self) -> Decimal {
257 self.price_change
258 }
259
260 #[getter]
261 #[pyo3(name = "price_change_percent")]
262 fn py_price_change_percent(&self) -> Decimal {
263 self.price_change_percent
264 }
265
266 #[getter]
267 #[pyo3(name = "weighted_avg_price")]
268 fn py_weighted_avg_price(&self) -> Decimal {
269 self.weighted_avg_price
270 }
271
272 #[getter]
273 #[pyo3(name = "last_price")]
274 fn py_last_price(&self) -> Decimal {
275 self.last_price
276 }
277
278 #[getter]
279 #[pyo3(name = "last_qty")]
280 fn py_last_qty(&self) -> Decimal {
281 self.last_qty
282 }
283
284 #[getter]
285 #[pyo3(name = "open_price")]
286 fn py_open_price(&self) -> Decimal {
287 self.open_price
288 }
289
290 #[getter]
291 #[pyo3(name = "high_price")]
292 fn py_high_price(&self) -> Decimal {
293 self.high_price
294 }
295
296 #[getter]
297 #[pyo3(name = "low_price")]
298 fn py_low_price(&self) -> Decimal {
299 self.low_price
300 }
301
302 #[getter]
303 #[pyo3(name = "volume")]
304 fn py_volume(&self) -> Decimal {
305 self.volume
306 }
307
308 #[getter]
309 #[pyo3(name = "quote_volume")]
310 fn py_quote_volume(&self) -> Decimal {
311 self.quote_volume
312 }
313
314 #[getter]
315 #[pyo3(name = "open_time")]
316 fn py_open_time(&self) -> u64 {
317 self.open_time.as_u64()
318 }
319
320 #[getter]
321 #[pyo3(name = "close_time")]
322 fn py_close_time(&self) -> u64 {
323 self.close_time.as_u64()
324 }
325
326 #[getter]
327 #[pyo3(name = "first_trade_id")]
328 fn py_first_trade_id(&self) -> i64 {
329 self.first_trade_id
330 }
331
332 #[getter]
333 #[pyo3(name = "last_trade_id")]
334 fn py_last_trade_id(&self) -> i64 {
335 self.last_trade_id
336 }
337
338 #[getter]
339 #[pyo3(name = "num_trades")]
340 fn py_num_trades(&self) -> i64 {
341 self.num_trades
342 }
343
344 #[getter]
345 #[pyo3(name = "ts_event")]
346 fn py_ts_event(&self) -> u64 {
347 self.ts_event.as_u64()
348 }
349
350 #[getter]
351 #[pyo3(name = "ts_init")]
352 fn py_ts_init(&self) -> u64 {
353 self.ts_init.as_u64()
354 }
355}
356
357#[pymethods]
358#[pyo3_stub_gen::derive::gen_stub_pymethods]
359impl BinanceSpotTicker {
360 #[getter]
361 fn instrument_id(&self) -> InstrumentId {
362 self.instrument_id
363 }
364 #[getter]
365 fn price_change(&self) -> Decimal {
366 self.price_change
367 }
368 #[getter]
369 fn price_change_percent(&self) -> Decimal {
370 self.price_change_percent
371 }
372 #[getter]
373 fn weighted_avg_price(&self) -> Decimal {
374 self.weighted_avg_price
375 }
376 #[getter]
377 fn prev_close_price(&self) -> Decimal {
378 self.prev_close_price
379 }
380 #[getter]
381 fn last_price(&self) -> Decimal {
382 self.last_price
383 }
384 #[getter]
385 fn last_qty(&self) -> Decimal {
386 self.last_qty
387 }
388 #[getter]
389 fn bid_price(&self) -> Decimal {
390 self.bid_price
391 }
392 #[getter]
393 fn bid_qty(&self) -> Decimal {
394 self.bid_qty
395 }
396 #[getter]
397 fn ask_price(&self) -> Decimal {
398 self.ask_price
399 }
400 #[getter]
401 fn ask_qty(&self) -> Decimal {
402 self.ask_qty
403 }
404 #[getter]
405 fn open_price(&self) -> Decimal {
406 self.open_price
407 }
408 #[getter]
409 fn high_price(&self) -> Decimal {
410 self.high_price
411 }
412 #[getter]
413 fn low_price(&self) -> Decimal {
414 self.low_price
415 }
416 #[getter]
417 fn volume(&self) -> Decimal {
418 self.volume
419 }
420 #[getter]
421 fn quote_volume(&self) -> Decimal {
422 self.quote_volume
423 }
424 #[getter]
425 fn open_time(&self) -> u64 {
426 self.open_time.as_u64()
427 }
428 #[getter]
429 fn close_time(&self) -> u64 {
430 self.close_time.as_u64()
431 }
432 #[getter]
433 fn first_trade_id(&self) -> i64 {
434 self.first_trade_id
435 }
436 #[getter]
437 fn last_trade_id(&self) -> i64 {
438 self.last_trade_id
439 }
440 #[getter]
441 fn num_trades(&self) -> i64 {
442 self.num_trades
443 }
444 #[getter]
445 fn ts_event(&self) -> u64 {
446 self.ts_event.as_u64()
447 }
448 #[getter]
449 fn ts_init(&self) -> u64 {
450 self.ts_init.as_u64()
451 }
452}
453
454#[pymethods]
455#[pyo3_stub_gen::derive::gen_stub_pymethods]
456impl BinanceFuturesMarkPriceUpdate {
457 #[getter]
458 fn instrument_id(&self) -> InstrumentId {
459 self.instrument_id
460 }
461 #[getter]
462 fn mark_price(&self) -> Price {
463 self.mark_price
464 }
465 #[getter]
466 fn index_price(&self) -> Price {
467 self.index_price
468 }
469 #[getter]
470 fn estimated_settle_price(&self) -> Price {
471 self.estimated_settle_price
472 }
473 #[getter]
474 fn funding_rate(&self) -> Decimal {
475 self.funding_rate
476 }
477 #[getter]
478 fn next_funding_time(&self) -> Option<u64> {
479 self.next_funding_time.map(|time| time.as_u64())
480 }
481 #[getter]
482 fn ts_event(&self) -> u64 {
483 self.ts_event.as_u64()
484 }
485 #[getter]
486 fn ts_init(&self) -> u64 {
487 self.ts_init.as_u64()
488 }
489}
490
491#[pymethods]
492#[pyo3_stub_gen::derive::gen_stub_pymethods]
493impl BinanceFuturesOpenInterest {
494 #[getter]
495 #[pyo3(name = "instrument_id")]
496 fn py_instrument_id(&self) -> InstrumentId {
497 self.instrument_id
498 }
499
500 #[getter]
501 #[pyo3(name = "open_interest")]
502 fn py_open_interest(&self) -> Decimal {
503 self.open_interest
504 }
505
506 #[getter]
507 #[pyo3(name = "ts_event")]
508 fn py_ts_event(&self) -> u64 {
509 self.ts_event.as_u64()
510 }
511
512 #[getter]
513 #[pyo3(name = "ts_init")]
514 fn py_ts_init(&self) -> u64 {
515 self.ts_init.as_u64()
516 }
517}
518
519#[pymethods]
520#[pyo3_stub_gen::derive::gen_stub_pymethods]
521impl BinanceFuturesOpenInterestHistPoint {
522 #[getter]
523 #[pyo3(name = "sum_open_interest")]
524 fn py_sum_open_interest(&self) -> Decimal {
525 self.sum_open_interest
526 }
527
528 #[getter]
529 #[pyo3(name = "sum_open_interest_value")]
530 fn py_sum_open_interest_value(&self) -> Decimal {
531 self.sum_open_interest_value
532 }
533
534 #[getter]
535 #[pyo3(name = "ts_event")]
536 fn py_ts_event(&self) -> u64 {
537 self.ts_event.as_u64()
538 }
539}
540
541#[pymethods]
542#[pyo3_stub_gen::derive::gen_stub_pymethods]
543impl BinanceFuturesOpenInterestHist {
544 #[getter]
545 #[pyo3(name = "instrument_id")]
546 fn py_instrument_id(&self) -> InstrumentId {
547 self.instrument_id
548 }
549
550 #[getter]
551 #[pyo3(name = "period")]
552 fn py_period(&self) -> String {
553 self.period.clone()
554 }
555
556 #[getter]
557 #[pyo3(name = "points")]
558 fn py_points(&self, py: Python<'_>) -> PyResult<Py<PyList>> {
559 let points = self
560 .points
561 .iter()
562 .cloned()
563 .map(|point| point.into_py_any(py))
564 .collect::<PyResult<Vec<_>>>()?;
565 Ok(PyList::new(py, points)?.into())
566 }
567
568 #[getter]
569 #[pyo3(name = "ts_event")]
570 fn py_ts_event(&self) -> u64 {
571 self.ts_event.as_u64()
572 }
573
574 #[getter]
575 #[pyo3(name = "ts_init")]
576 fn py_ts_init(&self) -> u64 {
577 self.ts_init.as_u64()
578 }
579}