nautilus_interactive_brokers/python/
providers.rs1use nautilus_core::python::to_pyruntime_err;
19use nautilus_model::{identifiers::InstrumentId, python::instruments::instrument_any_to_pyobject};
20use pyo3::{prelude::*, types::PyList};
21
22use crate::{
23 providers::instruments::InteractiveBrokersInstrumentProvider,
24 python::conversion::{contract_details_to_pyobject, py_to_contract},
25};
26
27#[cfg(feature = "python")]
28#[pymethods]
29#[pyo3_stub_gen::derive::gen_stub_pymethods]
30impl InteractiveBrokersInstrumentProvider {
31 #[new]
32 fn py_new(config: crate::config::InteractiveBrokersInstrumentProviderConfig) -> Self {
33 Self::new(config)
34 }
35
36 fn __repr__(&self) -> String {
37 format!("{self:?}")
38 }
39
40 #[pyo3(name = "find")]
42 fn py_find(&self, py: Python, instrument_id: InstrumentId) -> PyResult<Option<Py<PyAny>>> {
43 match self.find(&instrument_id) {
44 Some(instrument) => Ok(Some(instrument_any_to_pyobject(py, instrument)?)),
45 None => Ok(None),
46 }
47 }
48
49 #[pyo3(name = "find_by_contract_id")]
51 fn py_find_by_contract_id(&self, py: Python, contract_id: i32) -> PyResult<Option<Py<PyAny>>> {
52 match self.find_by_contract_id(contract_id) {
53 Some(instrument) => Ok(Some(instrument_any_to_pyobject(py, instrument)?)),
54 None => Ok(None),
55 }
56 }
57
58 #[pyo3(name = "get_all")]
60 fn py_get_all<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyList>> {
61 let instruments = self.get_all();
62 let py_instruments: PyResult<Vec<_>> = instruments
63 .into_iter()
64 .map(|inst| instrument_any_to_pyobject(py, inst))
65 .collect();
66 PyList::new(py, py_instruments?)
67 }
68
69 #[pyo3(name = "count")]
71 fn py_count(&self) -> usize {
72 self.count()
73 }
74
75 #[pyo3(name = "get_price_magnifier")]
77 fn py_get_price_magnifier(&self, instrument_id: InstrumentId) -> i32 {
78 self.get_price_magnifier(&instrument_id)
79 }
80
81 #[pyo3(name = "fetch_contract_details")]
86 fn py_fetch_contract_details(&self) {}
87
88 #[pyo3(name = "determine_venue")]
90 #[allow(clippy::needless_pass_by_value)]
91 fn py_determine_venue(&self, py: Python<'_>, contract: Py<PyAny>) -> PyResult<String> {
92 let rust_contract = py_to_contract(contract.bind(py))?;
93 Ok(self.determine_venue(&rust_contract, None).to_string())
94 }
95
96 #[pyo3(name = "instrument_id_to_ib_contract_details")]
98 fn py_instrument_id_to_ib_contract_details(
99 &self,
100 py: Python<'_>,
101 instrument_id: InstrumentId,
102 ) -> PyResult<Option<Py<PyAny>>> {
103 self.instrument_id_to_ib_contract_details(&instrument_id)
104 .as_ref()
105 .map(|details| contract_details_to_pyobject(py, details))
106 .transpose()
107 }
108
109 #[pyo3(name = "save_cache")]
119 fn py_save_cache<'py>(
120 &self,
121 py: Python<'py>,
122 cache_path: String,
123 ) -> PyResult<Bound<'py, PyAny>> {
124 let provider = self.clone();
125 pyo3_async_runtimes::tokio::future_into_py(py, async move {
126 provider
127 .save_cache(&cache_path)
128 .await
129 .map_err(to_pyruntime_err)
130 })
131 }
132
133 #[pyo3(name = "load_cache")]
147 fn py_load_cache<'py>(
148 &self,
149 py: Python<'py>,
150 cache_path: String,
151 ) -> PyResult<Bound<'py, PyAny>> {
152 let provider = self.clone();
153 pyo3_async_runtimes::tokio::future_into_py(py, async move {
154 provider
155 .load_cache(&cache_path)
156 .await
157 .map_err(to_pyruntime_err)
158 })
159 }
160}