Skip to main content

Module ibkr

Module ibkr 

Source
Expand description

Interactive Brokers ExecutionClient implementation.

Uses the ibapi crate for IB TWS/Gateway connectivity. Supports equities, futures, options, and forex.

§Testing Status

NOT TESTED in CI. IBKR has not confirmed permission to use credentials for CI, and requires IB Gateway/TWS running locally.

Tested locally: All execution tests (connection, orders, account streaming) run on paper trading accounts — no market data subscriptions required.

§Connection

Requires TWS or IB Gateway running locally with API enabled:

ApplicationLive PortPaper Port
TWS74967497
IB Gateway40014002

Enable API in TWS/Gateway: Configure → API → Settings → Enable ActiveX and Socket Clients. For order placement, uncheck “Read-Only API”.

§Architecture

  • Connection: TCP socket to TWS/Gateway
  • Orders: Subscription-based events (OrderStatus, ExecutionData, CommissionReport)
  • Account: Subscription-based position and balance updates

§Balances and carrying costs

Balances are read from IB’s account summary, one per currency: total is TotalCashValue and free is AvailableFunds. No other tag is read, and ExecutionClient::account_stream delivers no balances.

As IB documents it, margin interest and stock borrow fees accrue through the month, reported under the AccruedCash tag, and are posted to cash monthly. Until they are posted, TotalCashValue, and so total, leaves them out: up to a month of charges. This client does not read AccruedCash. Fills carry none of these charges, so PnL computed from them excludes them too.

§Limitations

  • Order types: Market, Limit, Stop, StopLimit, TrailingStop, TrailingStopLimit, and Bracket (entry + take-profit + stop-loss) supported. No Algo orders.
  • TimeInForce: No post_only (IB has no maker-only orders)
  • Client order ids travel as each order’s IB order reference, so they are at most 128 ASCII characters

§Reconnection & Recovery

ibapi reconnects its socket to TWS/Gateway by itself, with the same client ID. In-flight requests fail with ConnectionReset at the drop, and new sends are refused until the reconnect completes. Order sends classify that as a transient OrderError::Connectivity. If the reconnect fails, ibapi shuts the client down.

ExecutionClient::account_stream stays open across a successful reconnect. It detects the gap and, once delivery is restored, recovers the fills TWS sent while the socket was down, emitting each exactly once: as a Trade, or as a TradeAmended when it corrects an earlier execution. It then reports how each order it held as live ended during the gap, if it did. The same applies when TWS loses its own link to IB’s servers (notice 1100) and later restores it (1101/1102). See that method for the details.

Each order carries its client order id as its IB order reference, which IB lists with the order, its executions and its completion. So a client finds its orders by the id they were placed with even across a restart: ExecutionClient::account_snapshot and ExecutionClient::fetch_open_orders list them under it and track them again, and OrderStatusClient finds how they ended.

§Caller Responsibilities

  1. Fill reconciliation: when fill recovery fails repeatedly, the stream reports the gap as AccountEventKind::FillRecoveryGaveUp and stays open. Read the gap’s fills with ExecutionClient::fetch_trades.
  2. Permanent disconnect: when ibapi gives up reconnecting, IbkrClient::disconnect is called, or TWS/Gateway ends the API session, account_stream ends with StreamTerminated, and account_stream on the shut-down client fails, so replace the client, by reconnecting with IbkrClient::connect_sync and choosing the client ID: the caller’s decision. The old client’s ID stays in use until every clone of it is dropped (see IbkrClient::disconnect). A new IbkrClient tracks the orders the old one placed once an account snapshot or fetch_open_orders lists them; until then their events are dropped.
  3. Stale state cleanup: Periodically call IbkrClient::clear_stale_executions, IbkrClient::clear_stale_order_ids, and IbkrClient::clear_stale_pending_cancels

Rationale: IBKR uses TCP to local TWS/Gateway, not cloud WebSocket. ibapi owns the transient reconnect. Replacing a client that is gone for good requires IB Gateway availability and client ID coordination, decisions that belong in the caller’s wrapper, not the library.

§See Also

Re-exports§

pub use order::BracketOrderRequest;
pub use order::BracketOrderResult;
pub use execution::parse_ib_timestamp;

Modules§

account
contract
Contract builders for IB integration.
execution
order

Structs§

ConnectOutcome
The result of IbkrClient::connect_sync_lenient: the connected client, and the configured contracts it connected without.
ContractConfig
Pre-configured contract for startup registration.
IbkrClient
Interactive Brokers execution client.
IbkrConfig
Configuration for the IBKR execution client.
SkippedContract
A contract in IbkrConfig::contracts that could not be registered when the client connected.

Enums§

ContractSkipReason
Why a configured contract could not be registered. Each variant carries the error of the step that failed: building, resolving or registering it.
IbkrConnectError
Why IbkrClient::connect_sync failed.