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, InteractiveBrokersExecClientConfig},
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::<InteractiveBrokersExecClientConfig>(py) {
84 Ok(c) => Ok(Box::new(c)),
85 Err(e) => Err(to_pyvalue_err(format!(
86 "Failed to extract InteractiveBrokersExecClientConfig: {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::IbAccountSummaryEvent>()?;
100 m.add_class::<crate::common::enums::IbAccountUpdateEvent>()?;
101 m.add_class::<crate::common::enums::IbAccountUpdateMultiEvent>()?;
102 m.add_class::<crate::common::enums::IbAction>()?;
103 m.add_class::<crate::common::enums::IbArticleType>()?;
104 m.add_class::<crate::common::enums::IbAuctionStrategy>()?;
105 m.add_class::<crate::common::enums::IbAuctionType>()?;
106 m.add_class::<crate::common::enums::IbBondIdentifierKind>()?;
107 m.add_class::<crate::common::enums::IbBuilderTimeInForce>()?;
108 m.add_class::<crate::common::enums::IbCancelOrderEvent>()?;
109 m.add_class::<crate::common::enums::IbComboLegOpenClose>()?;
110 m.add_class::<crate::common::enums::IbConditionConjunction>()?;
111 m.add_class::<crate::common::enums::IbConditionKind>()?;
112 m.add_class::<crate::common::enums::IbExecutionsEvent>()?;
113 m.add_class::<crate::common::enums::IbExerciseAction>()?;
114 m.add_class::<crate::common::enums::IbExerciseOptionsEvent>()?;
115 m.add_class::<crate::common::enums::IbFundAssetType>()?;
116 m.add_class::<crate::common::enums::IbFundDistributionPolicyIndicator>()?;
117 m.add_class::<crate::common::enums::IbHistoricalBarSize>()?;
118 m.add_class::<crate::common::enums::IbHistoricalBarUpdateEvent>()?;
119 m.add_class::<crate::common::enums::IbHistoricalTickType>()?;
120 m.add_class::<crate::common::enums::IbHistoricalWhatToShow>()?;
121 m.add_class::<crate::common::enums::IbLegAction>()?;
122 m.add_class::<crate::common::enums::IbLiquidity>()?;
123 m.add_class::<crate::common::enums::IbMarketDepthEvent>()?;
124 m.add_class::<crate::common::enums::IbOcaType>()?;
125 m.add_class::<crate::common::enums::IbOrderOpenClose>()?;
126 m.add_class::<crate::common::enums::IbOrderOrigin>()?;
127 m.add_class::<crate::common::enums::IbOptionRight>()?;
128 m.add_class::<crate::common::enums::IbOrderStatus>()?;
129 m.add_class::<crate::common::enums::IbOrderType>()?;
130 m.add_class::<crate::common::enums::IbOrderUpdateEvent>()?;
131 m.add_class::<crate::common::enums::IbOrdersEvent>()?;
132 m.add_class::<crate::common::enums::IbPlaceOrderEvent>()?;
133 m.add_class::<crate::common::enums::IbPositionUpdateEvent>()?;
134 m.add_class::<crate::common::enums::IbPositionUpdateMultiEvent>()?;
135 m.add_class::<crate::common::enums::IbRealtimeBarSize>()?;
136 m.add_class::<crate::common::enums::IbRealtimeWhatToShow>()?;
137 m.add_class::<crate::common::enums::IbReferencePriceType>()?;
138 m.add_class::<crate::common::enums::IbRiskAversion>()?;
139 m.add_class::<crate::common::enums::IbRule80A>()?;
140 m.add_class::<crate::common::enums::IbSecurityType>()?;
141 m.add_class::<crate::common::enums::IbShortSaleSlot>()?;
142 m.add_class::<crate::common::enums::IbTickEvent>()?;
143 m.add_class::<crate::common::enums::IbTickType>()?;
144 m.add_class::<crate::common::enums::IbTimeInForce>()?;
145 m.add_class::<crate::common::enums::IbTradingHours>()?;
146 m.add_class::<crate::common::enums::IbTriggerMethod>()?;
147 m.add_class::<crate::common::enums::IbTwapStrategyType>()?;
148 m.add_class::<crate::common::enums::IbVolatilityType>()?;
149 m.add_class::<crate::config::SymbologyMethod>()?;
150 m.add_class::<crate::error::ErrorCategory>()?;
151 m.add_class::<crate::error::InteractiveBrokersErrorKind>()?;
152 m.add_class::<crate::config::InteractiveBrokersDataClientConfig>()?;
153 m.add_class::<crate::config::InteractiveBrokersExecClientConfig>()?;
154 m.add_class::<crate::config::InteractiveBrokersInstrumentProviderConfig>()?;
155 m.add_class::<crate::config::DockerizedIBGatewayConfig>()?;
156 m.add_class::<crate::config::TradingMode>()?;
157 m.add_class::<crate::factories::InteractiveBrokersDataClientFactory>()?;
158 m.add_class::<crate::factories::InteractiveBrokersExecutionClientFactory>()?;
159 m.add_class::<crate::historical::HistoricalInteractiveBrokersClient>()?;
160 m.add_class::<crate::providers::instruments::InteractiveBrokersInstrumentProvider>()?;
161
162 #[cfg(feature = "gateway")]
163 {
164 m.add_class::<crate::gateway::dockerized::ContainerStatus>()?;
165 m.add_class::<crate::gateway::dockerized::DockerizedIBGateway>()?;
166 }
167
168 let registry = get_global_pyo3_registry();
169
170 if let Err(e) = registry
171 .register_factory_extractor(IB.to_string(), extract_interactive_brokers_data_factory)
172 {
173 return Err(to_pyruntime_err(format!(
174 "Failed to register Interactive Brokers data factory extractor: {e}"
175 )));
176 }
177
178 if let Err(e) = registry
179 .register_exec_factory_extractor(IB.to_string(), extract_interactive_brokers_exec_factory)
180 {
181 return Err(to_pyruntime_err(format!(
182 "Failed to register Interactive Brokers exec factory extractor: {e}"
183 )));
184 }
185
186 if let Err(e) = registry.register_config_extractor(
187 "InteractiveBrokersDataClientConfig".to_string(),
188 extract_interactive_brokers_data_config,
189 ) {
190 return Err(to_pyruntime_err(format!(
191 "Failed to register Interactive Brokers data config extractor: {e}"
192 )));
193 }
194
195 if let Err(e) = registry.register_config_extractor(
196 "InteractiveBrokersExecClientConfig".to_string(),
197 extract_interactive_brokers_exec_config,
198 ) {
199 return Err(to_pyruntime_err(format!(
200 "Failed to register Interactive Brokers exec config extractor: {e}"
201 )));
202 }
203
204 Ok(())
205}