ib-underscore-async-index.md
ib_async is a Python library that provides a clean, modern interface to Interactive Brokers’ Trader Workstation (TWS) and IB Gateway. It handles the complexities of the IBKR API so you can focus on building trading applications, research tools, and market data analysis.
Market Data Applications : Stream live quotes, historical data, and market depth
Trading Systems : Place, modify, and monitor orders programmatically
Portfolio Tools : Track positions, account balances, and P&L in real-time
Research Platforms : Analyze contract details, option chains, and fundamental data
Risk Management : Monitor exposures and implement automated controls
Simple and Intuitive : Write straightforward Python code without dealing with callback complexity
Automatic Synchronization : The IB component stays in sync with TWS/Gateway automatically
Async-Ready : Built on asyncio and eventkit for high-performance applications
Jupyter-Friendly : Interactive development with live data in notebooks
Production-Ready : Robust error handling, reconnection logic, and comprehensive logging
Be sure to take a look at the notebooks, the recipes and the API docs.
pipinstallib\_async
Requirements:
Python 3.10 or higher
A running IB Gateway application (or TWS with API mode enabled)
Make sure the API port is enabled and ‘Download open orders on connection’ is checked.
You may also want to increase the Java memory usage under Configure->Settings->Memory Allocation to 4096 MB minimum to prevent gateway crashes when loading bulk data.
The ibapi package from IB is not needed. ib_async implements the full IBKR API binary protocol internally.
First, install poetry:
pipinstallpoetry-U
poetryinstall
poetryinstall--with=docs,dev
poetryinstall--with=docspoetryrunsphinx-build-bhtmldocshtml
poetryrunmypyib\_async
poetrybuild
poetryinstallpoetryconfigpypi-token.pypiyour-api-tokenpoetrypublish--build
IB Gateway (Stable) — Updated every few months, more stable
IB Gateway (Latest) — Updated weekly, newest features
Trader Workstation (TWS) — Full trading platform
Enable API : Go to Configure → API → Settings and check “Enable ActiveX and Socket Clients”
Set Port : Default ports are 7497 (TWS) and 4001 (Gateway). You can change these if needed.
Allow Connections : Add 127.0.0.1 to “Trusted IPs” if connecting locally
Download Orders : Check “Download open orders on connection” to see existing orders
Memory : Go to Configure → Settings → Memory Allocation and set to 4096 MB minimum to prevent crashes with bulk data
Timeouts : Increase API timeout settings if you experience disconnections during large data requests
Connection Refused
# Make sure TWS/Gateway is running and API is enabled# Check that ports match (7497 for TWS, 4001 for Gateway)ib.connect('127.0.0.1',7497,clientId=1)# TWSib.connect('127.0.0.1',4001,clientId=1)# Gateway
Client ID Conflicts
# Each connection needs a unique client IDib.connect('127.0.0.1',7497,clientId=1)# Use different numbers for multiple connections
Market Data Issues
# For free delayed data (no subscription required)ib.reqMarketDataType(3)# Delayedib.reqMarketDataType(4)# Delayed frozen# For real-time data (requires subscription)ib.reqMarketDataType(1)# Real-time
from ib\_async import\*ib=IB()ib.connect('127.0.0.1',7497,clientId=1)# Your code hereib.disconnect()
from ib\_async import\*util.startLoop()# Required for notebooksib=IB()ib.connect('127.0.0.1',7497,clientId=1)# Your code here - no need to call ib.run()
import asynciofrom ib\_async import\*asyncdef main():ib=IB()awaitib.connectAsync('127.0.0.1',7497,clientId=1)# Your async code hereib.disconnect()asyncio.run(main())
from ib\_async import\*# Connect to TWS or IB Gatewayib=IB()ib.connect('127.0.0.1',7497,clientId=1)print("Connected")# Disconnect when doneib.disconnect()
from ib\_async import\*ib=IB()ib.connect('127.0.0.1',7497,clientId=1)# Get account summaryaccount=ib.managedAccounts()[0]summary=ib.accountSummary(account)foriteminsummary:print(f"{item.tag}: {item.value}")ib.disconnect()
from ib\_async import\*# util.startLoop() # uncomment this line when in a notebookib=IB()ib.connect('127.0.0.1',7497,clientId=1)# Request historical datacontract=Forex('EURUSD')bars=ib.reqHistoricalData(contract,endDateTime='',durationStr='30 D',barSizeSetting='1 hour',whatToShow='MIDPOINT',useRTH=True)# Convert to pandas dataframe (pandas needs to be installed):df=util.df(bars)print(df.head())ib.disconnect()
from ib\_async import\*import timeib=IB()ib.connect('127.0.0.1',7497,clientId=1)# Subscribe to live market datacontract=Stock('AAPL','SMART','USD')ticker=ib.reqMktData(contract,'',False,False)# Print live quotes for 30 secondsforiinrange(30):ib.sleep(1)# Wait 1 secondifticker.last:print(f"AAPL: ${ticker.last} (bid: ${ticker.bid}, ask: ${ticker.ask})")ib.disconnect()
from ib\_async import\*ib=IB()ib.connect('127.0.0.1',7497,clientId=1)# Create a contract and ordercontract=Stock('AAPL','SMART','USD')order=MarketOrder('BUY',100)# Place the ordertrade=ib.placeOrder(contract,order)print(f"Order placed: {trade}")# Monitor order statuswhilenottrade.isDone():ib.sleep(1)print(f"Order status: {trade.orderStatus.status}")ib.disconnect()
from ib\_async import\*ib=IB()ib.connect('127.0.0.1',7497,clientId=1)# Get current positionspositions=ib.positions()print("Current Positions:")forposinpositions:print(f"{pos.contract.symbol}: {pos.position} @ {pos.avgCost}")# Get open ordersorders=ib.openTrades()print(f"\nOpen Orders: {len(orders)}")fortradeinorders:print(f"{trade.contract.symbol}: {trade.order.action} {trade.order.totalQuantity}")ib.disconnect()
from ib\_async import\*def onPnL(pnl):print(f"P&L Update: Unrealized: ${pnl.unrealizedPnL:.2f}, Realized: ${pnl.realizedPnL:.2f}")ib=IB()ib.connect('127.0.0.1',7497,clientId=1)# Subscribe to P&L updatesaccount=ib.managedAccounts()[0]pnl=ib.reqPnL(account)pnl.updateEvent+=onPnL# Keep running to receive updatestry:ib.run()# Run until interruptedexceptKeyboardInterrupt:ib.disconnect()
from ib\_async import\*ib=IB()ib.connect('127.0.0.1',7497,clientId=1)# Create a bracket order (entry + stop loss + take profit)contract=Stock('TSLA','SMART','USD')# Parent orderparent=LimitOrder('BUY',100,250.00)parent.orderId=ib.client.getReqId()parent.transmit=False# Stop lossstopLoss=StopOrder('SELL',100,240.00)stopLoss.orderId=ib.client.getReqId()stopLoss.parentId=parent.orderIdstopLoss.transmit=False# Take profittakeProfit=LimitOrder('SELL',100,260.00)takeProfit.orderId=ib.client.getReqId()takeProfit.parentId=parent.orderIdtakeProfit.transmit=True# Place bracket ordertrades=[]trades.append(ib.placeOrder(contract,parent))trades.append(ib.placeOrder(contract,stopLoss))trades.append(ib.placeOrder(contract,takeProfit))print(f"Bracket order placed: {len(trades)} orders")ib.disconnect()
from ib\_async import\*import pandas as pdib=IB()ib.connect('127.0.0.1',7497,clientId=1)# Get multiple timeframescontract=Stock('SPY','SMART','USD')# Daily bars for 1 yeardaily\_bars=ib.reqHistoricalData(contract,endDateTime='',durationStr='1 Y',barSizeSetting='1 day',whatToShow='TRADES',useRTH=True)# 5-minute bars for last 5 daysintraday\_bars=ib.reqHistoricalData(contract,endDateTime='',durationStr='5 D',barSizeSetting='5 mins',whatToShow='TRADES',useRTH=True)# Convert to DataFramesdaily\_df=util.df(daily\_bars)intraday\_df=util.df(intraday\_bars)print(f"Daily bars: {len(daily\_df)} rows")print(f"Intraday bars: {len(intraday\_df)} rows")# Calculate simple moving averagedaily\_df['SMA\_20']=daily\_df['close'].rolling(20).mean()print(daily\_df[['date','close','SMA\_20']].tail())ib.disconnect()
ib_async.ib.IB - Main interface class
Connection management (connect(), disconnect(), connectAsync())
Market data requests (reqMktData(), reqHistoricalData())
Order management (placeOrder(), cancelOrder())
Account data (positions(), accountSummary(), reqPnL())
ib_async.contract - Financial instruments
Stock, Option, Future, Forex, Index, Bond
Contract - Base class for all instruments
ComboLeg, DeltaNeutralContract - Complex instruments
ib_async.order - Order types and management
MarketOrder, LimitOrder, StopOrder, StopLimitOrder
Order - Base order class with all parameters
OrderStatus, OrderState - Order execution tracking
Trade - Complete order lifecycle tracking
ib_async.ticker - Real-time market data
Ticker - Live quotes, trades, and market data
Automatic field updates (bid, ask, last, volume, etc.)
Event-driven updates via updateEvent
ib_async.objects - Data structures
BarData - Historical price bars
Position - Portfolio positions
PortfolioItem - Portfolio details with P&L
AccountValue - Account metrics
Synchronous vs Asynchronous
# Synchronous (blocks until complete)bars=ib.reqHistoricalData(contract,...)# Asynchronous (yields to event loop)bars=awaitib.reqHistoricalDataAsync(contract,...)
Event Handling
# Subscribe to eventsdef onOrderUpdate(trade):print(f"Order update: {trade.orderStatus.status}")ib.orderStatusEvent+=onOrderUpdate# Or with asyncasyncdef onTicker(ticker):print(f"Price update: {ticker.last}")ticker.updateEvent+=onTicker
Error Handling
try:ib.connect('127.0.0.1',7497,clientId=1)exceptConnectionRefusedError:print("TWS/Gateway not running or API not enabled")exceptExceptionase:print(f"Connection error: {e}")
The complete API documentation.
poetry install --with=dev
poetry run pytest
poetry run mypy ib_async
poetry run ruff format
poetry run ruff check --fix
git clone https://github.com/ib-api-reloaded/ib_async.gitcd ib_async
poetry install --with=dev,docs
poetry run pytest
poetry run mypy ib_async
Follow existing code style (enforced by ruff)
Add tests for new features
Update documentation for user-facing changes
Keep commits focused and well-described
Be responsive to code review feedback
If you have other public work related to ib_async or ib_insync open an issue and we can keep an active list here.
Projects below are not endorsed by any entity and are purely for reference or entertainment purposes.
Adi’s livestream VODs about using IBKR APIs: Interactive Brokers API in Python
Matt’s IBKR python CLI: icli
Corporate data parsing via IBKR API: ib_fundamental
The software is provided on the conditions of the simplified BSD license.
This project is not affiliated with Interactive Brokers Group, Inc.
Official Interactive Brokers API Docs
This library was originally created by Ewald de Wit as tws_async in early-2017 then became the more prominent ib_insync library in mid-2017. He maintained and improved the library for the world to use for free until his unexpected passing in early 2024. Afterward, we decided to rename the project to ib_async under a new github organization since we lost access to modify anything in the original repos and packaging and docs infrastructure.
The library is currently maintained by Matt Stancliff and we are open to adding more committers and org contributors if people show interest in helping out.