Algorithmic Trading on Interactive Brokers using Python

Consulting Services

Are you interested in developing an automated algorithm to trade on Interactive Brokers? Have a successful strategy already that you want automated in order to monitor a large number of data streams? Want your strategy backtested and optimized? We offer algorithmic trading consulting services for Interactive Brokers, including: algorithm implementation in python or C++, data analysis, backtesting and machine learning. Please get in touch to learn more!

About Interactive Brokers

Interactive Brokers is a large US-based brokerage firm dealing in stocks, ETFs, options, bonds and forex. Since 2021, it also offers cryptocurrency spot and futures trading.

Initial setup

Although Interactive Brokers also supports C#, C++, Java and VB, most people will probably prefer the convenience of python unless they are doing high frequency trading or their strategy is computationally demanding.

Of course, the first step is always to open an account with the broker which you can do here.

Getting setup to do algo trading on Interactive Brokers requires a few more steps than many other brokers. You’ll need to download and install their python API and their Trader Work Station app (TWS). The latter must be running in the background while you run your algo from your favourite python IDE.

After creating an ordinary account with Interactive Brokers, TWS gives you the option to log in with a paper trading account to allow you to test your algo code without making live trades. Paper accounts (otherwise known as test or demo accounts) usually have the limitation that the order book is not simulated, so they are useful for testing your code and learning how to use the API, but not always for evaluating the profitability of your strategy.

Before trying to connect using your python IDE, make sure “Enable ActiveX and Socket Clients” is ticked under File > Global Configuration > API > Settings.

Python initialization

The next step is to start reading IB’s API documentation to learn about the functionality.

These are some import statements you want at the beginning of your code:

from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.contract import Contract
from ibapi.order import Order

And these statements will initialize the connection to the broker.

app = IBapi()
app.connect(‘127.0.0.1’, 7497, 123)

The number 7497 is the socket port which can be found in the API settings in TWS mentioned above. The client ID can be an arbitrary positive integer. The EClientSocket class is used to send data to the TWS application, while the EWrapper interface is used to receive data from the TWS application.

Historical and streaming data

Using Interactive Broker’s API is slightly more complicated than for some other exchanges. As they explain in the API documentation here, the EWrapper interface needs to be implemented/overwritten by you to specify what should happen with data you request. So certain functions in the IBapi class will need to be implemented/overwritten to send the data where you want it to go. For example, to request historical data, I like to overwrite the historicalData function like this:

class IBapi(EWrapper, EClient):
def init(self):
EClient.init(self, self)
def historicalData(self, reqId, bar):
data.append(bar)

def grab_historical_data():
data = []
app.reqHistoricalData(1, eurusd_contract, ”, ’90 D’, ‘1 day’, ‘MIDPOINT’, 0, 2, False, [])
return data

This will grab daily price data for the last 90 days. It appears to use business days rather than calendar days. The interval of 90 days is calculated from the prior day’s close, so the last datapoint should be yesterday’s. Note that each day’s data contains open, close, high and low values. The variable eurusd_contract is actually a contract object which we’ll explain shortly.

If instead of getting historical data you wish to stream the latest price data as it becomes available, you want to overwrite the tickdata function use the function reqMktData as follows.

class IBapi(EWrapper, EClient):
def init(self):
EClient.init(self, self)
def tickPrice(self, reqId, tickType, price, attrib):
if tickType == 2 and reqId == 1:
print(‘The current ask price is: ‘, price)
latest_ask.append(price)

latest_ask = []
app.reqMktData(1, eurusd_contract, ”, False, False, [])

The tickType of 2 here filters for the ask price. If you want bid, high or low you can use 1 ,6 and 7 respectively.

Creating contracts and placing orders

Contract objects specify the underlying for which you wish to obtain price data or place orders. They can be created as follows:

eurusd_contract = Contract()
eurusd_contract.symbol = ‘EUR’
eurusd_contract.secType = ‘CASH’
eurusd_contract.exchange = ‘IDEALPRO’
eurusd_contract.currency = ‘USD’

In order to place an order on a given contract you must also create an order object, such as this:

eurusd_order = Order()
eurusd_order.action = ‘SELL’
eurusd_order.totalQuantity = 500
eurusd_order.orderType = ‘LMT’
eurusd_order.lmtPrice = ‘1.1389’

To place the order, you can use the placeOrder function:

app.placeOrder(1, eurusd_contract, eurusd_order)

The first number is an arbitrary integer used to ID the order.