Skip to main content

ibapi/
lib.rs

1//! [![github]](https://github.com/wboayue/rust-ibapi) [![crates-io]](https://crates.io/crates/ibapi) [![license]](https://opensource.org/licenses/MIT)
2//!
3//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
4//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
5//! [license]: https://img.shields.io/badge/License-MIT-blue.svg?style=for-the-badge&labelColor=555555
6//!
7//! <br>
8//!
9//! A comprehensive Rust implementation of the Interactive Brokers TWS API, providing a robust and
10//! user-friendly interface for TWS and IB Gateway. Designed with simplicity in mind, it integrates smoothly into trading systems.
11//!
12//! **API Documentation:**
13//! * [TWS API Reference](https://interactivebrokers.github.io/tws-api/introduction.html) - Detailed technical documentation
14//! * [IBKR Campus](https://ibkrcampus.com/ibkr-api-page/trader-workstation-api/) - IB's official learning platform
15//!
16//! This fully featured API enables the retrieval of account information, access to real-time and historical market data, order management,
17//! market scanning, and access to news and Wall Street Horizons (WSH) event data. Future updates will focus on bug fixes,
18//! maintaining parity with the official API, and enhancing usability.
19//!
20//! For an overview of API usage, refer to the [README](https://github.com/wboayue/rust-ibapi/blob/main/README.md).
21
22#![warn(missing_docs)]
23// Allow octal-looking escapes in string literals (used in test data)
24#![allow(clippy::octal_escapes)]
25#![allow(clippy::bool_assert_comparison)]
26#![allow(clippy::useless_format)]
27#![allow(clippy::uninlined_format_args)]
28#![allow(clippy::assertions_on_constants)]
29
30// Feature guards
31#[cfg(not(any(feature = "sync", feature = "async")))]
32compile_error!(
33    "You must enable at least one of the 'sync' or 'async' features to use this crate.\n\
34     The 'async' feature is enabled by default; if you disabled default features, be sure to\n\
35     opt back into either API:\n\
36         ibapi = { version = \"2.0\", default-features = false, features = [\"sync\"] }\n\
37         ibapi = { version = \"2.0\", default-features = false, features = [\"async\"] }\n\
38     You may also enable both to access the synchronous API under `client::blocking`."
39);
40
41/// Describes items present in an account.
42pub mod accounts;
43
44/// TWS API Client.
45///
46/// The Client establishes the connection to TWS or the Gateway.
47/// It manages the routing of messages between TWS and the application.
48pub mod client;
49
50pub(crate) mod transport;
51
52/// Connection management
53pub(crate) mod connection;
54
55/// Callback for handling unsolicited messages during connection setup.
56///
57/// When TWS sends messages like `OpenOrder` or `OrderStatus` during the connection
58/// handshake, this callback is invoked to allow the application to process them
59/// instead of discarding them.
60///
61/// # Example
62///
63/// ```ignore
64/// use ibapi::{Client, StartupMessageCallback};
65/// use ibapi::messages::IncomingMessages;
66/// use std::sync::{Arc, Mutex};
67///
68/// #[tokio::main]
69/// async fn main() {
70///     let orders = Arc::new(Mutex::new(Vec::new()));
71///     let orders_clone = orders.clone();
72///
73///     let callback: StartupMessageCallback = Box::new(move |msg| {
74///         match msg.message_type() {
75///             IncomingMessages::OpenOrder | IncomingMessages::OrderStatus => {
76///                 orders_clone.lock().unwrap().push(msg);
77///             }
78///             _ => {}
79///         }
80///     });
81///
82///     let client = Client::connect_with_callback("127.0.0.1:4002", 100, Some(callback))
83///         .await
84///         .expect("connection failed");
85///
86///     println!("Received {} startup orders", orders.lock().unwrap().len());
87/// }
88/// ```
89pub use connection::ConnectionOptions;
90pub use connection::StartupMessageCallback;
91
92/// Common utilities shared across modules
93pub(crate) mod common;
94
95pub use common::timezone::register_timezone_alias;
96
97/// Display groups subscription support
98pub mod display_groups;
99
100/// Subscription types for streaming data
101pub mod subscriptions;
102
103/// A [Contract](crate::contracts::Contract) object represents trading instruments such as a stocks, futures or options.
104///
105/// Every time a new request that requires a contract (i.e. market data, order placing, etc.) is sent to the API, the system will try to match the provided contract object with a single candidate. If there is more than one contract matching the same description, the API will return an error notifying you there is an ambiguity. In these cases the API needs further information to narrow down the list of contracts matching the provided description to a single element.
106pub mod contracts;
107// Describes primary data structures used by the model.
108pub mod errors;
109/// APIs for retrieving market data
110pub mod market_data;
111pub mod messages;
112/// APIs for retrieving news data including articles, bulletins, and providers
113pub mod news;
114/// Data types for building and placing orders.
115pub mod orders;
116/// APIs for working with the market scanner.
117pub mod scanner;
118/// APIs for working with Wall Street Horizon: Earnings Calendar & Event Data.
119pub mod wsh;
120
121/// Server interaction tracing for debugging and monitoring
122pub mod trace;
123
124/// A prelude module for convenient importing of commonly used types.
125pub mod prelude;
126
127/// Protocol version checking and constants for TWS API features.
128pub mod protocol;
129
130/// Generated protobuf message types for the TWS API wire protocol.
131#[cfg(feature = "proto")]
132pub mod proto;
133
134mod server_versions;
135
136#[doc(inline)]
137pub use errors::Error;
138
139#[doc(inline)]
140pub use client::Client;
141use std::sync::LazyLock;
142use time::{
143    format_description::{self, BorrowedFormatItem},
144    Date,
145};
146
147#[cfg(test)]
148pub(crate) mod stubs;
149
150#[cfg(test)]
151pub(crate) mod tests;
152
153#[cfg(test)]
154pub(crate) mod testdata;
155
156// ToField
157
158pub(crate) trait ToField {
159    fn to_field(&self) -> String;
160}
161
162impl ToField for bool {
163    fn to_field(&self) -> String {
164        if *self {
165            String::from("1")
166        } else {
167            String::from("0")
168        }
169    }
170}
171
172impl ToField for String {
173    fn to_field(&self) -> String {
174        self.clone()
175    }
176}
177
178impl ToField for Option<String> {
179    fn to_field(&self) -> String {
180        encode_option_field(self)
181    }
182}
183
184impl ToField for &str {
185    fn to_field(&self) -> String {
186        <&str>::clone(self).to_string()
187    }
188}
189
190impl ToField for Option<&str> {
191    fn to_field(&self) -> String {
192        encode_option_field(self)
193    }
194}
195
196impl ToField for usize {
197    fn to_field(&self) -> String {
198        self.to_string()
199    }
200}
201
202impl ToField for i32 {
203    fn to_field(&self) -> String {
204        self.to_string()
205    }
206}
207
208impl ToField for Option<i32> {
209    fn to_field(&self) -> String {
210        encode_option_field(self)
211    }
212}
213
214impl ToField for f64 {
215    fn to_field(&self) -> String {
216        self.to_string()
217    }
218}
219
220impl ToField for Option<f64> {
221    fn to_field(&self) -> String {
222        encode_option_field(self)
223    }
224}
225
226fn date_format() -> Vec<BorrowedFormatItem<'static>> {
227    format_description::parse("[year][month][day]").unwrap()
228}
229
230static DATE_FORMAT: LazyLock<Vec<BorrowedFormatItem<'static>>> = LazyLock::new(date_format);
231
232impl ToField for Date {
233    fn to_field(&self) -> String {
234        self.format(&DATE_FORMAT).unwrap()
235    }
236}
237
238impl ToField for Option<Date> {
239    fn to_field(&self) -> String {
240        encode_option_field(self)
241    }
242}
243
244fn encode_option_field<T: ToField>(val: &Option<T>) -> String {
245    match val {
246        Some(val) => val.to_field(),
247        None => String::from(""),
248    }
249}
250
251// max attempts to retry failed tws requests
252const MAX_RETRIES: i32 = 5;