IB-insync
ib-insync is a Pythonic framework for Interactive Brokers API, offering both synchronous and asynchronous interfaces. It abstracts much of the complexity of the underlying `ibapi` library, providing a high-level, event-driven API for trading, market data, and account management. The current version is 0.9.86, and the library maintains a frequent release cadence with minor updates and bug fixes.
Common errors
-
ConnectionRefusedError: [Errno 61] Connection refused
cause The client (your Python script) tried to connect to a port where no TWS or IB Gateway listener was active, or a firewall blocked the connection.fixEnsure TWS or IB Gateway is running. Verify the correct port (default TWS: 7497, Gateway: 4002) is being used. Check firewall settings on your machine. -
ibapi.common.IBAPIError: API error (id=-1, errorCode=502, errorString=Can't connect to TWS. It is possible that TWS is not running.)
cause The Interactive Brokers API client library (`ibapi`) received an error from TWS/Gateway, typically indicating a connection problem or that the API is not ready to accept connections.fixConfirm TWS/IB Gateway is fully launched and logged in. Check API settings in TWS/Gateway (File -> Global Configuration -> API -> Settings) to ensure 'Enable ActiveX and Socket Clients' is active and a valid IP (127.0.0.1) is added if restricting by IP. -
ibapi.common.IBAPIError: No security definition has been found for the request.
cause The contract you defined is ambiguous or invalid according to Interactive Brokers' system. This often happens if key fields like `exchange`, `currency`, or `primaryExchange` are missing or incorrect, or if `ib.qualifyContracts()` wasn't called.fixAlways call `await ib.qualifyContracts(contract)` after defining a contract. Double-check all contract fields (`symbol`, `secType`, `exchange`, `currency`, `primaryExchange`) for accuracy. Use `ib.reqContractDetails(contract)` to search for valid contract definitions. -
RuntimeWarning: coroutine '...' was never awaited
cause An asynchronous `ib-insync` method (which returns a coroutine) was called but was not `await`ed, leading to it never being executed.fixEnsure all `ib-insync` methods that are designed to be `await`able (most network operations) are preceded by `await` when called from within an `async def` function. If in a synchronous context, consider using `ib.run()` or converting your script to use `asyncio.run()`.
Warnings
- breaking ibapi (Interactive Brokers API) version compatibility. ib-insync relies on the underlying ibapi library, which receives frequent updates. Mismatches between ib-insync and ibapi versions can lead to unexpected behavior or API errors.
- gotcha Synchronous vs. Asynchronous execution. ib-insync supports both. Using `ib.run()` directly blocks the main thread, while `await ib.run()` (or `asyncio.run(main())`) is for asynchronous use. Mixing these incorrectly or forgetting `await` can lead to deadlocks or `RuntimeWarning`s.
- gotcha TWS/Gateway connection issues. Common problems include 'Connection refused', 'errorCode=502', or 'Not connected' due to TWS/Gateway not running, incorrect port, firewall blocking, or API settings not allowing socket connections.
- gotcha Market Data Subscriptions. Many market data requests (e.g., `reqMktData`, `reqHistoricalData` for certain `whatToShow` values) will fail with 'Market data farm is disconnected' or 'Not subscribed to market data' errors if you do not have the required market data subscriptions on your Interactive Brokers account.
Install
-
pip install ib-insync ibapi
Imports
- IB
from ib_insync import IB
- Stock
from ib_insync import Stock
- Contract
from ib_insync import Contract
- util
from ib_insync import util
Quickstart
import asyncio
from ib_insync import IB, Stock, util
async def main():
ib = IB()
# Connect to TWS or IB Gateway on default port 7497 (TWS) or 4002 (Gateway)
# Ensure TWS/Gateway is running and API settings allow connection (File -> Global Configuration -> API -> Settings).
try:
await ib.connect('127.0.0.1', 7497, clientId=1)
print("Connected to Interactive Brokers API.")
# Define a contract (e.g., Apple stock)
contract = Stock('AAPL', 'SMART', 'USD')
# Qualify the contract to ensure it's valid and get full details
# This step is crucial to avoid 'No security definition' errors
await ib.qualifyContracts(contract)
print(f"Qualified contract: {contract.conId} - {contract.longName}")
# Request historical data for the contract
# Requires an active market data subscription for 'TRADES' or 'MIDPOINT'
bars = await ib.reqHistoricalData(
contract,
endDateTime='',
durationStr='1 D', # Request 1 day of data
barSizeSetting='1 min',
whatToShow='TRADES',
useRTH=True, # Use regular trading hours
formatDate=1 # Return datetime objects
)
print(f"Received {len(bars)} historical bars for {contract.symbol}.")
if bars:
print(f"Last bar: Time={bars[-1].date}, Open={bars[-1].open}, Close={bars[-1].close}")
except Exception as e:
print(f"An error occurred: {e}")
finally:
if ib.isConnected():
ib.disconnect()
print("Disconnected from Interactive Brokers API.")
if __name__ == '__main__':
asyncio.run(main())