Before we begin
This week we will be accessing Interactive Brokers API through ibpy module. This requires some advanced programming concepts and working with a live system, so there are a couple of things you should be aware of:
- Never work with your production account, only use paper trading account or a demo system. All the code provided on this site is for educational purposes only.
- All code (examples and ibpy) are provided under BSD license (please read it) meaning that the author is not responsible in any way for the damage(s) the code could cause.
- Understanding the workings of ibpy and the API requires knowledge of advanced programming concepts. Depending on your background knowledge it may take quite some time before you get accustomed to using the IB API.
Nevertheless, I am aiming to get you up and running asap, by providing working examples that you can use as a starting point for your own system.
Setting up TWS
TWS is the ‘trader workstation’ from Interactive brokers. You can download it from here.
After running the installer, you can login to a demo system by using these credentials:
user name: edemo
This logs you into a demo system providing faux data.
Now you must enable API access( see screenshot below). To do this, go to Edit->Global Configuration->API->Settings
Enable ‘Enable ActiveX and Socket clients’, and add 127.0.0.1 to the trusted IP list.
IbPy is a third-party implementation of the API used for accessing the
Interactive Brokers on-line trading system. IbPy implements
functionality that the Python programmer can use to connect to IB,
request stock ticker data, submit orders for stocks and futures, and
At this moment ibpy is the best way of connecting from Python to Interactive Brokers through their API. The module was written by Troy Melhase. As of today, the code has been moved to github. No active development is done any more, however maintenance patches are done by several people, including me.
First step of installation is quite straightforward. Please *don’t* use pip or easy_install as this will result in an outdated version.
- Download code from here.
- unzip to a directory, open command prompt and run
python setup.py install
Now you should have a working installation of ibpy
Example 1: Getting live prices from TWS
In this example we will take a look at how the IB API works. It uses a minimal amount of code to keep everything as clear as possible.
Please note that ibpy does not play nice with IPython. This means that you can not run this code from a notebook. (the interpreter must be restarted after each time you run the code).
I will be using Spyder (which is a standard part of Anaconda distribution), but you are welcome to use any editor or IDE.
You can always run the code by opening a command prompt in and running
python scriptName.py , where scriptName.py is the name of the file you saved the source code to.
''' ''' Copyright: Jev Kuznetsov License: BSD Demonstration of how to stream quotes from IB. This script will subscribe to SPY and stream quotes to the sreen for 10 seconds. ''' from time import sleep from ib.ext.Contract import Contract from ib.opt import ibConnection def price_tick_handler(msg): """ function to handle price ticks """ print msg #--------------main script------------------ import ib print 'ibpy version:' , ib.__version__ tws = ibConnection() # create connection object tws.enableLogging() # show debugging output from ibpy tws.register(price_tick_handler, 'tickPrice') # register handler tws.connect() # connect to API #-------create contract and subscribe to data c = Contract() c.m_symbol = "SPY" c.m_secType= "STK" c.m_exchange = "SMART" c.m_currency = "USD" tws.reqMktData(1,c,"",False) # request market data #-------print data for a couple of seconds, then close sleep(10) print 'All done' tws.disconnect()
Once you have created a new file with the source code above, you should set it to run in a dedicated interpreter or a system terminal. To do this, go to Run->Configure->Run Configurations and select one of the two options shown in the screenshot below:
Running the code
1. Start tws, log in with your paper trading account (if you have one) or a general demo system (user:edemo pass:demouser). You should have already enabled API access as described earlier.
2. Select Run->Run from the menu or press ‘F5’ The program should run for 10 seconds and print output to the output window. The result should look like something shown below:
How it works:
IB API reference can be found online here. You should use the ‘Java’ reference.
Example 2: Tick logger application
We have gone through the basics of receiving price and volume ticks. Now we can take it to a whole new level by writing an application that logs all incoming ticks for a set of stocks to a .csv file.
The application has these fancy features:
- runs as a stand-alone program in a command prompt, can be left to run in the background
- can be started with a list of stocks to log as a command line argument
- automatically creates a .csv file with timestamp in the name for each new log
- saves all ticks as meaningful text (‘volume’ instead of number 8)
an example log looks like this:
... 2.471,SPY,size,volume,632048 2.778,SPY,size,last,1 2.778,SPY,size,volume,632050 2.778,VXX,size,bid,298 2.779,VXX,size,ask,148 3.086,SPY,size,bid,438 3.086,SPY,size,ask,302 3.397,VXX,size,bid,295 3.708,SPY,size,last,2 3.708,SPY,size,volume,632058 ...
Data format is: [time since start of log in seconds, symbol, tick type, tick subtype , value]
here is the help output of the program (it has even that):
usage: ib_logQuotes.py [-h] [-v] symbols Log ticks for a set of stocks positional arguments: symbols symbols separated by coma: SPY,VXX optional arguments: -h, --help show this help message and exit -v, --verbose show all incoming messages
Because the full source is only 150 lines of code, it is all provided below:
Example 3: Getting historic intraday data from IB
Getting historic data from IB is not as easy as it may seem. After a data request through reqHistoricalData call, a whole lot of ticks are coming in that need to be handled.
I have tried to make this process as simple as possible, almost as simple as getting data from yahoo finance. Everything is being taken care of: waiting for data to come in with a timeout, complying to max requests number from IB etc. You just get a DataFrame back when its ready. Take a look at the source code to get an idea of the mechanics involved.
Note: you might be tempted to build an automatic system that requests historic data on periodic intervals, calculates indicators and trades accordingly. This will not work. IB poses restrictions on amount of data you are allowed to download, max 60 requests per 10 minutes. The Downloader class takes care of this by logging previous requests and waiting till a request is possible.
This downloader can be used in a loop to get intraday data up to a year back.
Note: edemo account is not suitable for getting historic data.
Here is a simple example on how to get todays historic data for SPY:
# -*- coding: utf-8 -*- """ @author: Jev Kuznetsov """ import tradingWithPython as twp #---check for correct version print ('twp version', twp.__version__) from tradingWithPython.lib.interactiveBrokers import histData, createContract dl = histData.Downloader(debug=True) # historic data downloader class contract = createContract('SPY') # create contract using defaults (STK,SMART,USD) data = dl.requestData(contract,"20130508 16:00:00 EST") # request 30-second data bars up till now data.to_csv('SPY.csv') # write data to csv print ('Done')
After saving to csv file the data looks like this:
,WAP,close,count,high,low,open,volume 2013-05-08 15:30:00,162.453,162.48,1792,162.49,162.41,162.42,9602 2013-05-08 15:30:30,162.484,162.49,733,162.5,162.46,162.48,3115 2013-05-08 15:31:00,162.51,162.48,1146,162.55,162.46,162.49,4458 2013-05-08 15:31:30,162.44,162.44,668,162.49,162.41,162.49,2594 2013-05-08 15:32:00,162.498,162.5,542,162.53,162.43,162.44,1747 2013-05-08 15:32:30,162.465,162.42,895,162.51,162.42,162.5,2462 2013-05-08 15:33:00,162.416,162.41,418,162.43,162.4,162.42,1080 2013-05-08 15:33:30,162.434,162.42,411,162.46,162.41,162.42,1314 2013-05-08 15:34:00,162.402,162.39,500,162.42,162.38,162.42,1722 2013-05-08 15:34:30,162.403,162.38,478,162.43,162.38,162.39,1646
Now it can be used in a notebook for research. (use DataFrame.from_csv(‘SPY.csv’) to read csv file to a DataFrame
Example 4: Placing simple orders
Placing orders is pretty straightforward:
- create a Contract object
- create an Order object
- choose a unique numeric orderId
- place order by calling ibConnection.placeOrder(orderId, contract ,order)
One thing requires some attention though : the orderId number. Ib requires it to be a unique number, which is higher than all previous orderIds. This means you can’t just use a random generator to make up ids. The lowest valid id number is sent by the tws upon connection in NextValidId message.
The example code below executes the steps needed to place an order. It also takes care of the initial NextValidId message
After 5 seconds the order is cancelled again.
WARNING: DO NOT USE ON PRODUCTION ACCOUNT!!!
Example 5: Placing combination orders
A more extensive example of order placement is a combination order. Such an order is useful for trading pairs or baskets consisting of multiple security types. This example follows the same steps as the IB Api example.
Accessing TWS from IPython notebook
As mentioned earlier, ibpy does not work well from within the IPython notebook. However, it is often required to get the data from from TWS into the notebook for further analysis. Another reason to do that would be sending orders after executing analysis in the notebook.
Luckily, there is a fairly simple way to pass the data both ways from and to the TWS by saving csv files to disk and running .py scripts in terminal.
An example of getting the account data into the ipython notebook is shown in