nautilus_interactive_brokers/python/
mod.rs1use nautilus_common::factories::{ClientConfig, DataClientFactory, ExecutionClientFactory};
19use nautilus_core::python::{to_pyruntime_err, to_pyvalue_err};
20use nautilus_system::get_global_pyo3_registry;
21use pyo3::prelude::*;
22
23use crate::{
24 common::consts::IB,
25 config::{InteractiveBrokersDataClientConfig, InteractiveBrokersExecutionClientConfig},
26 factories::{InteractiveBrokersDataClientFactory, InteractiveBrokersExecutionClientFactory},
27};
28
29pub mod config;
30pub mod conversion;
31pub mod enums;
32pub mod factories;
33pub mod historical;
34pub mod providers;
35
36#[cfg(feature = "gateway")]
37pub mod gateway;
38
39#[expect(clippy::needless_pass_by_value)]
40fn extract_interactive_brokers_data_factory(
41 py: Python<'_>,
42 factory: Py<PyAny>,
43) -> PyResult<Box<dyn DataClientFactory>> {
44 match factory.extract::<InteractiveBrokersDataClientFactory>(py) {
45 Ok(f) => Ok(Box::new(f)),
46 Err(e) => Err(to_pyvalue_err(format!(
47 "Failed to extract InteractiveBrokersDataClientFactory: {e}"
48 ))),
49 }
50}
51
52#[expect(clippy::needless_pass_by_value)]
53fn extract_interactive_brokers_exec_factory(
54 py: Python<'_>,
55 factory: Py<PyAny>,
56) -> PyResult<Box<dyn ExecutionClientFactory>> {
57 match factory.extract::<InteractiveBrokersExecutionClientFactory>(py) {
58 Ok(f) => Ok(Box::new(f)),
59 Err(e) => Err(to_pyvalue_err(format!(
60 "Failed to extract InteractiveBrokersExecutionClientFactory: {e}"
61 ))),
62 }
63}
64
65#[expect(clippy::needless_pass_by_value)]
66fn extract_interactive_brokers_data_config(
67 py: Python<'_>,
68 config: Py<PyAny>,
69) -> PyResult<Box<dyn ClientConfig>> {
70 match config.extract::<InteractiveBrokersDataClientConfig>(py) {
71 Ok(c) => Ok(Box::new(c)),
72 Err(e) => Err(to_pyvalue_err(format!(
73 "Failed to extract InteractiveBrokersDataClientConfig: {e}"
74 ))),
75 }
76}
77
78#[expect(clippy::needless_pass_by_value)]
79fn extract_interactive_brokers_exec_config(
80 py: Python<'_>,
81 config: Py<PyAny>,
82) -> PyResult<Box<dyn ClientConfig>> {
83 match config.extract::<InteractiveBrokersExecutionClientConfig>(py) {
84 Ok(c) => Ok(Box::new(c)),
85 Err(e) => Err(to_pyvalue_err(format!(
86 "Failed to extract InteractiveBrokersExecutionClientConfig: {e}"
87 ))),
88 }
89}
90
91#[pymodule]
97pub fn interactive_brokers(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
98 m.add_class::<crate::config::MarketDataType>()?;
99 m.add_class::<crate::common::enums::IbAction>()?;
100 m.add_class::<crate::common::enums::IbArticleType>()?;
101 m.add_class::<crate::common::enums::IbAuctionStrategy>()?;
102 m.add_class::<crate::common::enums::IbAuctionType>()?;
103 m.add_class::<crate::common::enums::IbBondIdentifierKind>()?;
104 m.add_class::<crate::common::enums::IbBuilderTimeInForce>()?;
105 m.add_class::<crate::common::enums::IbComboLegOpenClose>()?;
106 m.add_class::<crate::common::enums::IbConditionConjunction>()?;
107 m.add_class::<crate::common::enums::IbConditionKind>()?;
108 m.add_class::<crate::common::enums::IbExerciseAction>()?;
109 m.add_class::<crate::common::enums::IbFundAssetType>()?;
110 m.add_class::<crate::common::enums::IbFundDistributionPolicyIndicator>()?;
111 m.add_class::<crate::common::enums::IbHistoricalBarSize>()?;
112 m.add_class::<crate::common::enums::IbHistoricalTickType>()?;
113 m.add_class::<crate::common::enums::IbHistoricalWhatToShow>()?;
114 m.add_class::<crate::common::enums::IbLegAction>()?;
115 m.add_class::<crate::common::enums::IbLiquidity>()?;
116 m.add_class::<crate::common::enums::IbOcaType>()?;
117 m.add_class::<crate::common::enums::IbOrderOpenClose>()?;
118 m.add_class::<crate::common::enums::IbOrderOrigin>()?;
119 m.add_class::<crate::common::enums::IbOptionRight>()?;
120 m.add_class::<crate::common::enums::IbOrderStatus>()?;
121 m.add_class::<crate::common::enums::IbOrderType>()?;
122 m.add_class::<crate::common::enums::IbRealtimeBarSize>()?;
123 m.add_class::<crate::common::enums::IbRealtimeWhatToShow>()?;
124 m.add_class::<crate::common::enums::IbReferencePriceType>()?;
125 m.add_class::<crate::common::enums::IbRiskAversion>()?;
126 m.add_class::<crate::common::enums::IbRule80A>()?;
127 m.add_class::<crate::common::enums::IbSecurityType>()?;
128 m.add_class::<crate::common::enums::IbShortSaleSlot>()?;
129 m.add_class::<crate::common::enums::IbTickType>()?;
130 m.add_class::<crate::common::enums::IbTimeInForce>()?;
131 m.add_class::<crate::common::enums::IbTradingHours>()?;
132 m.add_class::<crate::common::enums::IbTriggerMethod>()?;
133 m.add_class::<crate::common::enums::IbTwapStrategyType>()?;
134 m.add_class::<crate::common::enums::IbVolatilityType>()?;
135 m.add_class::<crate::config::SymbologyMethod>()?;
136 m.add_class::<crate::config::InteractiveBrokersDataClientConfig>()?;
137 m.add_class::<crate::config::InteractiveBrokersExecutionClientConfig>()?;
138 m.add_class::<crate::config::InteractiveBrokersInstrumentProviderConfig>()?;
139 m.add_class::<crate::config::DockerizedIBGatewayConfig>()?;
140 m.add_class::<crate::config::TradingMode>()?;
141 m.add_class::<crate::error::ErrorCategory>()?;
142 m.add_class::<crate::error::InteractiveBrokersErrorKind>()?;
143 m.add_class::<crate::factories::InteractiveBrokersDataClientFactory>()?;
144 m.add_class::<crate::factories::InteractiveBrokersExecutionClientFactory>()?;
145 m.add_class::<crate::historical::HistoricalInteractiveBrokersClient>()?;
146 m.add_class::<crate::providers::instruments::InteractiveBrokersInstrumentProvider>()?;
147
148 #[cfg(feature = "gateway")]
149 {
150 m.add_class::<crate::gateway::dockerized::ContainerStatus>()?;
151 m.add_class::<crate::gateway::dockerized::DockerizedIBGateway>()?;
152 }
153
154 let registry = get_global_pyo3_registry();
155
156 if let Err(e) = registry
157 .register_factory_extractor(IB.to_string(), extract_interactive_brokers_data_factory)
158 {
159 return Err(to_pyruntime_err(format!(
160 "Failed to register Interactive Brokers data factory extractor: {e}"
161 )));
162 }
163
164 if let Err(e) = registry
165 .register_exec_factory_extractor(IB.to_string(), extract_interactive_brokers_exec_factory)
166 {
167 return Err(to_pyruntime_err(format!(
168 "Failed to register Interactive Brokers exec factory extractor: {e}"
169 )));
170 }
171
172 if let Err(e) = registry.register_config_extractor(
173 "InteractiveBrokersDataClientConfig".to_string(),
174 extract_interactive_brokers_data_config,
175 ) {
176 return Err(to_pyruntime_err(format!(
177 "Failed to register Interactive Brokers data config extractor: {e}"
178 )));
179 }
180
181 if let Err(e) = registry.register_config_extractor(
182 "InteractiveBrokersExecutionClientConfig".to_string(),
183 extract_interactive_brokers_exec_config,
184 ) {
185 return Err(to_pyruntime_err(format!(
186 "Failed to register Interactive Brokers exec config extractor: {e}"
187 )));
188 }
189
190 Ok(())
191}