May cohort is now open: How to secure your spot:

Automate your algo trading with Python and IB

PQN #018 Automate your algo trading with Python and IB

Automate your algo trading with Python and IB

In today’s issue, I’m going to show you how to send a trade order to Interactive Brokers (IB) with Python.

IB is a US-based broker that has an API that lets traders send trade orders through algorithms. IB has cheap commissions, access to global markets, and good execution. I recommend using IB for trading, both manually and algorithmically.

Some traders use the API to automate part of their trading. Some build sophisticated algorithms for fully-automated trading systems. Others use the API for storing real-time market data.

If you don’t have an IB set up yet, head over to Interactive Brokers and set one up. If you use this link, you can earn up to $1,000.

By the end of this issue, you’ll know how to:

  • Install the Python API
  • Install Trader Workstation
  • Connect to IB through Python
  • Send a stock order to IB through Python

Let’s go!

Step 1: Install the Python API

Download the Python API from the Interactive Brokers GitHub page.

PQN #018: Automate your algo trading with Python and IB

Download the stable Windows or Mac / Unix version of the API depending on your machine.

Install on Windows

Run the msi file and go through the setup wizard. Once completed, navigate to the directory that you specified in the installer. Within the install directory, navigate to /TWS API/source/pythonclient. In this folder open a command prompt and run python3 setup.py install to install the API.

Install on Mac or Linux

Follow the step-by-step instructions here https://ibkb.interactivebrokers.com/article/2484.

Test the installation at your Python prompt with import ibapi. If no errors appear, the installation was successful.

Step 2: Install Trader Workstation (TWS)

TWS is IB’s trading app. It’s great to use if you want to see what happens when you send trade orders with Python.

You need to change some settings. Navigate to Trader Workstation Configuration under Edit –> Global Configuration –> API –> Settings. You should a screen that looks like this:

PQN #018: Automate your algo trading with Python and IB

Make sure to check Enable ActiveX and Socket Clients. Check Read-Only API if you want extra protection against sending orders to IB. Lastly, check Allow connections from localhost only for security.

Make note of the Socket port which you’ll need to connect through Python. Depending on the version, it’s either 7497 or 7496.

Step 3: Test your connection

The Python API uses TWS to connect to the IB servers. After you log in to TWS, you can connect to IB with Python. Make sure you change the socket port number in the function app.connect if needed. The first parameter is the IP address of your local computer (i.e. localhost). Leave this as is. The second is the port you socket port you configured in TWS. Change this if it differs from TWS. The third parameter is a unique client ID. You can change this to any positive integer.

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("127.0.0.1", 7497, 123)
app.run()

# uncomment this section if unable to connect
# import time
# time.sleep(2)
# app.disconnect()

After you run the code, your output should look something like this:

PQN #018: Automate your algo trading with Python and IB

If you don’t get output, change the client ID and try again. If that doesn’t work, uncomment the last three lines the script. If that doesn’t work, investigate based on the log output.

Step 4: Buy AAPL

To buy a stock, you send information about what you want to buy to IB through the API. The app.placeOrder the method does all the hard work for you.

First, import the classes from the IB API. Import threading to run the app in a single thread and time to pause execution of the script.

from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.contract import Contract
from ibapi.order import *

import threading
import time

This class creates the app. The app is what you use to interact with IB.

This class inherits two classes from the IB API. If this doesn’t make sense, don’t worry. The API needs an order ID associated with every order. nextValidId is a built-in function that finds the next available order ID. The other methods log output so you can see what’s happening.

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

    def nextValidId(self, orderId: int):
        super().nextValidId(orderId)
        self.nextorderId = orderId
        print("The next valid order id is: ", self.nextorderId)

    def orderStatus(
        self,
        orderId,
        status,
        filled,
        remaining,
        avgFullPrice,
        permId,
        parentId,
        lastFillPrice,
        clientId,
        whyHeld,
        mktCapPrice,
    ):
        print(
            "orderStatus - orderid:",
            orderId,
            "status:",
            status,
            "filled",
            filled,
            "remaining",
            remaining,
            "lastFillPrice",
            lastFillPrice,
        )

    def openOrder(self, orderId, contract, order, orderState):
        print(
            "openOrder id:",
            orderId,
            contract.symbol,
            contract.secType,
            "@",
            contract.exchange,
            ":",
            order.action,
            order.orderType,
            order.totalQuantity,
            orderState.status,
        )

    def execDetails(self, reqId, contract, execution):
        print(
            "Order Executed: ",
            reqId,
            contract.symbol,
            contract.secType,
            contract.currency,
            execution.execId,
            execution.orderId,
            execution.shares,
            execution.lastLiquidity,
        )

Next, create a function to run the app. Then, define a stock contract (IB calls everything a contract).

def run_loop():
    app.run()

def stock_contract(
    symbol,
    secType='STK',
    exchange='SMART',
    currency='USD'
):
    # create a stock contract
    contract = Contract()
    contract.symbol = symbol
    contract.secType = secType
    contract.exchange = exchange
    contract.currency = currency

    return contract

Now that the setup is out of the way, make the connection and start a thread. The while loop checks if the API is connected. If it is, app.nextorderId returns an int . Otherwise, it returns None.

app = IBapi()
app.connect('127.0.0.1', 7497, 123)

app.nextorderId = None

api_thread = threading.Thread(target=run_loop, daemon=True)
api_thread.start()

while True:
    if isinstance(app.nextorderId, int):
        print('connected')
        break
    else:
        print('waiting for connection')
        time.sleep(1)

The next step is to create an order and send it to IB. This is where the core logic of your algorithm lives. In this case, I keep it simple and just buy 10 shares of AAPL. IB expects the order to be a Python object with buy or sell, quantity, and order type. Because I send a limit order, I set the limit price too. Finally, I send the order, wait three seconds, cancel it for the sake of this demo, wait three more seconds, then disconnect the app.

order = Order()
order.action = "BUY"
order.totalQuantity = 10
order.orderType = "LMT"
order.lmtPrice = "130.00"

app.placeOrder(app.nextorderId, stock_contract("AAPL"), order)

# uncomment if you are sending more than one order
# app.nextorderId += 1

time.sleep(3)

# cancel the order for the demo
print('cancelling order')
app.cancelOrder(app.nextorderId, "")

time.sleep(3)
app.disconnect()

When I run the script, the order is sent to IB and cancelled three seconds later. This is what the output looks like.

PQN #018: Automate your algo trading with Python and IB

I see my cancelled order in the Orders pane of TWS.

PQN #018: Automate your algo trading with Python and IB

Algorithmic trading is not easy. On top of finding, testing, and validating an edge, you have the technology to deal with. In real trading systems, you need to worry about the logic to cancel orders, checking if orders were executed, handling bad data, checking portfolio constraints, risk management, and many other things.

When you’re just getting started, execute everything in a paper trading account. You can find instructions to set up a paper trading account here. Trade manually alongside the algorithm to make sure trades execute how you expect. This way, you can fix any issues in your script too.

When you go live, execute with a very small size. Expect to lose the money you’re trading with. The longer you do this, and experience different market conditions, the more confidence you’ll have that things will go well.

Well, that’s it for today. I hope you enjoyed it.

See you again next week.