When investing or trading there’s a lot of research, analysis, and work going on behind every trade. Generally this is very time consuming and prone to error, and is very easy to miss a potential trade or entry point that you prepared in advance just because we were not ready that day, or something else came up that took your attention away.
Even if you have all the alerts and indicators you’d like by hand, manually checking these for all stocks in your watchlist can be a productivity drain, so in order to save time and plan trades more effectively I’m starting to build my own tools, using Python and the Interactive Brokers API ( both IB and TWS ).
This initial post will go through the process of connecting to the client and getting some data back into our terminal. Once everything is plugged and communicating together, then we can start to build stuff.
Latest update: 2021-06-14
Let’s start by creating an initial starting Python script ( I named mine ibkr_gateway_test.py ):
from ibapi.client import EClient from ibapi.wrapper import EWrapper import time class IBapi(EWrapper, EClient): def __init__(self): EClient.__init__(self, self) app = IBapi() app.connect('127.0.0.1', 7497, 1234) app.run() print("TEST successful: The app will stop running in 5 seconds...") time.sleep(5) app.disconnect()
What is what:
- EClient: Handles all outgoing requests to the API.
- EWrapper: Handles incoming data from the API.
- IBapi(): Our main class.
- app: Our instance of the IBapi class.
- connect(ip, args.port, clientId): We’ll use 127.0.0.1 as our IP (localhost), the port will be given depending on how are you connecting and if this is live or paper trading, and the clientId is used to identify your script to the API. It can be any unique positive integer.
- run(): Once the client is connected, a reader thread will be automatically created to handle incoming messages and put the messages into a message queue for further process. User is required to trigger Client::run(), where the message queue is processed.
- disconnect(): Closes the connection.
The way this API works is a bit different that the most use-cases: We’re not creating and consuming web API requests, but instead we’re using a network socket connection to the TWS application. In a nutshell: We’re sending and receiving instructions to the TWS application, and this will contain all the login to interact with the Interactive Brokers servers. We’re making a network socket application.
Most likely at this point you’ll try to run your script and you’ll face the first error message ( as I did ): ModuleNotFoundError: No module named ‘ibapi’ .
Well, this is because the official Interactive Brokers API is not in the Python Package Index (PyPI) because its distributed under a different license. We’ll install this module via a Python Wheel:
- Download “API Latest” from http://interactivebrokers.github.io/
- Unzip or install (if its a .msi file) the download.
- Go to tws-api/source/pythonclient/
- Build a wheel with: python3 setup.py bdist_wheel
- Install the wheel with: python3 -m pip install –user –upgrade dist/ibapi-9.76.1-py3-none-any.whl
If you see a new error message here, as error: invalid command ‘bdist_wheel’ , you will need to install this module first in your system:
python3 pip install wheel
At this point all should work correctly, but you still may see a last error message: 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
This only means that you need to login into TWS, go to your settings and both activate “Enable ActiveX and Socket Clients” as well as verify that the port you’re using in the code and the GUI is the same. Also is important to check or uncheck “Read-Only API” if you plan to send and receive requests, or only receive data (read-only). For the time being I’ll keep it checked as I’m not planning to execute orders through the initial app, just get data.
Save the changes, run the script, and there you go: We’re connected!
If you happen to run the script without the disconnect() method, you can open a new tab in your terminal and run the following command in order to stop execution:
pkill -f name_of_your_script.py
And that’s all for now! More in the next post!