Getting started with Interactive Brokers Python API on Ubuntu

Interactive brokers offer one of the lost latest Trading desktop application and best part is that it offers API access to most of the worlds leading stock exchanges. For India, Interactive brokers provide free access to NSE data (monthly account maintenance charges of INR 200) which is nothing if you compare pricing by main competitor zerodha ( Streaming INR 2000 + Historic INR 2000).

In this article, let us have a look at how to get started with Interactive Brokers API access.

Step#1  Open an account

First and foremost, you need to have funded account with Interactive Brokers. They are opening account virtually provided you have all relevant documents scanned copy.

If you need an access to market data you need to keep $500 or its equivalent in your account.  in INR, you can transfer ~40,000/- to be on safer side.

Step#2 Activate Market data.

Its takes about a week for your documents to be verified and account activation. Once your account is activated, you need to suscribe to market data using following path.

Login to web portal –> User Settings –> Market Data Suscription (Click on gear sign>–> select required exchanges and market data type–> confirm.

And you are all set.

Please note for NSE, Equity and Futures and Options market data is separate, so you need to sele

Step#3 Download TWS

You can download TWS (Traders Workstation) from here. This is one of the most advanced if you compare it with other competitors.

You might ask, I need API access, why do I need TWS ? Well, Interactive Brokers API need TWS to be installed on local machine. In a way, API piggy backs on the TWS. More on this later

Step#4 Download API Libraries

You can download API libraries from here. You can choose stable version.

Step#5 Basic Setup

Version that I downloaded is “”. This might be different for you based on latest version released by IBKR

$cd ~/Downloads
$sudo unzip -d $HOME/
$cd ~/IBJts
~/IBJts$ ls -la
total 68
drwxr-xr-x  5 userid root            4096 May 29 09:39 .
drwxr-xr-x 36 userid userid  4096 May 29 11:16 ..
-rw-r--r--  1 userid root              21 Feb  6 01:04 API_VersionNum.txt
drwxr-xr-x  2 userid userid  4096 May 28 22:38 log
drwxr-xr-x  5 userid root            4096 Feb  6 01:07 samples
drwxr-xr-x  5 userid root            4096 Feb  6 01:07 source

You can find code inside source and sample folder.

Before you start using this package, you need to install it. Go to folder twsapi_macunix.981.01–>IBJts–>source–>pythonclient

$cd Downloads/twsapi_macunix.981.01/IBJts/source/pythonclient
$ sudo python3 install

Step#6  Configure TWS

As mentioned in step#3, you need TWS. You need to enable API access in TWS by making following changes.

Go to Edit -> Global Configuration -> API -> Settings and make sure the “Enable ActiveX and Socket Clients” option is activated as shown below:

Live Account 7496
Paper Trading 7497

Step#7 Sample Code

Go to source–>pythonclient–>tests

Here you will find many sample code for various tasks

Important note:

Whenever you run API, you need to make sure TWS is running. else you will get error like below

~/IBJts$ /usr/bin/python3 "/home/conquistadorjd/IBJts/source/pythonclient/working/check_connection v"
ERROR -1 502 Couldn't connect to TWS. Confirm that "Enable ActiveX and Socket EClients" 
is enabled and connection port is the same as "Socket Port" on the 
TWS "Edit->Global Configuration...->API->Settings" menu. Live Trading ports: 
TWS: 7496; IB Gateway: 4001. Simulated Trading ports for new installations 
of version 954.1 or newer:  TWS: 7497; IB Gateway: 4002

Step#8 Sample code for you first program

from ibapi.client import EClient
from ibapi.wrapper import EWrapper  

class IBapi(EWrapper, EClient):
     def __init__(self):
         EClient.__init__(self, self) 

app = IBapi()
app.connect('', 7496, 1)

#Uncomment this section if unable to connect
#and to prevent errors on a reconnect
import time


You might get following error

traceback (most recent call last):
File "/home/userid/Downloads/twsapi_macunix.981.01/IBJts/source/pythonclient/tests/", line 1, in <module>
from ibapi.client import EClient
ModuleNotFoundError: No module named 'ibapi'

If you are seeing this error, you might have forgotten to manually install downloaded ibapi.  Go to step#5 and refer to last instruction of manually installing ibapi

How to install jupyter notebook Ubuntu

similar to any other package, before installing anything on Ubuntu run following command

$sudo apt-get update

Once system is updated to latest packages, you can install jupyter using following command

$sudo python3.6 -m pip install jupyter
WARNING: The directory '/home/username/.cache/pip' or its parent directory is not owned or is not writable by the current user. The cache has been disabled. Check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
Collecting jupyter
Downloading jupyter-1.0.0-py2.py3-none-any.whl (2.7 kB)
Collecting notebook
Downloading notebook-6.0.3-py3-none-any.whl (9.7 MB)
|████████████████████████████████| 9.7 MB 76 kB/s 
Collecting ipywidgets
Downloading ipywidgets-7.5.1-py2.py3-none-any.whl (121 kB)
|████████████████████████████████| 121 kB 294 kB/s 
Collecting nbconvert
Downloading nbconvert-5.6.1-py2.py3-none-any.whl (455 kB)
|████████████████████████████████| 455 kB 192 kB/s 
Collecting ipykernel
Downloading ipykernel-5.2.1-py3-none-any.whl (118 kB)
|████████████████████████████████| 118 kB 75 kB/s 
Collecting qtconsole
Downloading qtconsole-4.7.3-py2.py3-none-any.whl (117 kB)
|████████████████████████████████| 117 kB 126 kB/s 
Collecting jupyter-console
Downloading jupyter_console-6.1.0-py2.py3-none-any.whl (21 kB)
Collecting terminado>=0.8.1
Downloading terminado-0.8.3-py2.py3-none-any.whl (33 kB)
Collecting jupyter-client>=5.3.4
Downloading jupyter_client-6.1.3-py3-none-any.whl (106 kB)
|████████████████████████████████| 106 kB 139 kB/s 
Collecting Send2Trash
Downloading Send2Trash-1.5.0-py3-none-any.whl (12 kB)
Collecting ipython-genutils
Downloading ipython_genutils-0.2.0-py2.py3-none-any.whl (26 kB)
Collecting jinja2
Downloading Jinja2-2.11.2-py2.py3-none-any.whl (125 kB)
|████████████████████████████████| 125 kB 263 kB/s 
Collecting nbformat
Downloading nbformat-5.0.6-py3-none-any.whl (170 kB)
|████████████████████████████████| 170 kB 382 kB/s 
Collecting prometheus-client
Downloading prometheus_client-0.7.1.tar.gz (38 kB)
Collecting tornado>=5.0
Downloading tornado-6.0.4.tar.gz (496 kB)
|████████████████████████████████| 496 kB 99 kB/s 
Collecting traitlets>=4.2.1
Downloading traitlets-4.3.3-py2.py3-none-any.whl (75 kB)
|████████████████████████████████| 75 kB 82 kB/s 
Collecting pyzmq>=17
Downloading pyzmq-19.0.0-cp36-cp36m-manylinux1_x86_64.whl (1.1 MB)
|████████████████████████████████| 1.1 MB 71 kB/s 
Collecting jupyter-core>=4.6.1
Downloading jupyter_core-4.6.3-py2.py3-none-any.whl (83 kB)
|████████████████████████████████| 83 kB 212 kB/s 
Collecting widgetsnbextension~=3.5.0
Downloading widgetsnbextension-3.5.1-py2.py3-none-any.whl (2.2 MB)
|████████████████████████████████| 2.2 MB 178 kB/s 
Collecting ipython>=4.0.0; python_version >= "3.3"
Downloading ipython-7.13.0-py3-none-any.whl (780 kB)
|████████████████████████████████| 780 kB 203 kB/s 
Collecting bleach
Downloading bleach-3.1.5-py2.py3-none-any.whl (151 kB)
|████████████████████████████████| 151 kB 290 kB/s 
Collecting pygments
Downloading Pygments-2.6.1-py3-none-any.whl (914 kB)
|████████████████████████████████| 914 kB 130 kB/s 
Collecting mistune<2,>=0.8.1
Downloading mistune-0.8.4-py2.py3-none-any.whl (16 kB)
Collecting pandocfilters>=1.4.1
Downloading pandocfilters-1.4.2.tar.gz (14 kB)
Collecting testpath
Downloading testpath-0.4.4-py2.py3-none-any.whl (163 kB)
|████████████████████████████████| 163 kB 239 kB/s 
WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ReadTimeoutError("HTTPSConnectionPool(host='', port=443): Read timed out. (read timeout=15)",)': /simple/defusedxml/
Collecting defusedxml
Downloading defusedxml-0.6.0-py2.py3-none-any.whl (23 kB)
Collecting entrypoints>=0.2.2
Downloading entrypoints-0.3-py2.py3-none-any.whl (11 kB)
Collecting qtpy
Downloading QtPy-1.9.0-py2.py3-none-any.whl (54 kB)
|████████████████████████████████| 54 kB 36 kB/s 
Collecting prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0
Downloading prompt_toolkit-3.0.5-py3-none-any.whl (351 kB)
|████████████████████████████████| 351 kB 62 kB/s 
Collecting ptyprocess; os_name != "nt"
Downloading ptyprocess-0.6.0-py2.py3-none-any.whl (39 kB)
Requirement already satisfied: python-dateutil>=2.1 in /home/username/.local/lib/python3.6/site-packages (from jupyter-client>=5.3.4->notebook->jupyter) (2.8.1)
Requirement already satisfied: MarkupSafe>=0.23 in /usr/lib/python3/dist-packages (from jinja2->notebook->jupyter) (1.0)
Collecting jsonschema!=2.5.0,>=2.4
Downloading jsonschema-3.2.0-py2.py3-none-any.whl (56 kB)
|████████████████████████████████| 56 kB 106 kB/s 
Requirement already satisfied: six in /home/username/.local/lib/python3.6/site-packages (from traitlets>=4.2.1->notebook->jupyter) (1.14.0)
Collecting decorator
Downloading decorator-4.4.2-py2.py3-none-any.whl (9.2 kB)
Requirement already satisfied: pexpect; sys_platform != "win32" in /usr/lib/python3/dist-packages (from ipython>=4.0.0; python_version >= "3.3"->ipywidgets->jupyter) (4.2.1)
Collecting pickleshare
Downloading pickleshare-0.7.5-py2.py3-none-any.whl (6.9 kB)
Requirement already satisfied: setuptools>=18.5 in /home/username/.local/lib/python3.6/site-packages (from ipython>=4.0.0; python_version >= "3.3"->ipywidgets->jupyter) (45.1.0)
Collecting jedi>=0.10
Downloading jedi-0.17.0-py2.py3-none-any.whl (1.1 MB)
|████████████████████████████████| 1.1 MB 98 kB/s 
Collecting backcall
Downloading backcall-0.1.0.tar.gz (9.7 kB)
Collecting packaging
Downloading packaging-20.3-py2.py3-none-any.whl (37 kB)
Collecting webencodings
Downloading webencodings-0.5.1-py2.py3-none-any.whl (11 kB)
Collecting wcwidth
Downloading wcwidth-0.1.9-py2.py3-none-any.whl (19 kB)
Collecting attrs>=17.4.0
Downloading attrs-19.3.0-py2.py3-none-any.whl (39 kB)
Requirement already satisfied: importlib-metadata; python_version < "3.8" in /usr/local/lib/python3.6/dist-packages (from jsonschema!=2.5.0,>=2.4->nbformat->notebook->jupyter) (1.6.0)
Collecting pyrsistent>=0.14.0
Downloading pyrsistent-0.16.0.tar.gz (108 kB)
|████████████████████████████████| 108 kB 202 kB/s 
Collecting parso>=0.7.0
Downloading parso-0.7.0-py2.py3-none-any.whl (100 kB)
|████████████████████████████████| 100 kB 243 kB/s 
Collecting pyparsing>=2.0.2
Downloading pyparsing-2.4.7-py2.py3-none-any.whl (67 kB)
|████████████████████████████████| 67 kB 75 kB/s 
Requirement already satisfied: zipp>=0.5 in /usr/local/lib/python3.6/dist-packages (from importlib-metadata; python_version < "3.8"->jsonschema!=2.5.0,>=2.4->nbformat->notebook->jupyter) (3.1.0)
Building wheels for collected packages: prometheus-client, tornado, pandocfilters, backcall, pyrsistent
Building wheel for prometheus-client ( ... done
Created wheel for prometheus-client: filename=prometheus_client-0.7.1-py3-none-any.whl size=41402 sha256=1877caa0c6edd08a07b1fa309bfbdda584bd76e844bdd201b86be6d7d22cafbe
Stored in directory: /tmp/pip-ephem-wheel-cache-8bi_3gi1/wheels/1d/4a/79/a3ad3f74b3495b4555359375ca33ad7b64e77f8b7a53c8894f
Building wheel for tornado ( ... done
Created wheel for tornado: filename=tornado-6.0.4-cp36-cp36m-linux_x86_64.whl size=427632 sha256=d6aafe6d2604804cf85b680683a70cef28b97f1eb209117421a48c1aa9ab7c68
Stored in directory: /tmp/pip-ephem-wheel-cache-8bi_3gi1/wheels/37/a7/db/2d592e44029ef817f3ef63ea991db34191cebaef087a96f505
Building wheel for pandocfilters ( ... done
Created wheel for pandocfilters: filename=pandocfilters-1.4.2-py3-none-any.whl size=7855 sha256=422d885d227893b61571ea6ff8f118801dc5949559cdb74af149b10804d8ebbc
Stored in directory: /tmp/pip-ephem-wheel-cache-8bi_3gi1/wheels/46/c4/40/718c6fd14c2129ccaee10e0cf03ef6c4d01d98cad5dbbfda38
Building wheel for backcall ( ... done
Created wheel for backcall: filename=backcall-0.1.0-py3-none-any.whl size=10412 sha256=dc8f81fbfca6f8b8b1321046de42f718a1f7b1cc1ce997bbc18228a2c9d3c0ff
Stored in directory: /tmp/pip-ephem-wheel-cache-8bi_3gi1/wheels/b4/cb/f1/d142b3bb45d488612cf3943d8a1db090eb95e6687045ba61d1
Building wheel for pyrsistent ( ... done
Created wheel for pyrsistent: filename=pyrsistent-0.16.0-cp36-cp36m-linux_x86_64.whl size=97738 sha256=f6ffcf09823e6aadbd67a5b06ba106699614a0b3add6f7a0ba92a1e6fa2ea49f
Stored in directory: /tmp/pip-ephem-wheel-cache-8bi_3gi1/wheels/d1/8a/1c/32ab9017418a2c64e4fbaf503c08648bed2f8eb311b869a464
Successfully built prometheus-client tornado pandocfilters backcall pyrsistent
Installing collected packages: ptyprocess, tornado, terminado, ipython-genutils, decorator, traitlets, jupyter-core, pyzmq, jupyter-client, Send2Trash, pyparsing, packaging, webencodings, bleach, pygments, mistune, jinja2, pandocfilters, attrs, pyrsistent, jsonschema, nbformat, testpath, defusedxml, entrypoints, nbconvert, wcwidth, prompt-toolkit, pickleshare, parso, jedi, backcall, ipython, ipykernel, prometheus-client, notebook, widgetsnbextension, ipywidgets, qtpy, qtconsole, jupyter-console, jupyter
Successfully installed Send2Trash-1.5.0 attrs-19.3.0 backcall-0.1.0 bleach-3.1.5 decorator-4.4.2 defusedxml-0.6.0 entrypoints-0.3 ipykernel-5.2.1 ipython-7.13.0 ipython-genutils-0.2.0 ipywidgets-7.5.1 jedi-0.17.0 jinja2-2.11.2 jsonschema-3.2.0 jupyter-1.0.0 jupyter-client-6.1.3 jupyter-console-6.1.0 jupyter-core-4.6.3 mistune-0.8.4 nbconvert-5.6.1 nbformat-5.0.6 notebook-6.0.3 packaging-20.3 pandocfilters-1.4.2 parso-0.7.0 pickleshare-0.7.5 prometheus-client-0.7.1 prompt-toolkit-3.0.5 ptyprocess-0.6.0 pygments-2.6.1 pyparsing-2.4.7 pyrsistent-0.16.0 pyzmq-19.0.0 qtconsole-4.7.3 qtpy-1.9.0 terminado-0.8.3 testpath-0.4.4 tornado-6.0.4 traitlets-4.3.3 wcwidth-0.1.9 webencodings-0.5.1 widgetsnbextension-3.5.1


Yeah, this is pretty long list of packages required for jupyter. !

Once installation is completed, you can start jupyter using following command

$ jupyter notebook --allow-root
[I 20:44:06.979 NotebookApp] The port 8888 is already in use, trying another port.
[I 20:44:06.982 NotebookApp] Serving notebooks from local directory: /home/username/code/quant
[I 20:44:06.982 NotebookApp] The Jupyter Notebook is running at:
[I 20:44:06.982 NotebookApp] http://localhost:8889/?token=94cc0863965bf1d2751ad8a7a4b26d08f1b9f0be4f380c9a
[I 20:44:06.982 NotebookApp] or
[I 20:44:06.982 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[C 20:44:06.987 NotebookApp]

To access the notebook, open this file in a browser:
Or copy and paste one of these URLs:
[W 20:44:09.233 NotebookApp] 404 GET /api/kernels/7f717081-a79b-4170-b5be-c7e548ea28c7/channels?session_id=a53b179c3d2c4deda89418767c9bb6b9 ( Kernel does not exist: 7f717081-a79b-4170-b5be-c7e548ea28c7
[W 20:44:09.249 NotebookApp] 404 GET /api/kernels/7f717081-a79b-4170-b5be-c7e548ea28c7/channels?session_id=a53b179c3d2c4deda89418767c9bb6b9 ( 19.55ms referer=None

and then you can access your jupyter notebooks at http://localhost:8889
Here is how it looks

Hope this helps.