pub struct Client { /* private fields */ }Expand description
Asynchronous TWS API Client
Implementations§
Source§impl Client
impl Client
Sourcepub async fn positions(&self) -> Result<Subscription<PositionUpdate>, Error>
pub async fn positions(&self) -> Result<Subscription<PositionUpdate>, Error>
Subscribe to streaming position updates for all accessible accounts.
The stream first replays the full position list and then sends incremental updates.
§Examples
use ibapi::Client;
use ibapi::accounts::PositionUpdate;
use ibapi::subscriptions::SubscriptionItem;
use futures::StreamExt;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let mut subscription = client.positions().await.expect("error requesting positions");
while let Some(item) = subscription.next().await {
match item {
Ok(SubscriptionItem::Data(PositionUpdate::Position(position))) => println!("{position:?}"),
Ok(SubscriptionItem::Data(PositionUpdate::PositionEnd)) => println!("initial set of positions received"),
Ok(SubscriptionItem::Notice(n)) => eprintln!("notice: {n}"),
Err(e) => eprintln!("Error: {e}"),
}
}
}Sourcepub async fn positions_multi(
&self,
account: Option<&AccountId>,
model_code: Option<&ModelCode>,
) -> Result<Subscription<PositionUpdateMulti>, Error>
pub async fn positions_multi( &self, account: Option<&AccountId>, model_code: Option<&ModelCode>, ) -> Result<Subscription<PositionUpdateMulti>, Error>
Subscribe to streaming position updates scoped by account and model code.
§Arguments
account- If an account Id is provided, only the account’s positions belonging to the specified model will be delivered.model_code- The code of the model’s positions we are interested in.
§Examples
use ibapi::Client;
use ibapi::accounts::types::AccountId;
use futures::StreamExt;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let account = AccountId("U1234567".to_string());
let mut subscription = client.positions_multi(Some(&account), None).await.expect("error requesting positions by model");
while let Some(position) = subscription.next().await {
println!("{position:?}")
}
}Sourcepub async fn family_codes(&self) -> Result<Vec<FamilyCode>, Error>
pub async fn family_codes(&self) -> Result<Vec<FamilyCode>, Error>
Fetch the account family codes registered with the broker.
§Examples
use ibapi::Client;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let codes = client.family_codes().await.expect("error requesting family codes");
println!("family codes: {codes:?}")
}Sourcepub async fn pnl(
&self,
account: &AccountId,
model_code: Option<&ModelCode>,
) -> Result<Subscription<PnL>, Error>
pub async fn pnl( &self, account: &AccountId, model_code: Option<&ModelCode>, ) -> Result<Subscription<PnL>, Error>
Subscribe to real-time daily and unrealized PnL updates for an account.
Optionally filter by model code to scope the updates.
§Arguments
account- account for which to receive PnL updatesmodel_code- specify to request PnL updates for a specific model
§Examples
use ibapi::Client;
use ibapi::accounts::types::AccountId;
use futures::StreamExt;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let account = AccountId("account id".to_string());
let mut subscription = client.pnl(&account, None).await.expect("error requesting pnl");
while let Some(pnl) = subscription.next().await {
println!("{pnl:?}")
}
}Sourcepub async fn pnl_single(
&self,
account: &AccountId,
contract_id: ContractId,
model_code: Option<&ModelCode>,
) -> Result<Subscription<PnLSingle>, Error>
pub async fn pnl_single( &self, account: &AccountId, contract_id: ContractId, model_code: Option<&ModelCode>, ) -> Result<Subscription<PnLSingle>, Error>
Subscribe to real-time daily PnL updates for a single contract.
The stream includes realized and unrealized PnL information for the requested position.
§Arguments
account- Account in which position existscontract_id- Contract ID of contract to receive daily PnL updates for.model_code- Model in which position exists
§Examples
use ibapi::Client;
use ibapi::accounts::types::{AccountId, ContractId};
use futures::StreamExt;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let account = AccountId("<account id>".to_string());
let contract_id = ContractId(1001);
let mut subscription = client.pnl_single(&account, contract_id, None).await.expect("error requesting pnl");
while let Some(pnl) = subscription.next().await {
println!("{pnl:?}")
}
}Sourcepub async fn account_summary(
&self,
group: &AccountGroup,
tags: &[&str],
) -> Result<Subscription<AccountSummaryResult>, Error>
pub async fn account_summary( &self, group: &AccountGroup, tags: &[&str], ) -> Result<Subscription<AccountSummaryResult>, Error>
Subscribe to account summary updates for a group of accounts.
§Subscription lifetime
The subscription stays open until it is dropped or cancelled. TWS first sends the requested
tags followed by AccountSummaryResult::End, then keeps pushing
AccountSummaryResult::Summary rows without another End: when values change, and
periodically, when a push can resend rows whose values did not change. Dropping the subscription cancels
the request.
§Arguments
group- Set to “All” to return account summary data for all accounts, or set to a specific Advisor Account Group name.tags- List of the desired tags.
§Examples
use ibapi::Client;
use ibapi::accounts::AccountSummaryTags;
use ibapi::accounts::types::AccountGroup;
use futures::StreamExt;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let group = AccountGroup("All".to_string());
let mut subscription = client.account_summary(&group, AccountSummaryTags::ALL).await.expect("error requesting account summary");
while let Some(summary) = subscription.next().await {
println!("{summary:?}")
}
}Sourcepub async fn account_summary_snapshots(
&self,
group: &AccountGroup,
tags: &[&str],
quiet: Duration,
) -> Result<AccountSummarySnapshots, Error>
pub async fn account_summary_snapshots( &self, group: &AccountGroup, tags: &[&str], quiet: Duration, ) -> Result<AccountSummarySnapshots, Error>
Subscribe to account summary updates as complete snapshots.
Wraps account_summary and keeps the latest value of every row, so
each AccountSummarySnapshot holds the whole account rather than only the rows TWS pushed
last. TWS sends one End marker after the initial snapshot and none after the rows it pushes
later, so the first snapshot is emitted at the first End, even when empty, and each later
one once no row has arrived for quiet. Pushes arrive when values change and periodically
(IB documents every three minutes), and a push can resend unchanged rows. A later snapshot is
emitted only when a row changed a value since the previous one. Choose quiet longer than
the gap between the rows of one push, which arrive within milliseconds of each other.
To fold the rows with your own batching instead, use AccountSummarySnapshot::apply.
Notices that arrive on the subscription are logged at warn!. For other streams that dump
then push, batch with Subscription::next_batch.
Dropping the returned stream cancels the subscription in a background task. Call
cancel before resubscribing: TWS allows two account
summary requests at a time.
§Arguments
group- Set to “All” to return account summary data for all accounts, or set to a specific Advisor Account Group name.tags- List of the desired tags.quiet- How long without a row completes a pushed update.
§Examples
use ibapi::Client;
use ibapi::accounts::AccountSummaryTags;
use ibapi::accounts::types::AccountGroup;
use std::time::Duration;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let group = AccountGroup("All".to_string());
let tags = &[AccountSummaryTags::NET_LIQUIDATION];
let mut snapshots = client
.account_summary_snapshots(&group, tags, Duration::from_secs(1))
.await
.expect("error requesting account summary");
while let Some(snapshot) = snapshots.next().await {
let snapshot = snapshot.expect("account summary error");
println!("{} rows", snapshot.len());
}
}Sourcepub async fn account_updates(
&self,
account: &AccountId,
) -> Result<Subscription<AccountUpdate>, Error>
pub async fn account_updates( &self, account: &AccountId, ) -> Result<Subscription<AccountUpdate>, Error>
Subscribe to detailed account updates for a specific account.
All account values and positions will be returned initially, and then there will only be updates when there is a change in a position, or to an account value every 3 minutes if it has changed.
TWS streams one account at a time per connection. Subscribing to the same
account again shares the stream; another account is refused until every
subscription to the first has been cancelled. Call
cancel().await before switching accounts: a
dropped subscription is released by a spawned task, so a request made right
after the drop can still be refused. To stream several accounts at once, use
account_updates_multi.
§Arguments
account- The account id (i.e. U1234567) for which the information is requested.
§Errors
Error::AccountUpdatesInUse while another account’s updates are live.
§Examples
use ibapi::Client;
use ibapi::accounts::AccountUpdate;
use ibapi::accounts::types::AccountId;
use ibapi::subscriptions::SubscriptionItem;
use futures::StreamExt;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let account = AccountId("U1234567".to_string());
let mut subscription = client.account_updates(&account).await.expect("error requesting account updates");
while let Some(item) = subscription.next().await {
match item {
Ok(SubscriptionItem::Data(update)) => {
println!("{update:?}");
if let AccountUpdate::End = update {
break;
}
}
Ok(SubscriptionItem::Notice(n)) => eprintln!("notice: {n}"),
Err(e) => eprintln!("Error: {e}"),
}
}
}Sourcepub async fn account_updates_multi(
&self,
account: Option<&AccountId>,
model_code: Option<&ModelCode>,
) -> Result<Subscription<AccountUpdateMulti>, Error>
pub async fn account_updates_multi( &self, account: Option<&AccountId>, model_code: Option<&ModelCode>, ) -> Result<Subscription<AccountUpdateMulti>, Error>
Subscribe to account updates scoped by account and model code.
Each subscription is routed by its own request id, so several accounts or models can stream at once.
§Arguments
account- Account values can be requested for a particular account.model_code- Account values can also be requested for a model.
§Examples
use ibapi::Client;
use ibapi::accounts::AccountUpdateMulti;
use ibapi::accounts::types::AccountId;
use ibapi::subscriptions::SubscriptionItem;
use futures::StreamExt;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let account = AccountId("U1234567".to_string());
let mut subscription = client.account_updates_multi(Some(&account), None).await.expect("error requesting account updates multi");
while let Some(item) = subscription.next().await {
match item {
Ok(SubscriptionItem::Data(update)) => {
println!("{update:?}");
if let AccountUpdateMulti::End = update {
break;
}
}
Ok(SubscriptionItem::Notice(n)) => eprintln!("notice: {n}"),
Err(e) => eprintln!("Error: {e}"),
}
}
}Sourcepub async fn managed_accounts(&self) -> Result<Vec<String>, Error>
pub async fn managed_accounts(&self) -> Result<Vec<String>, Error>
Fetch the list of accounts accessible to the current user.
§Examples
use ibapi::Client;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let accounts = client.managed_accounts().await.expect("error requesting managed accounts");
println!("managed accounts: {accounts:?}")
}Sourcepub async fn server_time(&self) -> Result<OffsetDateTime, Error>
pub async fn server_time(&self) -> Result<OffsetDateTime, Error>
Query the current server time reported by TWS or IB Gateway.
§Examples
use ibapi::Client;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let server_time = client.server_time().await.expect("error requesting server time");
println!("server time: {server_time:?}");
}Sourcepub async fn server_time_millis(&self) -> Result<OffsetDateTime, Error>
pub async fn server_time_millis(&self) -> Result<OffsetDateTime, Error>
Query the current server time in milliseconds reported by TWS or IB Gateway.
§Examples
use ibapi::Client;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let server_time = client.server_time_millis().await.expect("error requesting server time");
println!("server time to the millisecond: {server_time:?}");
}Sourcepub async fn soft_dollar_tiers(&self) -> Result<Vec<SoftDollarTier>, Error>
pub async fn soft_dollar_tiers(&self) -> Result<Vec<SoftDollarTier>, Error>
Request the configured soft dollar tiers available to the account.
§Examples
use ibapi::Client;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let tiers = client.soft_dollar_tiers().await.expect("request failed");
for tier in &tiers {
println!("{}: {}", tier.name, tier.display_name);
}
}Sourcepub async fn user_info(&self) -> Result<UserInfo, Error>
pub async fn user_info(&self) -> Result<UserInfo, Error>
Request white-branding identity information for the logged-in user.
§Examples
use ibapi::Client;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let info = client.user_info().await.expect("request failed");
println!("white branding id: {}", info.white_branding_id);
}Sourcepub async fn request_fa(
&self,
fa_data_type: FaDataType,
) -> Result<FaConfig, Error>
pub async fn request_fa( &self, fa_data_type: FaDataType, ) -> Result<FaConfig, Error>
Request the current Financial Advisor configuration as an XML string.
§Arguments
fa_data_type- which FA dataset to fetch.
§Examples
use ibapi::Client;
use ibapi::accounts::FaDataType;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let cfg = client.request_fa(FaDataType::Groups).await.expect("request failed");
println!("{}", cfg.xml);
}Sourcepub async fn replace_fa(
&self,
fa_data_type: FaDataType,
xml: &str,
) -> Result<ReplaceFaResult, Error>
pub async fn replace_fa( &self, fa_data_type: FaDataType, xml: &str, ) -> Result<ReplaceFaResult, Error>
Replace the Financial Advisor configuration on the server.
§Arguments
fa_data_type- which FA dataset to replace.xml- the replacement configuration as an XML string.
§Examples
use ibapi::Client;
use ibapi::accounts::FaDataType;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let result = client.replace_fa(FaDataType::Groups, "<xml/>").await.expect("request failed");
println!("{}", result.text);
}Sourcepub async fn set_server_log_level(
&self,
log_level: ServerLogLevel,
) -> Result<(), Error>
pub async fn set_server_log_level( &self, log_level: ServerLogLevel, ) -> Result<(), Error>
Set the verbosity level for server-side TWS API diagnostics.
§Examples
use ibapi::Client;
use ibapi::accounts::ServerLogLevel;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
client.set_server_log_level(ServerLogLevel::Detail).await.expect("request failed");
}Sourcepub async fn verify_request(
&self,
api_name: &str,
api_version: &str,
) -> Result<VerificationChallenge, Error>
pub async fn verify_request( &self, api_name: &str, api_version: &str, ) -> Result<VerificationChallenge, Error>
Initiate a TWS extension verification handshake.
Most users will not call this directly; it is part of the IB Linking flow.
§Examples
use ibapi::Client;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let challenge = client.verify_request("MyApp", "1.0").await.expect("request failed");
println!("{}", challenge.api_data);
}Sourcepub async fn verify_message(
&self,
api_data: &str,
) -> Result<VerificationResult, Error>
pub async fn verify_message( &self, api_data: &str, ) -> Result<VerificationResult, Error>
Continue a TWS extension verification handshake by sending the API response data.
§Examples
use ibapi::Client;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let result = client.verify_message("signed-challenge").await.expect("request failed");
if result.is_successful {
println!("verified");
} else {
eprintln!("{}", result.error_text);
}
}Source§impl Client
impl Client
Sourcepub async fn connect(address: &str, client_id: i32) -> Result<Client, Error>
pub async fn connect(address: &str, client_id: i32) -> Result<Client, Error>
Establishes a connection to TWS or Gateway with no extra configuration.
One-liner shortcut equivalent to
Client::builder().address(address).client_id(client_id).connect().await.
For tcp_no_delay, startup callbacks, or a pre-bound NoticeStream,
use Client::builder instead.
§Arguments
address- address of server. e.g. 127.0.0.1:4002client_id- id of client. e.g. 100
§Examples
use ibapi::Client;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
println!("server_version: {}", client.server_version());
println!("connection_time: {:?}", client.connection_time());
println!("next_order_id: {}", client.next_order_id());
}Sourcepub fn builder() -> ClientBuilder
pub fn builder() -> ClientBuilder
Begin a fluent connection builder.
See ClientBuilder for the configurators (address, client_id,
tcp_no_delay, startup_callback) and the two terminals
(connect, connect_with_notice_stream).
§Examples
use ibapi::Client;
let client = Client::builder()
.address("127.0.0.1:4002")
.client_id(100)
.tcp_no_delay(true)
.connect()
.await?;
drop(client);Sourcepub fn server_version(&self) -> i32
pub fn server_version(&self) -> i32
Returns the server version
Sourcepub fn connection_time(&self) -> Option<OffsetDateTime>
pub fn connection_time(&self) -> Option<OffsetDateTime>
Returns the gateway’s clock reading when the client connected, or
None if the zone is unrecognized (see time_zone)
or the reading is malformed.
Sourcepub fn time_zone(&self) -> Option<&'static Tz>
pub fn time_zone(&self) -> Option<&'static Tz>
Returns the time zone of the gateway host, from the connection handshake.
Informational: the crate does not convert any data with it. None if
the gateway sent a name that no alias or IANA zone matches (logged as a
warning at connect). Map such a name with
register_timezone_alias. See
Gateway Time Zone.
Sourcepub fn is_connected(&self) -> bool
pub fn is_connected(&self) -> bool
Returns true if the client is currently connected to TWS/IB Gateway.
This method checks if the underlying connection to TWS or IB Gateway is active. Returns false if the connection has been lost, shut down, or reset.
§Examples
use ibapi::Client;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
if client.is_connected() {
println!("Client is connected to TWS/Gateway");
} else {
println!("Client is not connected");
}
}Sourcepub async fn disconnect(&self)
pub async fn disconnect(&self)
Cleanly shuts down the message bus.
All outstanding Subscriptions see their channels
close and their next() calls return None. The background dispatch task is awaited
to completion before this returns.
Call this before dropping the final Arc<Client> if any spawned
tasks hold that Arc. Otherwise the tokio runtime will hang on
shutdown — Drop cannot perform the full async shutdown because it
is not async.
Safe to call multiple times.
§Examples
use ibapi::Client;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
// ... use client, spawn tasks holding Arc<Client> ...
client.disconnect().await;
}Sourcepub fn notice_stream(&self) -> Result<NoticeStream, Error>
pub fn notice_stream(&self) -> Result<NoticeStream, Error>
Subscribe to globally routed IB notices (notices with no request_id —
connectivity codes 1100/1101/1102, farm-status 2104/2105/2106/2107/2108,
and any other unrouted error/warning).
Each call returns a fresh, independent NoticeStream;
late subscribers do not see prior notices. The stream ends when the client shuts
down; one created after shutdown is already ended.
Per-subscription notices (codes carrying a real request_id) are not
delivered here — they reach their owning subscription as
SubscriptionItem::Notice
(via futures::StreamExt::next on the Subscription stream).
§Note on handshake-time notices
Notices emitted during the connection handshake — the typical
2104/2106/2158 farm-status burst that arrives before connect returns —
will not be observed by a NoticeStream created afterwards. Use
ClientBuilder::connect_with_notice_stream
to capture those (the pre-bound stream covers handshake AND post-connect
notices, and survives auto-reconnects).
§Examples
use ibapi::Client;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let mut stream = client.notice_stream().expect("notice subscription failed");
while let Some(notice) = stream.next().await {
if notice.is_system_message() {
println!("connectivity: {notice}");
} else if notice.is_informational() {
println!("info: {notice}");
} else {
eprintln!("error: {notice}");
}
}
}Sourcepub fn next_order_id(&self) -> i32
pub fn next_order_id(&self) -> i32
Returns the next order ID
Source§impl Client
impl Client
Sourcepub async fn subscribe_to_group_events(
&self,
group_id: i32,
) -> Result<DisplayGroupSubscription, Error>
pub async fn subscribe_to_group_events( &self, group_id: i32, ) -> Result<DisplayGroupSubscription, Error>
Subscribes to display group events for the specified group.
Display Groups are a TWS-only feature (not available in IB Gateway). They allow organizing contracts into color-coded groups in the TWS UI. When subscribed, you receive updates whenever the user changes the contract displayed in that group within TWS.
§Arguments
group_id- The ID of the group to subscribe to (1-9)
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:7497", 100).await.expect("connection failed");
let mut subscription = client.subscribe_to_group_events(1).await.expect("subscription failed");
// Update the displayed contract
subscription.update("265598@SMART").await.expect("update failed");
// Consume the subscription so display-group events surface.
while let Some(event) = subscription.next().await {
println!("group event: {event:?}");
}
}Source§impl Client
impl Client
Sourcepub async fn config(&self) -> Result<Config, Error>
pub async fn config(&self) -> Result<Config, Error>
Reads the TWS/Gateway configuration (API, precautions, orders, and lock-and-exit settings) the gateway is currently running with.
This is a read-only snapshot; fields the gateway does not report are
left as None.
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let config = client.config().await.expect("request config failed");
println!("{config:?}");
}Sourcepub fn update_config(&self) -> UpdateConfigBuilder<'_, Client>
pub fn update_config(&self) -> UpdateConfigBuilder<'_, Client>
Begins a fluent UpdateConfigBuilder to edit the TWS/Gateway
configuration. Set only the groups you want to change and terminate with
submit.
§Examples
use ibapi::prelude::*;
use ibapi::config::{OrdersConfig, OrdersSmartRouting};
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let response = client
.update_config()
.orders(OrdersConfig {
smart_routing: Some(OrdersSmartRouting {
seek_price_improvement: Some(true),
..Default::default()
}),
})
.submit()
.await
.expect("update config failed");
println!("{response:?}");
}Source§impl Client
impl Client
Sourcepub async fn contract_details(
&self,
contract: &Contract,
) -> Result<Vec<ContractDetails>, Error>
pub async fn contract_details( &self, contract: &Contract, ) -> Result<Vec<ContractDetails>, Error>
Requests contract information.
Provides all the contracts matching the contract provided. It can also be used to retrieve complete options and futures chains.
Collects every row before returning. To read rows as they arrive, stop reading early, or know the request id up front, use Client::contract_details_stream.
Waits for TWS’s end marker with no time bound. For a bound, use
contract_details_stream and
collect_to_end_within.
§Arguments
contract- The Contract used as sample to query the available contracts.
§Examples
use ibapi::Client;
use ibapi::contracts::Contract;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let contract = Contract::stock("AAPL").build();
let details = client.contract_details(&contract).await.expect("request failed");
for detail in details {
println!("Contract: {} - Exchange: {}", detail.contract.symbol, detail.contract.exchange);
}
}Sourcepub fn contract_details_stream<'a>(
&'a self,
contract: &'a Contract,
) -> ContractDetailsBuilder<'a, Self>
pub fn contract_details_stream<'a>( &'a self, contract: &'a Contract, ) -> ContractDetailsBuilder<'a, Self>
Build a contract-details request whose subscription yields one ContractDetails per matching contract.
Use this over Client::contract_details to read rows as they arrive,
stop reading early, or know the request id before anything is sent.
Dropping the subscription before the end sends TWS’s native cancel
(server 215+); rows TWS sends after that are discarded.
collect_to_end_within
collects the whole result within a time bound.
Terminal: ContractDetailsBuilder::subscribe.
§Arguments
contract- The Contract used as sample to query the available contracts.
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let contract = Contract::stock("AAPL").build();
let request = client.contract_details_stream(&contract);
let request_id = request.request_id(); // known before anything is sent
let subscription = request.subscribe().await.expect("request failed");
let mut details = subscription.filter_data().take(5);
while let Some(details) = details.next().await {
match details {
Ok(details) => println!("[{request_id}] {} on {}", details.contract.symbol, details.contract.exchange),
Err(e) => {
eprintln!("error: {e}");
break;
}
}
}
}Sourcepub async fn matching_symbols(
&self,
pattern: &str,
) -> Result<Vec<ContractDescription>, Error>
pub async fn matching_symbols( &self, pattern: &str, ) -> Result<Vec<ContractDescription>, Error>
Requests matching stock symbols.
§Arguments
pattern- Either start of ticker symbol or (for larger strings) company name.
§Retries
If the connection resets mid-request, this waits for the reconnect and sends the request again with a fresh request id, up to 3 times (4 attempts in all). Other errors are not retried. A caller pacing requests against TWS limits should count each reconnect (see the notice stream) as a possible extra request.
§Examples
use ibapi::Client;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let symbols = client.matching_symbols("AAP").await.expect("request failed");
for symbol in symbols {
println!("{} - {} ({})", symbol.contract.symbol,
symbol.contract.primary_exchange, symbol.contract.currency);
}
}Sourcepub async fn market_rule(
&self,
market_rule_id: i32,
) -> Result<MarketRule, Error>
pub async fn market_rule( &self, market_rule_id: i32, ) -> Result<MarketRule, Error>
Requests details about a given market rule.
The market rule for an instrument on a particular exchange provides details about how the minimum price increment changes with price.
§Arguments
market_rule_id- The market rule ID to query
§Examples
use ibapi::Client;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let rule = client.market_rule(26).await.expect("request failed");
for increment in rule.price_increments {
println!("Above ${}: increment ${}", increment.low_edge, increment.increment);
}
}Sourcepub async fn smart_components(
&self,
bbo_exchange: &str,
) -> Result<Vec<SmartComponent>, Error>
pub async fn smart_components( &self, bbo_exchange: &str, ) -> Result<Vec<SmartComponent>, Error>
Requests the underlying exchanges that contribute to a consolidated (BBO) feed.
Given a BBO exchange code (an opaque per-session token, e.g. "a6"),
returns the list of underlying exchanges with each entry’s bit
position, full exchange name, and single-letter abbreviation. Useful
for decoding the mdSize / mdMask bitmaps on tick-by-tick and
market-depth streams. The token is typically obtained from the
LAST_EXCHANGE market-data tick (tick type 84).
§Arguments
bbo_exchange- The BBO exchange token (e.g."a6").
§Examples
use ibapi::Client;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let components = client.smart_components("a6").await.expect("request failed");
for component in &components {
println!("bit {}: {} ({})", component.bit_number, component.exchange, component.exchange_letter);
}
}Sourcepub async fn calculate_option_price(
&self,
contract: &Contract,
volatility: f64,
underlying_price: f64,
) -> Result<OptionComputation, Error>
pub async fn calculate_option_price( &self, contract: &Contract, volatility: f64, underlying_price: f64, ) -> Result<OptionComputation, Error>
Calculates an option’s price based on the provided volatility and its underlying’s price.
§Arguments
contract- The Contract object representing the option for which the calculation is being requested.volatility- Hypothetical volatility.underlying_price- Hypothetical option’s underlying price.
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let contract = Contract::option("AAPL", "20251219", 150.0, OptionRight::Call);
let calculation = client
.calculate_option_price(&contract, 100.0, 235.0)
.await
.expect("request failed");
println!("calculation: {calculation:?}");
}Sourcepub async fn calculate_implied_volatility(
&self,
contract: &Contract,
option_price: f64,
underlying_price: f64,
) -> Result<OptionComputation, Error>
pub async fn calculate_implied_volatility( &self, contract: &Contract, option_price: f64, underlying_price: f64, ) -> Result<OptionComputation, Error>
Calculates the implied volatility based on hypothetical option and its underlying prices.
§Arguments
contract- The Contract object representing the option for which the calculation is being requested.option_price- Hypothetical option price.underlying_price- Hypothetical option’s underlying price.
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let contract = Contract::option("AAPL", "20230519", 150.0, OptionRight::Call);
let calculation = client
.calculate_implied_volatility(&contract, 25.0, 235.0)
.await
.expect("request failed");
println!("calculation: {calculation:?}");
}Sourcepub async fn cancel_contract_details(
&self,
request_id: i32,
) -> Result<(), Error>
pub async fn cancel_contract_details( &self, request_id: i32, ) -> Result<(), Error>
Cancels an in-flight contract details request.
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
// `request_id` is the id of the request to cancel, e.g. from `ContractDetailsBuilder::request_id`.
// Dropping a `contract_details_stream` subscription already cancels it.
client.cancel_contract_details(42).await.expect("cancel failed");
}Sourcepub fn option_chain<'a>(
&'a self,
symbol: &'a str,
security_type: SecurityType,
contract_id: i32,
) -> OptionChainBuilder<'a, Self>
pub fn option_chain<'a>( &'a self, symbol: &'a str, security_type: SecurityType, contract_id: i32, ) -> OptionChainBuilder<'a, Self>
Build a request for an underlying’s option chain: one OptionChain per
exchange the options trade on.
Terminal: OptionChainBuilder::subscribe. Optional narrowing via OptionChainBuilder::exchange.
§Arguments
symbol- Symbol of the underlying.security_type- Security type of the underlying, e.g.SecurityType::Stock.contract_id- Contract id of the underlying. Required; TWS rejects0with code 321 “Invalid contract id”.
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let subscription = client
.option_chain("AAPL", SecurityType::Stock, 265598)
.subscribe()
.await
.expect("request option chain failed");
let mut chains = subscription.filter_data();
while let Some(chain) = chains.next().await {
let chain = chain.expect("decode error");
println!("{}: {} expirations, {} strikes", chain.exchange, chain.expirations.len(), chain.strikes.len());
}
}Source§impl Client
impl Client
Sourcepub async fn head_timestamp(
&self,
contract: &Contract,
what_to_show: WhatToShow,
trading_hours: TradingHours,
) -> Result<OffsetDateTime, Error>
pub async fn head_timestamp( &self, contract: &Contract, what_to_show: WhatToShow, trading_hours: TradingHours, ) -> Result<OffsetDateTime, Error>
Returns the timestamp of earliest available historical data for a contract and data type.
§Arguments
contract- Contract to retrieve the head timestamp for.what_to_show- requested bar type: WhatToShow.trading_hours- Use TradingHours::Regular for data generated only during regular trading hours, or TradingHours::Extended to include data from outside regular trading hours.
§Examples
use ibapi::Client;
use ibapi::contracts::Contract;
use ibapi::market_data::historical::WhatToShow;
use ibapi::market_data::TradingHours;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let contract = Contract::stock("MSFT").build();
let result = client
.head_timestamp(&contract, WhatToShow::Trades, TradingHours::Regular)
.await
.expect("head timestamp failed");
println!("head_timestamp: {result:?}");
}Sourcepub fn historical_data<'a>(
&'a self,
contract: &'a Contract,
bar_size: BarSize,
) -> HistoricalDataBuilder<'a, Self>
pub fn historical_data<'a>( &'a self, contract: &'a Contract, bar_size: BarSize, ) -> HistoricalDataBuilder<'a, Self>
Build a request for historical bar data.
Required: a date spec via either HistoricalDataBuilder::duration
(with optional HistoricalDataBuilder::ending) or
HistoricalDataBuilder::between. Terminals:
HistoricalDataBuilder::fetch for a one-shot
HistoricalData result; HistoricalDataBuilder::stream
for a Subscription<HistoricalBarUpdate> that yields bars as they arrive.
§Arguments
contract- Contract object that is subject of querybar_size- Bar size (resolution)
§Examples
use ibapi::prelude::*;
use time::macros::datetime;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let contract = Contract::stock("AAPL").build();
// IBKR-native: amount of data ending at a specific time (or now)
let bars = client
.historical_data(&contract, HistoricalBarSize::Hour)
.what_to_show(HistoricalWhatToShow::Trades)
.duration(7.days())
.fetch()
.await
.expect("historical data request failed");
// Convenience: explicit date range; bars outside it are dropped
let bars = client
.historical_data(&contract, HistoricalBarSize::Hour)
.between(datetime!(2023-04-08 0:00 UTC), datetime!(2023-04-15 0:00 UTC))
.fetch()
.await
.expect("historical data request failed");
let _ = bars;
}Sourcepub fn historical_schedules<'a>(
&'a self,
contract: &'a Contract,
duration: Duration,
) -> HistoricalScheduleBuilder<'a, Self>
pub fn historical_schedules<'a>( &'a self, contract: &'a Contract, duration: Duration, ) -> HistoricalScheduleBuilder<'a, Self>
Build a request for Schedule data over the given duration.
Defaults to anchoring at the current time. Use HistoricalScheduleBuilder::ending
to anchor at a specific end date.
§Arguments
§Examples
use ibapi::prelude::*;
use time::macros::datetime;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let contract = Contract::stock("GM").build();
// Ending now:
let schedule = client
.historical_schedules(&contract, 30.days())
.fetch()
.await
.expect("historical schedule request failed");
// Anchored to a specific end date:
let schedule = client
.historical_schedules(&contract, 30.days())
.ending(datetime!(2023-04-15 0:00 UTC))
.fetch()
.await
.expect("historical schedule request failed");
for session in &schedule.sessions {
println!("{session:?}");
}
}Sourcepub fn historical_ticks<'a>(
&'a self,
contract: &'a Contract,
number_of_ticks: i32,
) -> HistoricalTicksBuilder<'a, Self>
pub fn historical_ticks<'a>( &'a self, contract: &'a Contract, number_of_ticks: i32, ) -> HistoricalTicksBuilder<'a, Self>
Build a request for historical time & sales data (tick-by-tick).
The terminal method selects the tick type:
HistoricalTicksBuilder::trade /
.mid_point() / .bid_ask(IgnoreSize). Use
HistoricalTicksBuilder::starting /
.ending() to anchor the query (at least one is required per IBKR).
§Arguments
contract- Contract object that is subject of querynumber_of_ticks- Number of distinct data points. Max currently 1000 per request.
§Examples
use ibapi::prelude::*;
use ibapi::market_data::IgnoreSize;
use time::macros::datetime;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let contract = Contract::stock("TSLA").build();
// Trade ticks anchored at a start date:
let mut trades = client
.historical_ticks(&contract, 100)
.starting(datetime!(2023-04-15 0:00 UTC))
.trade()
.await
.expect("historical ticks request failed");
while let Some(tick) = trades.next().await {
println!("{tick:?}");
}
// Bid/ask ticks anchored at an end date, ignoring tick sizes:
let _quotes = client
.historical_ticks(&contract, 100)
.ending(datetime!(2023-04-15 0:00 UTC))
.bid_ask(IgnoreSize::Yes)
.await
.expect("historical ticks request failed");
}Sourcepub async fn cancel_historical_ticks(
&self,
request_id: i32,
) -> Result<(), Error>
pub async fn cancel_historical_ticks( &self, request_id: i32, ) -> Result<(), Error>
Cancels an in-flight historical ticks request.
§Arguments
request_id- The request ID of the historical ticks subscription to cancel.
§Examples
use ibapi::Client;
use ibapi::contracts::Contract;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let contract = Contract::stock("MSFT").build();
let subscription = client.historical_ticks(&contract, 100).trade().await.expect("request failed");
// Holding the subscription, `subscription.cancel().await` (or dropping it) does the same.
client.cancel_historical_ticks(subscription.request_id()).await.expect("cancel failed");
}Sourcepub async fn histogram_data(
&self,
contract: &Contract,
trading_hours: TradingHours,
period: BarSize,
) -> Result<Vec<HistogramEntry>, Error>
pub async fn histogram_data( &self, contract: &Contract, trading_hours: TradingHours, period: BarSize, ) -> Result<Vec<HistogramEntry>, Error>
Requests data histogram of specified contract.
§Arguments
contract- Contract to retrieve HistogramEntry data for.trading_hours- Regular trading hours only, or include extended hours.period- The time period of each histogram bar (e.g.,BarSize::Day,BarSize::Week,BarSize::Month).
§Examples
use ibapi::Client;
use ibapi::contracts::Contract;
use ibapi::market_data::historical::BarSize;
use ibapi::market_data::TradingHours;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let contract = Contract::stock("GM").build();
let histogram = client
.histogram_data(&contract, TradingHours::Regular, BarSize::Week)
.await
.expect("histogram request failed");
for item in &histogram {
println!("{item:?}");
}
}Source§impl Client
impl Client
Sourcepub async fn switch_market_data_type(
&self,
market_data_type: MarketDataType,
) -> Result<(), Error>
pub async fn switch_market_data_type( &self, market_data_type: MarketDataType, ) -> Result<(), Error>
Switches market data type returned from request_market_data requests to Live, Frozen, Delayed, or FrozenDelayed.
§Arguments
market_data_type- Type of market data to retrieve.
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let market_data_type = MarketDataType::Realtime;
client.switch_market_data_type(market_data_type).await.expect("request failed");
println!("market data switched: {market_data_type:?}");
}Sourcepub fn market_data<'a>(
&'a self,
contract: &'a Contract,
) -> MarketDataBuilder<'a, Self>
pub fn market_data<'a>( &'a self, contract: &'a Contract, ) -> MarketDataBuilder<'a, Self>
Returns a builder for a streaming level-1 market data subscription.
Streams by default; .snapshot() switches to a one-shot request. See
MarketDataBuilder for the chained methods.
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let contract = Contract::stock("AAPL").build();
// Subscribe to real-time streaming data with specific tick types
let mut subscription = client
.market_data(&contract)
.generic_ticks(&["233", "236"]) // RTVolume and Shortable
.subscribe()
.await
.expect("subscription failed");
while let Some(item) = subscription.next().await {
match item {
Ok(SubscriptionItem::Data(TickTypes::Price(price))) => println!("Price: {price:?}"),
Ok(SubscriptionItem::Data(TickTypes::Size(size))) => println!("Size: {size:?}"),
Ok(SubscriptionItem::Data(_)) => {}
Ok(SubscriptionItem::Notice(n)) => eprintln!("notice: {n}"),
Err(e) => { eprintln!("error: {e}"); break; }
}
}
}A one-shot snapshot, driven manually. To just collect the ticks and stop, prefer
MarketDataBuilder::snapshot_once, which wraps this loop with a timeout.
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let contract = Contract::stock("AAPL").build();
let mut subscription = client
.market_data(&contract)
.snapshot()
.subscribe()
.await
.expect("subscription failed");
while let Some(item) = subscription.next().await {
match item {
Ok(SubscriptionItem::Data(TickTypes::SnapshotEnd)) => { println!("Snapshot complete"); break; }
Ok(SubscriptionItem::Data(tick)) => println!("tick: {tick:?}"),
Ok(SubscriptionItem::Notice(n)) => eprintln!("notice: {n}"),
Err(e) => { eprintln!("error: {e}"); break; }
}
}
}Sourcepub fn realtime_bars<'a>(
&'a self,
contract: &'a Contract,
) -> RealtimeBarsBuilder<'a, Self>
pub fn realtime_bars<'a>( &'a self, contract: &'a Contract, ) -> RealtimeBarsBuilder<'a, Self>
Returns a builder for a real-time 5-second bar subscription.
Defaults to WhatToShow::Trades and TradingHours::Regular. See
RealtimeBarsBuilder for the chained methods.
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let contract = Contract::stock("TSLA").build();
let mut subscription = client
.realtime_bars(&contract)
.what_to_show(RealtimeWhatToShow::Trades)
.trading_hours(TradingHours::Extended)
.subscribe()
.await
.expect("realtime bars request failed");
while let Some(item) = subscription.next().await {
match item {
Ok(SubscriptionItem::Data(bar)) => println!("{bar:?}"),
Ok(SubscriptionItem::Notice(n)) => eprintln!("notice: {n}"),
Err(e) => { eprintln!("error: {e}"); break; }
}
}
}Sourcepub fn tick_by_tick<'a>(
&'a self,
contract: &'a Contract,
number_of_ticks: i32,
) -> TickByTickBuilder<'a, Self>
pub fn tick_by_tick<'a>( &'a self, contract: &'a Contract, number_of_ticks: i32, ) -> TickByTickBuilder<'a, Self>
Returns a builder for a tick-by-tick real-time subscription.
Pick the tick stream with the terminal — .last() / .all_last() /
.bid_ask(IgnoreSize) / .mid_point(). See TickByTickBuilder.
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let contract = Contract::stock("AAPL").build();
let mut quotes = client
.tick_by_tick(&contract, 10)
.bid_ask(IgnoreSize::No)
.await
.expect("tick-by-tick bid/ask request failed");
while let Some(item) = quotes.next().await {
match item {
Ok(SubscriptionItem::Data(q)) => println!("{q:?}"),
Ok(SubscriptionItem::Notice(n)) => eprintln!("notice: {n}"),
Err(e) => { eprintln!("error: {e}"); break; }
}
}
}Sourcepub fn market_depth<'a>(
&'a self,
contract: &'a Contract,
number_of_rows: i32,
) -> MarketDepthBuilder<'a, Self>
pub fn market_depth<'a>( &'a self, contract: &'a Contract, number_of_rows: i32, ) -> MarketDepthBuilder<'a, Self>
Returns a builder for a level-2 market-depth (order book) subscription.
Defaults to SmartDepth::No. See MarketDepthBuilder for the chained
methods, and MarketDepths for handling a book reset (317) and halt
(316).
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let contract = Contract::stock("AAPL").build();
let mut subscription = client
.market_depth(&contract, 5)
.smart_depth(SmartDepth::Yes)
.subscribe()
.await
.expect("market depth request failed");
while let Some(item) = subscription.next().await {
match item {
Ok(SubscriptionItem::Data(row)) => println!("{row:?}"),
Ok(SubscriptionItem::Notice(n)) => eprintln!("notice: {n}"),
Err(e) => { eprintln!("error: {e}"); break; }
}
}
}Sourcepub async fn market_depth_exchanges(
&self,
) -> Result<Vec<DepthMarketDataDescription>, Error>
pub async fn market_depth_exchanges( &self, ) -> Result<Vec<DepthMarketDataDescription>, Error>
Requests venues for which market data is returned to market_depth (those with market makers)
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let exchanges = client.market_depth_exchanges().await.expect("error requesting market depth exchanges");
for exchange in &exchanges {
println!("{exchange:?}");
}
}Source§impl Client
impl Client
Sourcepub async fn news_providers(&self) -> Result<Vec<NewsProvider>, Error>
pub async fn news_providers(&self) -> Result<Vec<NewsProvider>, Error>
Requests news providers which the user has subscribed to.
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let providers = client.news_providers().await.expect("news_providers failed");
for provider in providers {
println!("{provider:?}");
}
}Sourcepub async fn news_bulletins(
&self,
all_messages: bool,
) -> Result<Subscription<NewsBulletin>, Error>
pub async fn news_bulletins( &self, all_messages: bool, ) -> Result<Subscription<NewsBulletin>, Error>
Subscribes to IB’s News Bulletins.
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let subscription = client.news_bulletins(true).await.expect("news_bulletins failed");
let mut bulletins = subscription.filter_data();
while let Some(bulletin) = bulletins.next().await {
println!("{bulletin:?}");
}
}Sourcepub async fn historical_news(
&self,
contract_id: i32,
provider_codes: &[&str],
start_time: OffsetDateTime,
end_time: OffsetDateTime,
total_results: u8,
) -> Result<Subscription<NewsArticle>, Error>
pub async fn historical_news( &self, contract_id: i32, provider_codes: &[&str], start_time: OffsetDateTime, end_time: OffsetDateTime, total_results: u8, ) -> Result<Subscription<NewsArticle>, Error>
Historical News Headlines
§Examples
use ibapi::prelude::*;
use time::macros::datetime;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let subscription = client
.historical_news(
8314, // IBM
&["BRFG"],
datetime!(2025-01-01 0:00 UTC),
datetime!(2025-01-31 23:59 UTC),
10,
)
.await
.expect("historical_news failed");
let mut articles = subscription.filter_data();
while let Some(article) = articles.next().await {
println!("{article:?}");
}
}Sourcepub async fn news_article(
&self,
provider_code: &str,
article_id: &str,
) -> Result<NewsArticleBody, Error>
pub async fn news_article( &self, provider_code: &str, article_id: &str, ) -> Result<NewsArticleBody, Error>
Requests news article body
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let article = client
.news_article("BRFG", "BRFG$0a3e3f54")
.await
.expect("news_article failed");
println!("{article:?}");
}Sourcepub async fn contract_news(
&self,
contract: &Contract,
provider_codes: &[&str],
) -> Result<Subscription<NewsArticle>, Error>
pub async fn contract_news( &self, contract: &Contract, provider_codes: &[&str], ) -> Result<Subscription<NewsArticle>, Error>
Subscribe to news for a specific contract
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let contract = Contract::stock("AAPL").build();
let subscription = client.contract_news(&contract, &["BRFG"]).await.expect("contract_news failed");
let mut articles = subscription.filter_data();
while let Some(article) = articles.next().await {
println!("{article:?}");
}
}Sourcepub async fn broad_tape_news(
&self,
provider_code: &str,
) -> Result<Subscription<NewsArticle>, Error>
pub async fn broad_tape_news( &self, provider_code: &str, ) -> Result<Subscription<NewsArticle>, Error>
Subscribe to broad tape news
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let subscription = client.broad_tape_news("BRFG").await.expect("broad_tape_news failed");
let mut articles = subscription.filter_data();
while let Some(article) = articles.next().await {
println!("{article:?}");
}
}Source§impl Client
Submitting several OCA orders in one call.
impl Client
Submitting several OCA orders in one call.
Sourcepub async fn submit_oca_orders(
&self,
orders: Vec<(Contract, Order)>,
) -> Result<Vec<OrderId>, Error>
pub async fn submit_oca_orders( &self, orders: Vec<(Contract, Order)>, ) -> Result<Vec<OrderId>, Error>
Submit multiple OCA (One-Cancels-All) orders
When one order in the group is filled, all others are automatically cancelled.
§Example
use ibapi::Client;
use ibapi::contracts::Contract;
use ibapi::orders::OcaType;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let contract1 = Contract::stock("AAPL").build();
let contract2 = Contract::stock("MSFT").build();
let order1 = client.order(&contract1)
.buy(100)
.limit(50.0)
.oca_group("MyOCA", OcaType::CancelWithBlock)
.build_order().expect("order build failed");
let order2 = client.order(&contract2)
.buy(100)
.limit(45.0)
.oca_group("MyOCA", OcaType::CancelWithBlock)
.build_order().expect("order build failed");
let order_ids = client.submit_oca_orders(
vec![(contract1, order1), (contract2, order2)]
).await.expect("OCA submission failed");
}Source§impl Client
impl Client
Sourcepub fn order<'a>(
&'a self,
contract: &'a Contract,
) -> OrderBuilder<ClientBound<'a, Self>>
pub fn order<'a>( &'a self, contract: &'a Contract, ) -> OrderBuilder<ClientBound<'a, Self>>
Start building an order for the given contract
This is the primary API for creating orders, providing a fluent interface that guides you through the order creation process.
§Examples
use ibapi::Client;
use ibapi::contracts::Contract;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let contract = Contract::stock("AAPL").build();
let order_id = client.order(&contract)
.buy(100)
.limit(50.0)
.submit().await.expect("order submission failed");
}Sourcepub async fn order_update_stream(
&self,
) -> Result<Subscription<OrderUpdate>, Error>
pub async fn order_update_stream( &self, ) -> Result<Subscription<OrderUpdate>, Error>
Subscribes to order update events. Only one subscription can be active at a time.
Order-bound TWS errors and warnings (e.g. rejections, code 399 order
messages) arrive as SubscriptionItem::Notice,
not as OrderUpdate variants. They surface via next() as below;
filter_data() drops them (logging at warn! level), so match on
notices explicitly when monitoring fire-and-forget orders for rejection.
To pair a CommissionReport with the
ExecutionData it belongs to, join on
execution_id — the commission follows its execution and shares that key. See
the CommissionReport docs for the idiom.
§Gaps and recovery
TWS does not replay order events, so two situations leave a gap the stream cannot fill on its own:
- Reconnect. The stream survives the client’s automatic reconnects:
the same subscription keeps delivering once the connection returns,
but updates TWS emitted during the outage are lost and no marker
appears in the stream. Watch
Self::notice_streamfor the connectivity notices (codes 1100 connectivity lost, 1101 restored with data lost, 1102 restored with data maintained, 1300 socket reset). - Error. An
Erritem ends the stream; every later call returnsNone. A frame that fails to decode is a bug in TWS or this crate, so it is surfaced rather than skipped.
Client shutdown (disconnect, drop, or a reconnect that gives up) also
ends the stream; after it, order_update_stream returns
Error::Shutdown.
After an error, drop the ended subscription (and any clones) and call
order_update_stream again; while one is held, a second call
returns Error::AlreadySubscribed.
After a reconnect, the existing subscription is still live. In both
cases, rebuild state from snapshots:
Self::all_open_orders: every open order and its status.Self::completed_orders(false): orders that filled or were cancelled during the gap.Self::executionswith a defaultExecutionFilter: fills and their commissions. The default covers the current day only; setlast_n_dayswhen the gap may span midnight, as the daily gateway reset does.
The snapshots cover every client’s orders, while this stream reports
only this client’s. Keep the entries whose order.client_id /
execution.client_id matches, or state will hold orders the stream
never updates.
Take the snapshots after the stream is live again, so no event falls
between the two. An event can then arrive both ways; apply updates
idempotently, keyed by perm_id for orders and execution_id for fills.
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let mut stream = client.order_update_stream().await.expect("failed to create stream");
while let Some(item) = stream.next().await {
match item {
Ok(SubscriptionItem::Data(OrderUpdate::OrderStatus(s))) => println!("status: {s:?}"),
Ok(SubscriptionItem::Data(update)) => println!("update: {update:?}"),
Ok(SubscriptionItem::Notice(notice)) if notice.is_error() => {
eprintln!("order {:?} rejected: {}", notice.request_id, notice.message);
}
Ok(SubscriptionItem::Notice(notice)) => println!("notice: {}", notice.message),
Err(e) => { eprintln!("err: {e:?}"); break; }
}
}
}Sourcepub async fn submit_order(
&self,
order_id: impl Into<OrderId>,
contract: &Contract,
order: &Order,
) -> Result<(), Error>
pub async fn submit_order( &self, order_id: impl Into<OrderId>, contract: &Contract, order: &Order, ) -> Result<(), Error>
Submits an Order (fire-and-forget).
§Errors
Error::OrderIdInRequestRange if order_id, or a parent_id or preset attached-order id on order, is at or above 1,500,000,000 (reserved for request ids).
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let contract = Contract::stock("AAPL").build();
let order = client
.order(&contract)
.buy(100)
.market()
.build()
.expect("order build");
let order_id = client.next_valid_order_id().await.expect("next id");
client.submit_order(order_id, &contract, &order).await.expect("submit failed");
}Sourcepub async fn place_order(
&self,
order_id: impl Into<OrderId>,
contract: &Contract,
order: &Order,
) -> Result<Subscription<PlaceOrder>, Error>
pub async fn place_order( &self, order_id: impl Into<OrderId>, contract: &Contract, order: &Order, ) -> Result<Subscription<PlaceOrder>, Error>
Submits an Order with a subscription for updates.
§Errors
Error::OrderIdInRequestRange if order_id, or a parent_id or preset attached-order id on order, is at or above 1,500,000,000 (reserved for request ids).
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let contract = Contract::stock("AAPL").build();
let order = client
.order(&contract)
.buy(100)
.market()
.build()
.expect("order build");
let order_id = client.next_valid_order_id().await.expect("next id");
let subscription = client.place_order(order_id, &contract, &order).await.expect("place");
let mut updates = subscription.filter_data();
while let Some(update) = updates.next().await {
println!("{update:?}");
}
}Sourcepub async fn cancel_order(
&self,
order_id: impl Into<OrderId>,
manual_order_cancel_time: &str,
) -> Result<Subscription<CancelOrder>, Error>
pub async fn cancel_order( &self, order_id: impl Into<OrderId>, manual_order_cancel_time: &str, ) -> Result<Subscription<CancelOrder>, Error>
Cancels an open Order.
The confirmation (TWS code 202) arrives as a non-terminal
SubscriptionItem::Notice;
the subscription stays open until dropped, so break once cancellation
is observed.
§Errors
Error::OrderIdInRequestRange if order_id is at or above 1,500,000,000 (reserved for request ids).
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
// `""` selects immediate cancel (no manual order time).
let mut subscription = client.cancel_order(42, "").await.expect("cancel failed");
while let Some(item) = subscription.next().await {
match item {
Ok(SubscriptionItem::Data(event)) => println!("status: {event:?}"),
Ok(SubscriptionItem::Notice(n)) if n.is_cancellation() => {
println!("cancelled: {n}");
break;
}
Ok(SubscriptionItem::Notice(n)) => println!("notice: {n}"),
Err(e) => { eprintln!("cancel err: {e:?}"); break; }
}
}
}Sourcepub async fn global_cancel(&self) -> Result<(), Error>
pub async fn global_cancel(&self) -> Result<(), Error>
Sourcepub async fn next_valid_order_id(&self) -> Result<i32, Error>
pub async fn next_valid_order_id(&self) -> Result<i32, Error>
Gets next valid order id
The returned value also raises the client’s order-ID generator to at least that value — monotonically, never lowering it below locally allocated order IDs, including IDs whose order has not yet reached the server.
§Errors
Error::OrderIdInRequestRange if TWS returns an id at or above 1,500,000,000 (reserved for request ids).
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let next = client.next_valid_order_id().await.expect("next id failed");
println!("next_valid_order_id: {next}");
}Sourcepub async fn completed_orders(
&self,
api_only: bool,
) -> Result<Subscription<Orders>, Error>
pub async fn completed_orders( &self, api_only: bool, ) -> Result<Subscription<Orders>, Error>
Requests completed Orders.
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let subscription = client.completed_orders(true).await.expect("completed_orders failed");
let mut orders = subscription.filter_data();
while let Some(order) = orders.next().await {
println!("{order:?}");
}
}Sourcepub async fn open_orders(&self) -> Result<Subscription<Orders>, Error>
pub async fn open_orders(&self) -> Result<Subscription<Orders>, Error>
Requests all open orders placed by this specific API client.
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let subscription = client.open_orders().await.expect("open_orders failed");
let mut orders = subscription.filter_data();
while let Some(order) = orders.next().await {
println!("{order:?}");
}
}Sourcepub async fn all_open_orders(&self) -> Result<Subscription<Orders>, Error>
pub async fn all_open_orders(&self) -> Result<Subscription<Orders>, Error>
Requests all current open orders in associated accounts.
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let subscription = client.all_open_orders().await.expect("all_open_orders failed");
let mut orders = subscription.filter_data();
while let Some(order) = orders.next().await {
println!("{order:?}");
}
}Sourcepub async fn auto_open_orders(
&self,
auto_bind: bool,
) -> Result<Subscription<Orders>, Error>
pub async fn auto_open_orders( &self, auto_bind: bool, ) -> Result<Subscription<Orders>, Error>
Requests status updates about future orders placed from TWS.
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let subscription = client.auto_open_orders(true).await.expect("auto_open_orders failed");
let mut orders = subscription.filter_data();
while let Some(order) = orders.next().await {
println!("{order:?}");
}
}Sourcepub async fn executions(
&self,
filter: ExecutionFilter,
) -> Result<Subscription<Executions>, Error>
pub async fn executions( &self, filter: ExecutionFilter, ) -> Result<Subscription<Executions>, Error>
Requests executions matching the filter.
Covers the current day (since midnight) by default; set
ExecutionFilter::last_n_days or ExecutionFilter::specific_dates
to reach earlier days.
Both ExecutionData and
CommissionReport are delivered on this
stream. Join a commission to its execution by execution_id
(see the CommissionReport docs) — the commission follows its execution.
§Examples
use ibapi::Client;
use ibapi::orders::{ExecutionFilter, ExecutionFilterSide};
use ibapi::subscriptions::SubscriptionItem;
use futures::StreamExt;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let filter = ExecutionFilter {
side: Some(ExecutionFilterSide::Buy),
..ExecutionFilter::default()
};
let mut subscription = client.executions(filter).await.expect("request failed");
while let Some(item) = subscription.next().await {
match item {
Ok(SubscriptionItem::Data(ex)) => println!("{ex:?}"),
Ok(SubscriptionItem::Notice(n)) => eprintln!("notice: {n}"),
Err(e) => eprintln!("Error: {e}"),
}
}
}Sourcepub async fn order_status_stream(
&self,
order_id: impl Into<OrderId>,
) -> Result<Subscription<OrderStatus>, Error>
pub async fn order_status_stream( &self, order_id: impl Into<OrderId>, ) -> Result<Subscription<OrderStatus>, Error>
Streams one order’s status updates.
Starts with the order’s latest status, if this client has seen one
(the latest statuses of the 10,000 most recent orders are kept), then
yields each new OrderStatus as TWS sends it. If TWS refuses the
order with an error before any status (e.g. 110, a price off the
minimum tick), the stream yields that error as Error::Notice and
ends; a stream opened later starts with it. Otherwise the stream does
not end on its own when the order does; stop reading, or see
wait_for_fill for the common case.
Takes nothing from order_update_stream or
a place_order subscription: all may be open at
once, as may several streams on one order. Nothing is sent to TWS.
§Examples
use futures::StreamExt;
use ibapi::contracts::Contract;
use ibapi::subscriptions::SubscriptionItemStreamExt;
use ibapi::Client;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let contract = Contract::stock("AAPL").build();
let order_id = client.order(&contract).buy(100).limit(150.0).submit().await.expect("order submission failed");
let mut statuses = client.order_status_stream(order_id).await.expect("stream failed").filter_data();
while let Some(status) = statuses.next().await {
let status = status.expect("stream error");
println!("{}: {}/{} filled", status.status, status.filled, status.filled + status.remaining);
if status.status.is_terminal() {
break;
}
}
}Sourcepub async fn wait_for_fill(
&self,
order_id: impl Into<OrderId>,
timeout: Duration,
) -> Result<OrderOutcome, Error>
pub async fn wait_for_fill( &self, order_id: impl Into<OrderId>, timeout: Duration, ) -> Result<OrderOutcome, Error>
Waits until an order fills or ends, or timeout elapses.
Returns OrderOutcome::Filled when the order filled completely,
OrderOutcome::Ended when it was cancelled or became inactive first,
OrderOutcome::Rejected with TWS’s error when TWS refused the order
without a status (e.g. 110, a price off the minimum tick), and
OrderOutcome::TimedOut with the last status seen when time runs
out. A timeout leaves the order working; cancel it yourself if needed.
Built on order_status_stream, so an
order that already finished before the call is reported at once, as
long as this client saw its status since connecting. An order whose
statuses never reach this client (placed by another client, or
finished before this connection) waits out the timeout.
§Errors
Error::ConnectionReset if the connection drops during the wait,
Error::Shutdown if the client shuts down.
§Examples
use std::time::Duration;
use ibapi::contracts::Contract;
use ibapi::orders::OrderOutcome;
use ibapi::Client;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let contract = Contract::stock("AAPL").build();
let order_id = client.order(&contract).buy(100).market().submit().await.expect("order submission failed");
match client.wait_for_fill(order_id, Duration::from_secs(30)).await.expect("wait failed") {
OrderOutcome::Filled(status) => println!("filled {} @ {:?}", status.filled, status.average_fill_price),
OrderOutcome::Ended(status) => println!("ended {:?} after {} filled", status.status, status.filled),
OrderOutcome::TimedOut(status) => println!("still working: {status:?}"),
OrderOutcome::Rejected(notice) => println!("rejected: {notice}"),
}
}Sourcepub fn exercise_options<'a>(
&'a self,
contract: &'a Contract,
) -> ExerciseOptionsBuilder<'a, Self>
pub fn exercise_options<'a>( &'a self, contract: &'a Contract, ) -> ExerciseOptionsBuilder<'a, Self>
Exercise or lapse an option position.
Terminal: ExerciseOptionsBuilder::submit. Pick exercise
or lapse; account,
override_natural_action and
manual_order_time are optional.
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let contract = Contract::option("AAPL", "20251219", 150.0, OptionRight::Call);
let subscription = client
.exercise_options(&contract)
.exercise(1)
.override_natural_action()
.submit()
.await
.expect("exercise_options failed");
}Source§impl Client
impl Client
Sourcepub async fn scanner_parameters(&self) -> Result<String, Error>
pub async fn scanner_parameters(&self) -> Result<String, Error>
Requests an XML list of scanner parameters valid in TWS.
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let xml = client.scanner_parameters().await.expect("scanner_parameters failed");
println!("scanner parameters: {} chars", xml.len());
}Sourcepub async fn scanner_subscription(
&self,
subscription: &ScannerSubscription,
filter: &[TagValue],
) -> Result<Subscription<Vec<ScannerData>>, Error>
pub async fn scanner_subscription( &self, subscription: &ScannerSubscription, filter: &[TagValue], ) -> Result<Subscription<Vec<ScannerData>>, Error>
Starts a subscription to market scan results based on the provided parameters.
§Examples
use ibapi::prelude::*;
use ibapi::scanner::ScannerSubscription;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let mut sub = ScannerSubscription::default();
sub.instrument = Some("STK".to_string());
sub.location_code = Some("STK.US.MAJOR".to_string());
sub.scan_code = Some("TOP_PERC_GAIN".to_string());
let filter: Vec<ibapi::contracts::TagValue> = Vec::new();
let subscription = client
.scanner_subscription(&sub, &filter)
.await
.expect("scanner_subscription failed");
// Take the first batch of results, if any.
let mut data = subscription.filter_data();
if let Some(batch) = data.next().await {
match batch {
Ok(rows) => {
for row in rows {
println!(
"rank: {}, symbol: {}",
row.rank, row.contract_details.contract.symbol
);
}
}
Err(e) => eprintln!("scanner error: {e:?}"),
}
}
}Source§impl Client
impl Client
Sourcepub async fn wsh_metadata(&self) -> Result<WshMetadata, Error>
pub async fn wsh_metadata(&self) -> Result<WshMetadata, Error>
Fetch Wall Street Horizon metadata table with retry semantics.
§Examples
use ibapi::prelude::*;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let metadata = client.wsh_metadata().await.expect("request wsh metadata failed");
println!("{metadata:?}");
}Sourcepub fn wsh_event_data_by_contract(
&self,
contract_id: i32,
) -> WshEventDataBuilder<'_, Self>
pub fn wsh_event_data_by_contract( &self, contract_id: i32, ) -> WshEventDataBuilder<'_, Self>
Build a request for Wall Street Horizon events on one contract.
Terminal: WshEventDataBuilder::fetch. Optional narrowing via
.starting() / .ending() / .limit() / .auto_fill().
§Arguments
contract_id- Contract identifier for the event request.
§Examples
use ibapi::Client;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let contract_id = 76792991; // TSLA
let event_data = client
.wsh_event_data_by_contract(contract_id)
.fetch()
.await
.expect("request wsh event data failed");
println!("{event_data:?}");
}Sourcepub fn wsh_event_data_by_filter<'a>(
&'a self,
filter: &'a str,
) -> WshEventFilterBuilder<'a, Self>
pub fn wsh_event_data_by_filter<'a>( &'a self, filter: &'a str, ) -> WshEventFilterBuilder<'a, Self>
Build a request for Wall Street Horizon events matching a JSON filter.
Terminal: WshEventFilterBuilder::subscribe.
§Arguments
filter- Json-formatted string containing all filter values.
§Examples
use ibapi::Client;
use ibapi::subscriptions::r#async::SubscriptionItemStreamExt;
use futures::StreamExt;
#[tokio::main]
async fn main() {
let client = Client::connect("127.0.0.1:4002", 100).await.expect("connection failed");
let filter = "{}"; // see https://www.interactivebrokers.com/campus/ibkr-api-page/twsapi-doc/#wsheventdata-object
let mut subscription = client
.wsh_event_data_by_filter(filter)
.subscribe()
.await
.expect("request wsh event data failed");
let mut events = subscription.filter_data();
while let Some(event) = events.next().await {
println!("{:?}", event.expect("decode error"));
}
}