YATWS (Yet Another TWS API)
A comprehensive, thread-safe, type-safe, and ergonomic Rust interface to the Interactive Brokers TWS API.
Overview
YATWS provides a modern Rust implementation for interacting with Interactive Brokers' Trader Workstation (TWS) and Gateway. The library's manager-based architecture and support for both synchronous and asynchronous patterns make it suitable for various trading applications, from simple data retrieval to complex automated trading systems.
This library was born out of the need to place orders in rapid succession in response to market events, which is not easily accomplished with existing Rust crates. It takes about 3ms to place an order with this library. While order management was the primary focus, other interfaces (market data, account information, etc.) have been implemented for completeness.
Current Status: Early stage but US equity trading is production-ready. The API has been used to trade 9 figures of dollars in volume.
Features
- Comprehensive API Coverage: Access to orders, accounts, market data, fundamentals, news, and reference data
- Book-keeping: Keeps the portfolio with PNL and order book up-to-date
- Multiple Programming Patterns:
- Synchronous blocking calls with timeouts
- Asynchronous observer pattern
- Subscription model
- Options Strategy Builder: Simplified creation of common options strategies
- Strong Type Safety: Leverages Rust's type system for safer API interactions
- Domain-Specific Managers: Organized access to different API functionalities
- Rate limits: pace the requests in accordance with IBKR rules
- Session Recording/Replay: Record TWS interactions for testing and debugging
Architecture
YATWS follows a client-manager architecture:
- Core Client (
IBKRClient): Central connection point to TWS/Gateway - Specialized Managers: Domain-specific functionality organized into managers:
OrderManager: Order placement, modification, and trackingAccountManager: Account and portfolio data (summary, positions, P&L, executions, liquidation warnings)DataMarketManager: Real-time and historical market dataDataRefManager: Reference data (contract details, etc.)DataNewsManager: News headlines and articlesDataFundamentalsManager: Financial dataFinancialAdvisorManager: Financial Advisor configurations (groups, profiles, aliases)
Usage Examples
Establishing a Connection
// Connect to TWS/Gateway
let client = new?;
// Alternative: Record session to SQLite database
let client = new?;
// Replay a recorded session
let replay_client = from_db?;
Account Information
// Subscribe to account updates
client.account.subscribe_account_updates?;
// Get account summary
let info = client.account.get_account_info?;
println!;
// Get a single specific value.
use AccountValueKey;
let buying_power_value = client.account.get_account_value?;
if let Some = buying_power_value
// List positions
let positions = client.account.list_open_positions?;
// Get today's executions
let executions = client.account.get_day_executions?;
// Check for pre-liquidation warning
if client.account.has_received_pre_liquidation_warning
Order Management
// Create and place an order using OrderBuilder
let = new
.for_stock
.with_exchange
.with_currency
.limit
.with_tif
.build?;
let order_id = client.orders.place_order?;
// Wait for order to be filled (with timeout)
let status = client.orders.try_wait_order_executed?;
Order Subscription Pattern
For tracking order lifecycle with real-time updates:
use ;
use OrderEvent;
use Duration;
// Create order specification
let = new
.for_stock
.market
.with_tif
.build?;
// Subscribe to order lifecycle events
let order_subscription = client.orders.subscribe_new_order?;
let mut order_events = order_subscription.events;
// Process order events until completion or error
while let Some = order_events.try_next
Market Data
// Get a simple quote
let = client.data_market.get_quote?;
// Get historical data
use DurationUnit;
let bars = client.data_market.get_historical_data?;
Options Strategies
// Create a bull call spread
let builder = new?;
let = builder
.bull_call_spread?
.with_limit_price // Debit of $3.50 per spread
.build?;
let order_id = client.orders.place_order?;
Financial Advisor Configuration
// Access the FinancialAdvisorManager
let fa_manager = client.financial_advisor;
// Request FA Groups data
fa_manager.request_fa_data?;
// Get the current FA configuration
let fa_config = fa_manager.get_config;
println!;
Asynchronous Event Handling
YATWS supports an observer pattern for handling asynchronous events. This is a push programming model where events are pushed to you. You initiate the request and implement on_event methods. This is the closest to the official IBKR TWS API, except you have observers split by functionality rather than a single EWrapper.
This is best suited for event-driven trading, such as reacting to news, order fills and buying power depletion.
Market Data Observer Example
use ;
use ;
use thread;
use Duration;
Subscriptions
Simimlar to the ibapi crate, you can use a subscription programming model. This is in-between the sync and async models desribed above. This is best suited for receiving a stream of data. This is a pull model where you receive an iterator of events.
Account Subscription Example
use ;
use ;
use Duration;
use thread;
News Subscription Example
use ;
use Duration;
use thread;
Advanced Features
Session Recording and Replay
// Enable session recording
let client = new?;
// Later, replay the session
let replay_client = from_db?;
Order Conditions
// Create a price-conditional order
let = new
.for_stock
.limit
.add_price_condition
.build?;
Rate Limiting
YATWS provides built-in rate limiting to ensure compliance with Interactive Brokers' API limits:
// Enable rate limiting with default settings (50 msgs/sec, 50 historical requests, 100 market data lines)
client.enable_rate_limiting?;
// Configure custom rate limiting settings
let mut config = default;
config.enabled = true;
config.max_messages_per_second = 40; // Be more conservative
config.max_historical_requests = 30; // Lower than default 50
config.rate_limit_wait_timeout = from_secs; // Longer timeout
client.configure_rate_limiter?;
// Check current rate limiter status
if let Some = client.get_rate_limiter_status
// Disable rate limiting when needed
client.disable_rate_limiting?;
// Clean up stale requests (useful for long-running applications)
let = client.cleanup_stale_rate_limiter_requests?;
println!;
Error Handling
YATWS uses Rust's Result pattern consistently, with a custom IBKRError type:
match client.account.get_net_liquidation
API Reference
For detailed information about the available functions, structs, and traits, please refer to the API documentation on docs.rs or the API reference on GitHub.
Key components include:
IBKRClient: Primary client for interacting with the TWS APIOrderManager: Order-related operationsAccountManager: Account and portfolio data (including liquidation warning status)DataMarketManager: Market data operationsDataRefManager: Reference dataDataNewsManager: News dataDataFundamentalsManager: Financial dataFinancialAdvisorManager: Financial Advisor configurationsOrderBuilder: Fluent API for creating ordersOptionsStrategyBuilder: Factory for common options strategies