nautilus_live/python/client/
requests.rs1use std::num::NonZero;
23
24use nautilus_common::messages::data::{
25 RequestBars, RequestBookDeltas, RequestBookDepth, RequestBookSnapshot, RequestCustomData,
26 RequestFundingRates, RequestInstrument, RequestInstruments, RequestOptionChainReferencePrice,
27 RequestQuotes, RequestTrades,
28};
29use nautilus_core::{UUID4, python::params::params_to_pydict};
30use nautilus_model::{
31 data::{BarType, DataType},
32 identifiers::{ClientId, InstrumentId, OptionSeriesId, Venue},
33};
34use pyo3::{IntoPyObjectExt, prelude::*, types::PyDict};
35
36macro_rules! request {
37 ($wrapper:ident, $request:ident, $name:tt, $client_id:ty, {$($field:ident: $ty:ty = $convert:expr),* $(,)?}) => {
38 #[doc = concat!("An owned ", $name, " request.")]
39 #[pyo3_stub_gen::derive::gen_stub_pyclass(module = "nautilus_trader.live")]
40 #[pyclass(name = $name, module = "nautilus_trader.live", frozen)]
41 #[derive(Debug)]
42 pub struct $wrapper {
43 pub(crate) request: $request,
44 }
45
46 #[pyo3_stub_gen::derive::gen_stub_pymethods]
47 #[pymethods]
48 impl $wrapper {
49 #[getter]
50 fn client_id(&self) -> $client_id { self.request.client_id }
51
52 #[getter]
53 fn request_id(&self) -> UUID4 { self.request.request_id }
54
55 #[getter]
56 fn ts_init(&self) -> u64 { self.request.ts_init.as_u64() }
57
58 #[getter]
59 fn params(&self, py: Python<'_>) -> PyResult<Option<Py<PyDict>>> {
60 self.request.params.as_ref().map(|params| params_to_pydict(py, params)).transpose()
61 }
62 $(
63 #[getter]
64 fn $field(&self) -> $ty { ($convert)(&self.request) }
65 )*
66 }
67 };
68}
69
70macro_rules! request_window {
71 ($wrapper:ident) => {
72 #[pyo3_stub_gen::derive::gen_stub_pymethods]
73 #[pymethods]
74 impl $wrapper {
75 #[getter]
76 #[gen_stub(override_return_type(type_repr = "datetime.datetime | None", imports = ("datetime",)))]
77 fn start(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
78 self.request.start.into_py_any(py)
79 }
80
81 #[getter]
82 #[gen_stub(override_return_type(type_repr = "datetime.datetime | None", imports = ("datetime",)))]
83 fn end(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
84 self.request.end.into_py_any(py)
85 }
86
87 #[getter]
88 fn start_ns(&self) -> Option<i128> {
89 self.request.start.map(|timestamp| timestamp.as_nanosecond())
90 }
91
92 #[getter]
93 fn end_ns(&self) -> Option<i128> {
94 self.request.end.map(|timestamp| timestamp.as_nanosecond())
95 }
96 }
97 };
98}
99
100request!(PyRequestCustomData, RequestCustomData, "RequestCustomData", ClientId, {
101 data_type: DataType = |request: &RequestCustomData| request.data_type.clone(),
102 limit: Option<usize> = |request: &RequestCustomData| request.limit.map(NonZero::get)
103});
104request_window!(PyRequestCustomData);
105
106request!(PyRequestInstruments, RequestInstruments, "RequestInstruments", Option<ClientId>, {
107 venue: Option<Venue> = |request: &RequestInstruments| request.venue
108});
109request_window!(PyRequestInstruments);
110
111request!(PyRequestInstrument, RequestInstrument, "RequestInstrument", Option<ClientId>, {
112 instrument_id: InstrumentId = |request: &RequestInstrument| request.instrument_id
113});
114request_window!(PyRequestInstrument);
115
116request!(PyRequestBookSnapshot, RequestBookSnapshot, "RequestBookSnapshot", Option<ClientId>, {
117 instrument_id: InstrumentId = |request: &RequestBookSnapshot| request.instrument_id,
118 depth: Option<usize> = |request: &RequestBookSnapshot| request.depth.map(NonZero::get)
119});
120
121request!(PyRequestQuotes, RequestQuotes, "RequestQuotes", Option<ClientId>, {
122 instrument_id: InstrumentId = |request: &RequestQuotes| request.instrument_id,
123 limit: Option<usize> = |request: &RequestQuotes| request.limit.map(NonZero::get)
124});
125request_window!(PyRequestQuotes);
126
127request!(PyRequestTrades, RequestTrades, "RequestTrades", Option<ClientId>, {
128 instrument_id: InstrumentId = |request: &RequestTrades| request.instrument_id,
129 limit: Option<usize> = |request: &RequestTrades| request.limit.map(NonZero::get)
130});
131request_window!(PyRequestTrades);
132
133request!(PyRequestFundingRates, RequestFundingRates, "RequestFundingRates", Option<ClientId>, {
134 instrument_id: InstrumentId = |request: &RequestFundingRates| request.instrument_id,
135 limit: Option<usize> = |request: &RequestFundingRates| request.limit.map(NonZero::get)
136});
137request_window!(PyRequestFundingRates);
138
139request!(PyRequestOptionChainReferencePrice, RequestOptionChainReferencePrice, "RequestOptionChainReferencePrice", Option<ClientId>, {
140 instrument_id: InstrumentId = |request: &RequestOptionChainReferencePrice| request.instrument_id,
141 series_id: OptionSeriesId = |request: &RequestOptionChainReferencePrice| request.series_id
142});
143
144request!(PyRequestBars, RequestBars, "RequestBars", Option<ClientId>, {
145 bar_type: BarType = |request: &RequestBars| request.bar_type,
146 limit: Option<usize> = |request: &RequestBars| request.limit.map(NonZero::get)
147});
148request_window!(PyRequestBars);
149
150request!(PyRequestBookDepth, RequestBookDepth, "RequestBookDepth", Option<ClientId>, {
151 instrument_id: InstrumentId = |request: &RequestBookDepth| request.instrument_id,
152 limit: Option<usize> = |request: &RequestBookDepth| request.limit.map(NonZero::get),
153 depth: Option<usize> = |request: &RequestBookDepth| request.depth.map(NonZero::get)
154});
155request_window!(PyRequestBookDepth);
156
157request!(PyRequestBookDeltas, RequestBookDeltas, "RequestBookDeltas", Option<ClientId>, {
158 instrument_id: InstrumentId = |request: &RequestBookDeltas| request.instrument_id,
159 limit: Option<usize> = |request: &RequestBookDeltas| request.limit.map(NonZero::get)
160});
161request_window!(PyRequestBookDeltas);
162
163pub(crate) fn register(m: &Bound<'_, PyModule>) -> PyResult<()> {
164 m.add_class::<PyRequestCustomData>()?;
165 m.add_class::<PyRequestInstruments>()?;
166 m.add_class::<PyRequestInstrument>()?;
167 m.add_class::<PyRequestBookSnapshot>()?;
168 m.add_class::<PyRequestQuotes>()?;
169 m.add_class::<PyRequestTrades>()?;
170 m.add_class::<PyRequestFundingRates>()?;
171 m.add_class::<PyRequestOptionChainReferencePrice>()?;
172 m.add_class::<PyRequestBars>()?;
173 m.add_class::<PyRequestBookDepth>()?;
174 m.add_class::<PyRequestBookDeltas>()?;
175 Ok(())
176}