nautilus_interactive_brokers/python/
config.rs1use nautilus_model::identifiers::InstrumentId;
19use pyo3::prelude::*;
20
21use crate::config::{
22 DockerizedIBGatewayConfig, InteractiveBrokersDataClientConfig,
23 InteractiveBrokersExecClientConfig, InteractiveBrokersInstrumentProviderConfig, MarketDataType,
24 TradingMode,
25};
26
27#[pymethods]
28impl MarketDataType {
29 #[classattr]
30 const REALTIME: i32 = 1;
31
32 #[classattr]
33 const FROZEN: i32 = 2;
34
35 #[classattr]
36 const DELAYED: i32 = 3;
37
38 #[classattr]
39 const DELAYED_FROZEN: i32 = 4;
40}
41
42#[pymethods]
43impl InteractiveBrokersDataClientConfig {
44 #[new]
46 #[pyo3(signature = (host=None, port=None, client_id=None, use_regular_trading_hours=None, market_data_type=None, ignore_quote_tick_size_updates=None, connection_timeout=None, request_timeout=None, handle_revised_bars=None, batch_quotes=None))]
47 #[allow(clippy::too_many_arguments)]
48 fn py_new(
49 host: Option<String>,
50 port: Option<u16>,
51 client_id: Option<i32>,
52 use_regular_trading_hours: Option<bool>,
53 market_data_type: Option<MarketDataType>,
54 ignore_quote_tick_size_updates: Option<bool>,
55 connection_timeout: Option<u64>,
56 request_timeout: Option<u64>,
57 handle_revised_bars: Option<bool>,
58 batch_quotes: Option<bool>,
59 ) -> Self {
60 Self {
61 host: host.unwrap_or_else(|| crate::common::consts::DEFAULT_HOST.to_string()),
62 port: port.unwrap_or(crate::common::consts::DEFAULT_PORT),
63 client_id: client_id.unwrap_or(crate::common::consts::DEFAULT_CLIENT_ID),
64 use_regular_trading_hours: use_regular_trading_hours.unwrap_or(true),
65 market_data_type: market_data_type.unwrap_or_default(),
66 ignore_quote_tick_size_updates: ignore_quote_tick_size_updates.unwrap_or(false),
67 connection_timeout: connection_timeout.unwrap_or(300),
68 request_timeout: request_timeout.unwrap_or(60),
69 handle_revised_bars: handle_revised_bars.unwrap_or(false),
70 batch_quotes: batch_quotes.unwrap_or(true),
71 }
72 }
73
74 #[getter]
76 fn host(&self) -> &str {
77 &self.host
78 }
79
80 #[getter]
82 fn port(&self) -> u16 {
83 self.port
84 }
85
86 #[getter]
88 fn client_id(&self) -> i32 {
89 self.client_id
90 }
91
92 #[getter]
94 fn use_regular_trading_hours(&self) -> bool {
95 self.use_regular_trading_hours
96 }
97
98 #[getter]
100 fn market_data_type(&self) -> MarketDataType {
101 self.market_data_type
102 }
103
104 #[getter]
106 fn ignore_quote_tick_size_updates(&self) -> bool {
107 self.ignore_quote_tick_size_updates
108 }
109
110 #[getter]
112 fn connection_timeout(&self) -> u64 {
113 self.connection_timeout
114 }
115
116 #[getter]
118 fn request_timeout(&self) -> u64 {
119 self.request_timeout
120 }
121
122 #[getter]
124 fn handle_revised_bars(&self) -> bool {
125 self.handle_revised_bars
126 }
127
128 #[getter]
130 fn batch_quotes(&self) -> bool {
131 self.batch_quotes
132 }
133}
134
135#[pymethods]
136impl InteractiveBrokersExecClientConfig {
137 #[new]
139 #[pyo3(signature = (host=None, port=None, client_id=None, account_id=None, connection_timeout=None, request_timeout=None, fetch_all_open_orders=None, track_option_exercise_from_position_update=None))]
140 fn py_new(
141 host: Option<String>,
142 port: Option<u16>,
143 client_id: Option<i32>,
144 account_id: Option<String>,
145 connection_timeout: Option<u64>,
146 request_timeout: Option<u64>,
147 fetch_all_open_orders: Option<bool>,
148 track_option_exercise_from_position_update: Option<bool>,
149 ) -> Self {
150 Self {
151 host: host.unwrap_or_else(|| crate::common::consts::DEFAULT_HOST.to_string()),
152 port: port.unwrap_or(crate::common::consts::DEFAULT_PORT),
153 client_id: client_id.unwrap_or(crate::common::consts::DEFAULT_CLIENT_ID),
154 account_id,
155 connection_timeout: connection_timeout.unwrap_or(300),
156 request_timeout: request_timeout.unwrap_or(60),
157 fetch_all_open_orders: fetch_all_open_orders.unwrap_or(false),
158 track_option_exercise_from_position_update: track_option_exercise_from_position_update
159 .unwrap_or(false),
160 }
161 }
162
163 #[getter]
165 fn host(&self) -> &str {
166 &self.host
167 }
168
169 #[getter]
171 fn port(&self) -> u16 {
172 self.port
173 }
174
175 #[getter]
177 fn client_id(&self) -> i32 {
178 self.client_id
179 }
180
181 #[getter]
183 fn account_id(&self) -> Option<String> {
184 self.account_id.clone()
185 }
186
187 #[getter]
189 fn connection_timeout(&self) -> u64 {
190 self.connection_timeout
191 }
192
193 #[getter]
195 fn request_timeout(&self) -> u64 {
196 self.request_timeout
197 }
198
199 #[getter]
201 fn fetch_all_open_orders(&self) -> bool {
202 self.fetch_all_open_orders
203 }
204
205 #[getter]
207 fn track_option_exercise_from_position_update(&self) -> bool {
208 self.track_option_exercise_from_position_update
209 }
210}
211
212#[pymethods]
213impl InteractiveBrokersInstrumentProviderConfig {
214 #[new]
216 #[pyo3(signature = (symbology_method=None, load_ids=None, load_contracts=None, min_expiry_days=None, max_expiry_days=None, build_options_chain=None, build_futures_chain=None, cache_validity_days=None, convert_exchange_to_mic_venue=None, symbol_to_mic_venue=None, filter_sec_types=None, cache_path=None))]
217 #[allow(clippy::too_many_arguments)]
218 fn py_new(
219 py: Python<'_>,
220 symbology_method: Option<crate::config::SymbologyMethod>,
221 load_ids: Option<std::collections::HashSet<InstrumentId>>,
222 load_contracts: Option<Py<pyo3::types::PyList>>,
223 min_expiry_days: Option<u32>,
224 max_expiry_days: Option<u32>,
225 build_options_chain: Option<bool>,
226 build_futures_chain: Option<bool>,
227 cache_validity_days: Option<u32>,
228 convert_exchange_to_mic_venue: Option<bool>,
229 symbol_to_mic_venue: Option<std::collections::HashMap<String, String>>,
230 filter_sec_types: Option<std::collections::HashSet<String>>,
231 cache_path: Option<String>,
232 ) -> PyResult<Self> {
233 Ok(Self {
234 symbology_method: symbology_method.unwrap_or_default(),
235 load_ids: load_ids.unwrap_or_default(),
236 load_contracts: if let Some(c) = load_contracts {
237 crate::python::conversion::py_list_to_json_values(c.bind(py))?
238 } else {
239 Vec::new()
240 },
241 min_expiry_days,
242 max_expiry_days,
243 build_options_chain,
244 build_futures_chain,
245 cache_validity_days,
246 convert_exchange_to_mic_venue: convert_exchange_to_mic_venue.unwrap_or(false),
247 symbol_to_mic_venue: symbol_to_mic_venue.unwrap_or_default(),
248 filter_sec_types: filter_sec_types.unwrap_or_default(),
249 cache_path,
250 })
251 }
252
253 #[getter]
255 fn symbology_method(&self) -> crate::config::SymbologyMethod {
256 self.symbology_method
257 }
258
259 #[getter]
261 fn load_ids(&self) -> std::collections::HashSet<InstrumentId> {
262 self.load_ids.clone()
263 }
264
265 #[getter]
267 fn load_contracts(&self, py: Python<'_>) -> PyResult<Py<pyo3::types::PyList>> {
268 let json_mod = py.import("json")?;
269 let list = pyo3::types::PyList::empty(py);
270
271 for value in &self.load_contracts {
272 let json_str = value.to_string();
273 let dict = json_mod.call_method1("loads", (json_str,))?;
274 list.append(dict)?;
275 }
276 Ok(list.unbind())
277 }
278
279 #[getter]
281 fn min_expiry_days(&self) -> Option<u32> {
282 self.min_expiry_days
283 }
284
285 #[getter]
287 fn max_expiry_days(&self) -> Option<u32> {
288 self.max_expiry_days
289 }
290
291 #[getter]
293 fn build_options_chain(&self) -> Option<bool> {
294 self.build_options_chain
295 }
296
297 #[getter]
299 fn build_futures_chain(&self) -> Option<bool> {
300 self.build_futures_chain
301 }
302
303 #[getter]
305 fn cache_validity_days(&self) -> Option<u32> {
306 self.cache_validity_days
307 }
308
309 #[getter]
311 fn convert_exchange_to_mic_venue(&self) -> bool {
312 self.convert_exchange_to_mic_venue
313 }
314
315 #[getter]
317 fn symbol_to_mic_venue(&self) -> std::collections::HashMap<String, String> {
318 self.symbol_to_mic_venue.clone()
319 }
320
321 #[getter]
323 fn filter_sec_types(&self) -> Vec<String> {
324 self.filter_sec_types.iter().cloned().collect()
325 }
326
327 #[getter]
329 fn cache_path(&self) -> Option<String> {
330 self.cache_path.clone()
331 }
332
333 #[setter]
335 fn set_cache_path(&mut self, cache_path: Option<String>) {
336 self.cache_path = cache_path;
337 }
338}
339
340#[pymethods]
341impl DockerizedIBGatewayConfig {
342 #[new]
344 #[pyo3(signature = (username=None, password=None, trading_mode=None, read_only_api=None, timeout=None, container_image=None, vnc_port=None))]
345 fn py_new(
346 username: Option<String>,
347 password: Option<String>,
348 trading_mode: Option<TradingMode>,
349 read_only_api: Option<bool>,
350 timeout: Option<u64>,
351 container_image: Option<String>,
352 vnc_port: Option<u16>,
353 ) -> Self {
354 Self {
355 username,
356 password,
357 trading_mode: trading_mode.unwrap_or_default(),
358 read_only_api: read_only_api.unwrap_or(true),
359 timeout: timeout.unwrap_or(300),
360 container_image: container_image
361 .unwrap_or_else(|| "ghcr.io/gnzsnz/ib-gateway:stable".to_string()),
362 vnc_port,
363 }
364 }
365
366 #[getter]
368 fn username(&self) -> Option<String> {
369 self.username.clone()
370 }
371
372 #[getter]
374 fn password(&self) -> Option<String> {
375 self.password.as_ref().map(|_| "********".to_string())
376 }
377
378 #[getter]
380 fn trading_mode(&self) -> TradingMode {
381 self.trading_mode
382 }
383
384 #[getter]
386 fn read_only_api(&self) -> bool {
387 self.read_only_api
388 }
389
390 #[getter]
392 fn timeout(&self) -> u64 {
393 self.timeout
394 }
395
396 #[getter]
398 fn container_image(&self) -> &str {
399 &self.container_image
400 }
401
402 #[getter]
404 fn vnc_port(&self) -> Option<u16> {
405 self.vnc_port
406 }
407}