1use std::sync::Arc;
19
20use ibapi::contracts::{
21 Contract, Currency as IBCurrency, Exchange as IBExchange, SecurityType, Symbol,
22};
23use nautilus_common::{clients::DataClient, live::get_runtime};
24use nautilus_core::python::to_pyruntime_err;
25use nautilus_model::{
26 data::BarType,
27 identifiers::{ClientId, InstrumentId, Venue},
28 instruments::{Instrument, InstrumentAny},
29 python::instruments::instrument_any_to_pyobject,
30};
31use pyo3::{
32 IntoPyObjectExt,
33 prelude::*,
34 types::{PyDict, PyList},
35};
36
37use crate::{
38 data::InteractiveBrokersDataClient,
39 python::conversion::{contract_details_to_pyobject, py_list_to_contracts, py_to_contract},
40};
41
42#[cfg(feature = "python")]
43#[pymethods]
44impl InteractiveBrokersDataClient {
45 #[new]
46 #[pyo3(signature = (_msgbus, _cache, _clock, instrument_provider, config))]
47 fn py_new(
48 _msgbus: Py<PyAny>,
49 _cache: Py<PyAny>,
50 _clock: Py<PyAny>,
51 instrument_provider: crate::providers::instruments::InteractiveBrokersInstrumentProvider,
52 config: crate::config::InteractiveBrokersDataClientConfig,
53 ) -> PyResult<Self> {
54 Self::new_for_python(config, instrument_provider).map_err(to_pyruntime_err)
55 }
56
57 #[pyo3(name = "set_event_callback")]
58 fn py_set_event_callback(&self, callback: Py<PyAny>) {
59 self.register_python_event_callback(callback);
60 }
61
62 #[getter]
64 pub fn client_id(&self) -> ClientId {
65 DataClient::client_id(self)
66 }
67
68 #[getter]
70 pub fn is_connected(&self) -> bool {
71 DataClient::is_connected(self)
72 }
73
74 #[getter]
76 pub fn is_disconnected(&self) -> bool {
77 DataClient::is_disconnected(self)
78 }
79
80 #[pyo3(name = "connect")]
81 fn py_connect(&mut self) -> PyResult<()> {
82 get_runtime()
83 .block_on(DataClient::connect(self))
84 .map_err(to_pyruntime_err)
85 }
86
87 #[pyo3(name = "disconnect")]
88 fn py_disconnect(&mut self) -> PyResult<()> {
89 get_runtime()
90 .block_on(DataClient::disconnect(self))
91 .map_err(to_pyruntime_err)
92 }
93
94 #[getter("get_instrument_provider")]
100 pub fn get_instrument_provider(
101 &self,
102 ) -> PyResult<crate::providers::instruments::InteractiveBrokersInstrumentProvider> {
103 Err(to_pyruntime_err(
107 "instrument_provider should be accessed through the data client's methods that use it internally",
108 ))
109 }
110
111 #[pyo3(name = "batch_load")]
127 fn py_batch_load<'py>(
128 &self,
129 py: Python<'py>,
130 instrument_ids: Vec<InstrumentId>,
131 ) -> PyResult<Bound<'py, PyAny>> {
132 let provider = self.instrument_provider();
133 let ib_client_ref = self.get_ib_client().map(Arc::clone);
134
135 pyo3_async_runtimes::tokio::future_into_py(py, async move {
136 let client = ib_client_ref
137 .ok_or_else(|| anyhow::anyhow!("IB client not connected. Call connect() first"))
138 .map_err(to_pyruntime_err)?;
139
140 provider
141 .batch_load(&client, instrument_ids, None)
142 .await
143 .map_err(to_pyruntime_err)
144 })
145 }
146
147 #[pyo3(signature = (underlying_symbol, exchange=None, currency=None, expiry_min=None, expiry_max=None))]
167 fn py_fetch_option_chain_by_range<'py>(
168 &self,
169 py: Python<'py>,
170 underlying_symbol: String,
171 exchange: Option<String>,
172 currency: Option<String>,
173 expiry_min: Option<String>,
174 expiry_max: Option<String>,
175 ) -> PyResult<Bound<'py, PyAny>> {
176 let provider = self.instrument_provider();
177 let ib_client_ref = self.get_ib_client().map(Arc::clone);
178
179 pyo3_async_runtimes::tokio::future_into_py(py, async move {
180 let client = ib_client_ref
181 .ok_or_else(|| anyhow::anyhow!("IB client not connected. Call connect() first"))
182 .map_err(to_pyruntime_err)?;
183
184 let underlying = Contract {
185 contract_id: 0,
186 symbol: Symbol::from(underlying_symbol.clone()),
187 security_type: SecurityType::Stock,
188 last_trade_date_or_contract_month: String::new(),
189 strike: 0.0,
190 right: String::new(),
191 multiplier: String::new(),
192 exchange: IBExchange::from(exchange.as_deref().unwrap_or("SMART")),
193 currency: IBCurrency::from(currency.as_deref().unwrap_or("USD")),
194 local_symbol: String::new(),
195 primary_exchange: IBExchange::default(),
196 trading_class: String::new(),
197 include_expired: false,
198 security_id_type: String::new(),
199 security_id: String::new(),
200 combo_legs_description: String::new(),
201 combo_legs: Vec::new(),
202 delta_neutral_contract: None,
203 issuer_id: String::new(),
204 description: String::new(),
205 last_trade_date: None,
206 };
207
208 provider
209 .fetch_option_chain_by_range(
210 &client,
211 &underlying,
212 expiry_min.as_deref(),
213 expiry_max.as_deref(),
214 )
215 .await
216 .map_err(to_pyruntime_err)
217 })
218 }
219
220 #[pyo3(signature = (contract, expiry_min=None, expiry_max=None))]
225 #[allow(clippy::needless_pass_by_value)]
226 fn py_fetch_option_chain_by_range_for_contract<'py>(
227 &self,
228 py: Python<'py>,
229 contract: Py<PyAny>,
230 expiry_min: Option<String>,
231 expiry_max: Option<String>,
232 ) -> PyResult<Bound<'py, PyAny>> {
233 let provider = self.instrument_provider();
234 let ib_client_ref = self.get_ib_client().map(Arc::clone);
235 let rust_contract = py_to_contract(contract.bind(py))?;
236
237 pyo3_async_runtimes::tokio::future_into_py(py, async move {
238 let client = ib_client_ref
239 .ok_or_else(|| anyhow::anyhow!("IB client not connected. Call connect() first"))
240 .map_err(to_pyruntime_err)?;
241
242 provider
243 .fetch_option_chain_by_range(
244 &client,
245 &rust_contract,
246 expiry_min.as_deref(),
247 expiry_max.as_deref(),
248 )
249 .await
250 .map_err(to_pyruntime_err)
251 })
252 }
253
254 #[pyo3(signature = (contract))]
259 #[allow(clippy::needless_pass_by_value)]
260 fn py_get_option_chain_metadata_for_contract<'py>(
261 &self,
262 py: Python<'py>,
263 contract: Py<PyAny>,
264 ) -> PyResult<Bound<'py, PyAny>> {
265 let ib_client_ref = self.get_ib_client().map(Arc::clone);
266 let rust_contract = py_to_contract(contract.bind(py))?;
267
268 pyo3_async_runtimes::tokio::future_into_py(py, async move {
269 let client = ib_client_ref
270 .ok_or_else(|| anyhow::anyhow!("IB client not connected. Call connect() first"))
271 .map_err(to_pyruntime_err)?;
272
273 let mut stream = client
274 .option_chain(
275 rust_contract.symbol.as_str(),
276 rust_contract.exchange.as_str(),
277 rust_contract.security_type.clone(),
278 rust_contract.contract_id,
279 )
280 .await
281 .map_err(to_pyruntime_err)?;
282
283 let mut chains = Vec::new();
284
285 while let Some(result) = stream.next().await {
286 match result {
287 Ok(chain) => chains.push(chain),
288 Err(e) => {
289 return Err(to_pyruntime_err(format!(
290 "Failed to receive option chain metadata: {e}",
291 )));
292 }
293 }
294 }
295
296 Python::attach(|py| -> PyResult<Py<PyAny>> {
297 let items = PyList::empty(py);
298 for chain in chains {
299 let item = PyDict::new(py);
300 item.set_item("underlying_contract_id", chain.underlying_contract_id)?;
301 item.set_item("trading_class", chain.trading_class)?;
302 item.set_item("multiplier", chain.multiplier)?;
303 item.set_item("exchange", chain.exchange)?;
304 item.set_item("expirations", chain.expirations)?;
305 item.set_item("strikes", chain.strikes)?;
306 items.append(item)?;
307 }
308 items.into_py_any(py)
309 })
310 .map_err(to_pyruntime_err)
311 })
312 }
313
314 #[pyo3(signature = (contract))]
319 #[allow(clippy::needless_pass_by_value)]
320 fn py_get_contract_details_for_contract<'py>(
321 &self,
322 py: Python<'py>,
323 contract: Py<PyAny>,
324 ) -> PyResult<Bound<'py, PyAny>> {
325 let ib_client_ref = self.get_ib_client().map(Arc::clone);
326 let rust_contract = py_to_contract(contract.bind(py))?;
327
328 pyo3_async_runtimes::tokio::future_into_py(py, async move {
329 let client = ib_client_ref
330 .ok_or_else(|| anyhow::anyhow!("IB client not connected. Call connect() first"))
331 .map_err(to_pyruntime_err)?;
332
333 let details = client
334 .contract_details(&rust_contract)
335 .await
336 .map_err(to_pyruntime_err)?;
337
338 Python::attach(|py| -> PyResult<Py<PyAny>> {
339 let items = PyList::empty(py);
340 for detail in details {
341 items.append(contract_details_to_pyobject(py, &detail)?)?;
342 }
343 items.into_py_any(py)
344 })
345 .map_err(to_pyruntime_err)
346 })
347 }
348
349 #[pyo3(signature = (contract))]
353 #[allow(clippy::needless_pass_by_value)]
354 fn py_debug_resolve_instrument<'py>(
355 &self,
356 py: Python<'py>,
357 contract: Py<PyAny>,
358 ) -> PyResult<Bound<'py, PyAny>> {
359 let provider = self.instrument_provider().clone();
360 let ib_client_ref = self.get_ib_client().map(Arc::clone);
361 let rust_contract = py_to_contract(contract.bind(py))?;
362
363 pyo3_async_runtimes::tokio::future_into_py(py, async move {
364 let client = ib_client_ref
365 .ok_or_else(|| anyhow::anyhow!("IB client not connected. Call connect() first"))
366 .map_err(to_pyruntime_err)?;
367
368 let result = provider
369 .get_instrument(&client, &rust_contract)
370 .await
371 .map_err(to_pyruntime_err)?;
372
373 Python::attach(|py| -> PyResult<Py<PyAny>> {
374 let dict = PyDict::new(py);
375
376 if let Some(instrument) = result {
377 let kind = match &instrument {
378 InstrumentAny::Betting(_) => "Betting",
379 InstrumentAny::BinaryOption(_) => "BinaryOption",
380 InstrumentAny::Cfd(_) => "Cfd",
381 InstrumentAny::Commodity(_) => "Commodity",
382 InstrumentAny::CryptoFuture(_) => "CryptoFuture",
383 InstrumentAny::CryptoOption(_) => "CryptoOption",
384 InstrumentAny::CryptoPerpetual(_) => "CryptoPerpetual",
385 InstrumentAny::CurrencyPair(_) => "CurrencyPair",
386 InstrumentAny::Equity(_) => "Equity",
387 InstrumentAny::FuturesContract(_) => "FuturesContract",
388 InstrumentAny::FuturesSpread(_) => "FuturesSpread",
389 InstrumentAny::IndexInstrument(_) => "IndexInstrument",
390 InstrumentAny::OptionContract(_) => "OptionContract",
391 InstrumentAny::OptionSpread(_) => "OptionSpread",
392 InstrumentAny::PerpetualContract(_) => "PerpetualContract",
393 InstrumentAny::TokenizedAsset(_) => "TokenizedAsset",
394 };
395 dict.set_item("kind", kind)?;
396 dict.set_item("instrument_id", instrument.id().to_string())?;
397 } else {
398 dict.set_item("kind", py.None())?;
399 dict.set_item("instrument_id", py.None())?;
400 }
401 dict.into_py_any(py)
402 })
403 .map_err(to_pyruntime_err)
404 })
405 }
406
407 #[pyo3(signature = (symbol, exchange=None, currency=None, min_expiry_days=None, max_expiry_days=None))]
425 fn py_fetch_futures_chain<'py>(
426 &self,
427 py: Python<'py>,
428 symbol: String,
429 exchange: Option<String>,
430 currency: Option<String>,
431 min_expiry_days: Option<u32>,
432 max_expiry_days: Option<u32>,
433 ) -> PyResult<Bound<'py, PyAny>> {
434 let provider = self.instrument_provider();
435 let ib_client_ref = self.get_ib_client().map(Arc::clone);
436
437 pyo3_async_runtimes::tokio::future_into_py(py, async move {
438 let client = ib_client_ref
439 .ok_or_else(|| anyhow::anyhow!("IB client not connected. Call connect() first"))
440 .map_err(to_pyruntime_err)?;
441
442 provider
443 .fetch_futures_chain(
444 &client,
445 &symbol,
446 exchange.as_deref().unwrap_or(""),
447 currency.as_deref().unwrap_or("USD"),
448 min_expiry_days,
449 max_expiry_days,
450 )
451 .await
452 .map_err(to_pyruntime_err)
453 })
454 }
455
456 #[pyo3(name = "get_instrument")]
472 #[allow(clippy::needless_pass_by_value)]
473 #[allow(deprecated)]
474 fn py_get_instrument<'py>(
475 &self,
476 py: Python<'py>,
477 contract: Py<PyAny>,
478 ) -> PyResult<Bound<'py, PyAny>> {
479 let provider = self.instrument_provider().clone();
480 let ib_client_ref = self.get_ib_client().map(Arc::clone);
481 let rust_contract = py_to_contract(contract.bind(py))?;
483
484 pyo3_async_runtimes::tokio::future_into_py(py, async move {
485 let client = ib_client_ref
486 .ok_or_else(|| anyhow::anyhow!("IB client not connected. Call connect() first"))
487 .map_err(to_pyruntime_err)?;
488
489 match provider
490 .get_instrument(&client, &rust_contract)
491 .await
492 .map_err(to_pyruntime_err)?
493 {
494 Some(instrument) => Python::attach(|gil| {
495 instrument_any_to_pyobject(gil, instrument).map_err(to_pyruntime_err)
496 }),
497 None => Python::attach(|gil| Ok(gil.None())),
498 }
499 })
500 }
501
502 #[pyo3(name = "load_async")]
513 fn py_load_async<'py>(
514 &self,
515 py: Python<'py>,
516 instrument_id: InstrumentId,
517 filters: Option<std::collections::HashMap<String, String>>,
518 ) -> PyResult<Bound<'py, PyAny>> {
519 let provider = self.instrument_provider();
520 let ib_client_ref = self.get_ib_client().map(Arc::clone);
521
522 pyo3_async_runtimes::tokio::future_into_py(py, async move {
523 let client = ib_client_ref
524 .ok_or_else(|| anyhow::anyhow!("IB client not connected. Call connect() first"))
525 .map_err(to_pyruntime_err)?;
526
527 provider
528 .load_async(&client, instrument_id, filters)
529 .await
530 .map_err(to_pyruntime_err)
531 })
532 }
533
534 #[pyo3(name = "load_with_return_async")]
549 fn py_load_with_return_async<'py>(
550 &self,
551 py: Python<'py>,
552 instrument_id: InstrumentId,
553 filters: Option<std::collections::HashMap<String, String>>,
554 ) -> PyResult<Bound<'py, PyAny>> {
555 let provider = self.instrument_provider();
556 let ib_client_ref = self.get_ib_client().map(Arc::clone);
557
558 pyo3_async_runtimes::tokio::future_into_py(py, async move {
559 let client = ib_client_ref
560 .ok_or_else(|| anyhow::anyhow!("IB client not connected. Call connect() first"))
561 .map_err(to_pyruntime_err)?;
562
563 provider
564 .load_with_return_async(&client, instrument_id, filters)
565 .await
566 .map_err(to_pyruntime_err)
567 })
568 }
569
570 #[pyo3(name = "load_ids_async")]
581 fn py_load_ids_async<'py>(
582 &self,
583 py: Python<'py>,
584 instrument_ids: Vec<InstrumentId>,
585 filters: Option<std::collections::HashMap<String, String>>,
586 ) -> PyResult<Bound<'py, PyAny>> {
587 let provider = self.instrument_provider();
588 let ib_client_ref = self.get_ib_client().map(Arc::clone);
589
590 pyo3_async_runtimes::tokio::future_into_py(py, async move {
591 let client = ib_client_ref
592 .ok_or_else(|| anyhow::anyhow!("IB client not connected. Call connect() first"))
593 .map_err(to_pyruntime_err)?;
594
595 provider
596 .load_ids_async(&client, instrument_ids, filters)
597 .await
598 .map_err(to_pyruntime_err)
599 })
600 }
601
602 #[pyo3(name = "load_ids_with_return_async")]
617 fn py_load_ids_with_return_async<'py>(
618 &self,
619 py: Python<'py>,
620 instrument_ids: Vec<InstrumentId>,
621 filters: Option<std::collections::HashMap<String, String>>,
622 ) -> PyResult<Bound<'py, PyAny>> {
623 let provider = self.instrument_provider();
624 let ib_client_ref = self.get_ib_client().map(Arc::clone);
625
626 pyo3_async_runtimes::tokio::future_into_py(py, async move {
627 let client = ib_client_ref
628 .ok_or_else(|| anyhow::anyhow!("IB client not connected. Call connect() first"))
629 .map_err(to_pyruntime_err)?;
630
631 provider
632 .load_ids_with_return_async(&client, instrument_ids, filters)
633 .await
634 .map_err(to_pyruntime_err)
635 })
636 }
637
638 #[pyo3(name = "get_instrument_id_by_contract_id")]
648 fn py_get_instrument_id_by_contract_id(&self, contract_id: i32) -> Option<InstrumentId> {
649 self.instrument_provider()
650 .get_instrument_id_by_contract_id(contract_id)
651 }
652
653 #[pyo3(name = "instrument_id_to_ib_contract_details")]
663 fn py_instrument_id_to_ib_contract_details(
664 &self,
665 instrument_id: InstrumentId,
666 ) -> Option<Py<PyAny>> {
667 let _details = self
670 .instrument_provider()
671 .instrument_id_to_ib_contract_details(&instrument_id);
672 None
674 }
675
676 #[pyo3(name = "determine_venue")]
686 #[allow(clippy::needless_pass_by_value)]
687 fn py_determine_venue(&self, py: Python<'_>, contract: Py<PyAny>) -> PyResult<String> {
688 let rust_contract = py_to_contract(contract.bind(py))?;
689 let venue = self
690 .instrument_provider()
691 .determine_venue(&rust_contract, None);
692 Ok(venue.to_string())
693 }
694
695 #[pyo3(name = "load_all_async")]
713 fn py_load_all_async<'py>(
714 &self,
715 py: Python<'py>,
716 instrument_ids: Option<Vec<InstrumentId>>,
717 contracts: Option<Py<PyAny>>,
718 force_instrument_update: bool,
719 ) -> PyResult<Bound<'py, PyAny>> {
720 let provider = self.instrument_provider();
721 let ib_client_ref = self.get_ib_client().map(Arc::clone);
722
723 let contracts_rust: Option<Vec<ibapi::contracts::Contract>> = if let Some(c) = contracts {
725 Some(py_list_to_contracts(c.bind(py))?)
726 } else {
727 None
728 };
729
730 pyo3_async_runtimes::tokio::future_into_py(py, async move {
731 let client = ib_client_ref
732 .ok_or_else(|| anyhow::anyhow!("IB client not connected. Call connect() first"))
733 .map_err(to_pyruntime_err)?;
734
735 provider
736 .load_all_async(
737 &client,
738 instrument_ids,
739 contracts_rust,
740 force_instrument_update,
741 )
742 .await
743 .map_err(to_pyruntime_err)
744 })
745 }
746
747 #[pyo3(name = "fetch_spread_instrument")]
764 fn py_fetch_spread_instrument<'py>(
765 &self,
766 py: Python<'py>,
767 spread_instrument_id: InstrumentId,
768 force_instrument_update: bool,
769 filters: Option<std::collections::HashMap<String, String>>,
770 ) -> PyResult<Bound<'py, PyAny>> {
771 let provider = self.instrument_provider();
772 let ib_client_ref = self.get_ib_client().map(Arc::clone);
773
774 pyo3_async_runtimes::tokio::future_into_py(py, async move {
775 let client = ib_client_ref
776 .ok_or_else(|| anyhow::anyhow!("IB client not connected. Call connect() first"))
777 .map_err(to_pyruntime_err)?;
778
779 provider
780 .fetch_spread_instrument(
781 &client,
782 spread_instrument_id,
783 force_instrument_update,
784 filters,
785 )
786 .await
787 .map_err(to_pyruntime_err)
788 })
789 }
790
791 #[pyo3(name = "subscribe_quotes")]
802 fn py_subscribe_quotes(
803 &mut self,
804 instrument_id: InstrumentId,
805 params: Option<std::collections::HashMap<String, String>>,
806 ) -> PyResult<()> {
807 self.subscribe_quotes_for_python(instrument_id, params)
808 .map_err(to_pyruntime_err)
809 }
810
811 #[pyo3(name = "subscribe_index_prices")]
821 fn py_subscribe_index_prices(&mut self, instrument_id: InstrumentId) -> PyResult<()> {
822 self.subscribe_index_prices_for_python(instrument_id)
823 .map_err(to_pyruntime_err)
824 }
825
826 #[pyo3(name = "subscribe_option_greeks")]
836 fn py_subscribe_option_greeks(&mut self, instrument_id: InstrumentId) -> PyResult<()> {
837 self.subscribe_option_greeks_for_python(instrument_id)
838 .map_err(to_pyruntime_err)
839 }
840
841 #[pyo3(name = "subscribe_trades")]
851 fn py_subscribe_trades(&mut self, instrument_id: InstrumentId) -> PyResult<()> {
852 self.subscribe_trades_for_python(instrument_id)
853 .map_err(to_pyruntime_err)
854 }
855
856 #[pyo3(name = "subscribe_bars", signature = (bar_type, params=None))]
866 fn py_subscribe_bars(
867 &mut self,
868 bar_type: BarType,
869 params: Option<std::collections::HashMap<String, String>>,
870 ) -> PyResult<()> {
871 self.subscribe_bars_for_python(bar_type, params)
872 .map_err(to_pyruntime_err)
873 }
874
875 #[pyo3(name = "subscribe_book_deltas")]
887 fn py_subscribe_book_deltas(
888 &mut self,
889 instrument_id: InstrumentId,
890 depth: Option<u16>,
891 params: Option<std::collections::HashMap<String, String>>,
892 ) -> PyResult<()> {
893 self.subscribe_book_deltas_for_python(instrument_id, depth, params)
894 .map_err(to_pyruntime_err)
895 }
896
897 #[pyo3(name = "unsubscribe_quotes")]
907 fn py_unsubscribe_quotes(&mut self, instrument_id: InstrumentId) -> PyResult<()> {
908 self.unsubscribe_quotes_for_python(instrument_id)
909 .map_err(to_pyruntime_err)
910 }
911
912 #[pyo3(name = "unsubscribe_index_prices")]
922 fn py_unsubscribe_index_prices(&mut self, instrument_id: InstrumentId) -> PyResult<()> {
923 self.unsubscribe_index_prices_for_python(instrument_id)
924 .map_err(to_pyruntime_err)
925 }
926
927 #[pyo3(name = "unsubscribe_option_greeks")]
937 fn py_unsubscribe_option_greeks(&mut self, instrument_id: InstrumentId) -> PyResult<()> {
938 self.unsubscribe_option_greeks_for_python(instrument_id)
939 .map_err(to_pyruntime_err)
940 }
941
942 #[pyo3(name = "unsubscribe_trades")]
952 fn py_unsubscribe_trades(&mut self, instrument_id: InstrumentId) -> PyResult<()> {
953 self.unsubscribe_trades_for_python(instrument_id)
954 .map_err(to_pyruntime_err)
955 }
956
957 #[pyo3(name = "unsubscribe_bars")]
967 fn py_unsubscribe_bars(&mut self, bar_type: BarType) -> PyResult<()> {
968 self.unsubscribe_bars_for_python(bar_type)
969 .map_err(to_pyruntime_err)
970 }
971
972 #[pyo3(name = "unsubscribe_book_deltas")]
982 fn py_unsubscribe_book_deltas(&mut self, instrument_id: InstrumentId) -> PyResult<()> {
983 self.unsubscribe_book_deltas_for_python(instrument_id)
984 .map_err(to_pyruntime_err)
985 }
986
987 #[pyo3(name = "request_quotes", signature = (instrument_id, limit=None, start=None, end=None, request_id=None))]
1000 fn py_request_quotes(
1001 &self,
1002 instrument_id: InstrumentId,
1003 limit: Option<u64>,
1004 start: Option<u64>,
1005 end: Option<u64>,
1006 request_id: Option<String>,
1007 ) -> PyResult<()> {
1008 self.request_quotes_for_python(instrument_id, limit, start, end, request_id)
1009 .map_err(to_pyruntime_err)
1010 }
1011
1012 #[pyo3(name = "request_trades", signature = (instrument_id, limit=None, start=None, end=None, request_id=None))]
1025 fn py_request_trades(
1026 &self,
1027 instrument_id: InstrumentId,
1028 limit: Option<u64>,
1029 start: Option<u64>,
1030 end: Option<u64>,
1031 request_id: Option<String>,
1032 ) -> PyResult<()> {
1033 self.request_trades_for_python(instrument_id, limit, start, end, request_id)
1034 .map_err(to_pyruntime_err)
1035 }
1036
1037 #[pyo3(name = "request_bars", signature = (bar_type, limit=None, start=None, end=None, request_id=None))]
1050 fn py_request_bars(
1051 &self,
1052 bar_type: BarType,
1053 limit: Option<u64>,
1054 start: Option<u64>,
1055 end: Option<u64>,
1056 request_id: Option<String>,
1057 ) -> PyResult<()> {
1058 self.request_bars_for_python(bar_type, limit, start, end, request_id)
1059 .map_err(to_pyruntime_err)
1060 }
1061
1062 #[pyo3(name = "request_instrument")]
1073 fn py_request_instrument(
1074 &self,
1075 instrument_id: InstrumentId,
1076 params: Option<std::collections::HashMap<String, String>>,
1077 ) -> PyResult<()> {
1078 self.request_instrument_for_python(instrument_id, params)
1079 .map_err(to_pyruntime_err)
1080 }
1081
1082 #[pyo3(name = "request_instruments")]
1093 fn py_request_instruments(
1094 &self,
1095 venue: Option<Venue>,
1096 params: Option<std::collections::HashMap<String, String>>,
1097 ) -> PyResult<()> {
1098 self.request_instruments_for_python(venue, params)
1099 .map_err(to_pyruntime_err)
1100 }
1101}