Part 4 – Going live

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
password: demouser
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.

TWS can now accept connections.

IBPY installation

 

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
more.

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.

Step-by-step install

First step of installation is quite straightforward. Please *don’t* use pip or easy_install as this will result in an outdated version.

  1. Download code from here.
  2. 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()

Configuring Spyder

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]

Get the code

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:

  1. create a Contract object
  2. create an Order object
  3. choose a unique numeric orderId
  4. 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!!!

See example code

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.

See example code

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

twp_401_portfolioData.ipynb