Interactive Brokers offers an advanced application programming interface (API) that is available to retail brokers allowing for the creating of advanced algorithmic trading strategies. In this series of articles we are going to dive into how to use the API to connect to the broker, stream real time quotes, retrieve historical data, manage positions and much more. This article assumes that the reader has an account with Interactive Brokers and the account has permissions for real-time data.
In this first article we will discuss setting up your development environment and connecting to the Interactive Brokers servers. We are going to use the Python programming language to manage our connection to the Interactive Brokers servers and we are going to stream real-time bid, ask and last price quotes. The Python API was only introduced as an officially supported language by Interactive Brokers fairly recently but is stable and easy to use.
The output you will see will look something like this;
If you do not have Python on your system a good place to start would be to install the Anaconda Python distribution. This makes getting started with Python extremely easy. The installer can be found here;
For this article we are using the Windows 64bit installer of Python version 3.6
Getting the API software
To interact with the Interactive Brokers (IB) servers you need to have the Trader Workstation (TWS) API software. It is available on the IB Github page and can be found here;
The TWS API is a programming interface to the IB TWS and as such an instance of TWS is required to connect to. You can do this by either running TWS or by running the IB Gateway. For our purposes running the Gateway is preferable as it’s a lightweight application and we are not going to use any of the features of the TWS application.
Before you start
Before we can connect to the IB Gateway we need to allow connections to TWS. It needs to be configured to listen for incoming API connections on a very specific port. Please refer to this IB page to setup your TWS settings: https://interactivebrokers.github.io/tws-api/initial_setup.html#gsc.tab=0
Getting the code
The full example code for this article can be found here: https://github.com/scalptrader/ScalpTrader-IBTWS
In the repository you will see a couple of Python files and a folder called ibapi which is the IB TWS API files that you downloaded from the IB servers above.
We will be looking into the main file, ibclient.py. The file logger.py is a simple logging class that creates log files.
The IBClient class performs all the logic required to connect to the IB TWS and start streaming real-time data. Let’s look at the main parts of the code starting at the main entry point
The first thing we do is start logging. It’s useful to log the start time to know how long your connection lasted
logger.debug("Start time is %s" % datetime.datetime.now())
Next we create our application
app = IBClientApp()
If you take a look at the IBClientApp class constructor you will see that it is derived from the IBWrapper and IBClient classes
class IBClientApp(IBWrapper, IBClient):
These are the IB TWS API classes that allow us to connect to the IB TWS service. The next line connects us to the IB TWS servers
app.connect("127.0.0.1", 4001, clientId=0)
Remember we are running the IB Gateway and have set that up to allow connections on port 4001 (specified in the connect args)
We check to see if the application connected successfully. If it did, we then request real-time market data for the symbol CLK7 which is the symbol for the WTI Crude Oil futures contract for May 2017
if( app.isConnected() ): # Request tick data for WTI Crude futures contract (May 2017) symbol = 'CLK7' app.requestMarketData(symbol) app.run()
Once we have called the app.run() method the application will wait for event callbacks from the IB TWS API. You will get the callbacks as long as you have a wrapper for the tickPrice and tickSize methods
@iswrapper def tickPrice(self, reqId: TickerId, tickType: TickType, price: float, attrib: TickAttrib): super().tickPrice(reqId, tickType, price, attrib)
@iswrapper def tickSize(self, reqId: TickerId, tickType: TickType, size: int): super().tickSize(reqId, tickType, size
When those methods get called you will receive a tickType.
This will be one of the enums that is defined in the IB TWS API
# From TickTypeEnum # 0 BID_SIZE # 1 BID # 2 ASK # 3 ASK_SIZE # 4 LAST # 5 LAST_SIZE # 8 VOLUME
As you can see it’s easy to pull out the latest bid, ask and last quotes along with the volume for each tick that the IB TWS gives us.
That’s really all there is to it. The IB TWS API makes it very easy for the Python programmer to access fast, reliable market data with minimal application code.