IBKR_API

Supporting Greed Monsters since 2019

IBKR_API Architecture

The IBKR_API is NOT some wrapper on top of the existing twsapi python API, but rather a complete redesign of the codebase. The new codebase was written with the following ideas in mind. One, a ‘design by contract’ approach was used, where each portion of the system has clearly defined responsibilities. For the most part these responsibilities are explicitly listed in their respective docstrings. The other governing principle was to keep the code ‘DRY’ and to avoid ‘speculative generality’. The codebase you see is the result of this philosophy.

Directory Structure

The table below describes various important directories within this API and their intended purpose

Directory Description
base The core application internals. Unless you are developing the API this code this code won’t be called directly
classes/contracts Various types of Contract objects such as Stock, Option, Put, Call, etc
classes/enum Various Enum and IntEnum classes that hold all legal values for whatever specific parameter they represent
classes/orders Objects that represent various types of orders that can be placed such as Limit , Discretionary, etc
classes/stocks Dow 30, S&P 500, etc (should/will probably be renamed to indexes…)
api.py IBKR_API interface. Use this if you are looking for a simple synchronized interface
client_application.py ClientApplication Interface. Use this if you are looking for a standard asynchronous event driven approach

Interfaces

There are three primary interfaces to use. For basic usage the IBKR_API class is your best bet. This class hides the complexity of the underlying asynchronous interface provided by the application Bridge (TWS or the IB Gateway) and gives you a straight forward way to query data.

For those users looking to implement real time algorithmic trading systems the ClientApplication class is the right place to start. This class provides an interface similar to what is provided by the official API, minus the artificial complexity.

RabbitMQ

Two exchanges are being used trading desk for messages bound for the trading desk. actor for messages bound for the various actors.

Message Exchanges

Routing key: <message_type>.<Actor.code>

+==============+====================+=================================================================+ | Exchange | Queue Message Type | Meaning | +==============+====================+=================================================================+ | trading_desk | bridge | (API) Requests from Actors for the bridge application | +————–+——————–+—————————————————————–+ | trading_desk | multi_client | Responses from prior request | +————–+——————–+—————————————————————–+ | actor | bridge | Request for the MultiClientApplication to deliver to the bridge | +————–+——————–+—————————————————————–+ | actor | multi_client | Request from the MultiClientApplication | +————–+——————–+—————————————————————–+

Installation Guide

To install ibkr_api all you need to do is run pip install:

pip install ibkr_api

Quick Start Guide

Now that we have ibkr_api installed. Let us do some real work.

Let’s start working with the data

Creating Your Application

  1. Create your own application class
  2. Implement your initialize action
    1. Read any configuration information
    2. Connect to your application’s database
    3. Get the initial valid order id
    4. Get the initial valid request id (next_valid_id

F.A.Q

How do I exit my application?

At the end of each event loop iteration. A call is made to your classes act() function. When your application wants to quit out, all you need to do is call the stop() function. This will set the still_running flag to false, and will then exit normally.

Contributing To This Codebase

General

Thanks for looking into contributing to this codebase. As many open source projects are handled differently, it is best to state some of my thinking in regards to contributions. Firstly, all contributions are welcome in this codebase. If you only feel comfortable making a small change, whether to improve some text or fix a variable name, please do.

Pull Requests

To minimize the pain of pull requests, my current plan is as follows on the second and last weekend of the month (US Mountain Time), I will actively look to merge any code that I can. One of my personal pet peeves is submitting a pull request and not getting any feedback. As such I will try my best to reply to pull requests in a timely fashion.

Found a Bug

Open up a ticket, and Ill discuss whatever you found. The more detailed you are in what you think the issue is and exact steps for someone to recreate will greatly aid in the debugging process.

IBKR_API Client Quick Start

IBKR_API provides an interface that hides the inherent complexity of an event driven asynchronous This page has several snippets for common tasks that you may want to do with this API. All the samples below assume that the code from the Initial Setup block have already been executed, otherwise the code shown should be self contained.

Initial Setup

from ibkr_api.api import IBKR_API
from ibkr_api.classes.contracts.contract import Contract
from ibkr_api.classes.stocks.dow30 import Dow30
from historical_data_types import HistoricalDataType as HDT

host = "127.0.0.1"
port =
ibkr = IBKR_API(host, port)

Working With Orders

Placing an Order

There are many various types of orders that can be placed and as such we will allow Interactive Brokers documentation to explain every option. (Even I as the developer of this API do not know all permutations at this point). The main endpoint to use is place_order . The order id simply must be a unique integer or a duplicate id error will be generated.

Placing a Limit Order

The sample below shows a limit order being placed to purchase 1 share of Bank of America Stock.

order_id = 60
contract = Stock('BAC')
contract.currency = "USD"
contract.exchange = "SMART"

total_quantity = 1
limit_price = 26.5
order = LimitOrder(OrderAction.BUY.value, contract, total_quantity, limit_price)
ibkr.place_order(order_id, order)

Get all open orders

Now that we know how to place an order. The next logical step is to check on that order. This can be done with a call to request_open_orders which will return a list of Order objects.

open_orders = ibkr.request_all_open_orders()
for open_order in open_orders:
 print(open_order)

Working With Options

List all the option chains for TSLA

Get the option chains for all Dow 30 Stocks

dow30 = Dow30()
for stk in dow30.stocks():
    stk = ibkr.request_contract_data(stk)
    option_chains = ibkr.request_option_chains(stk)
    for opt_chain in option_chains:
        print(opt_chain)

Other Functionality

Get all linked accounts (aka ‘Family Codes’)

family_codes = ibkr.request_family_codes()
for code in family_codes:
    desc = "{0} - {1}".format(code['account_id'],code['family_code'])
    print(desc)

Find All Contracts that Match ‘TSLA’

request_id, contracts = ibkr.request_matching_symbols('TSLA')
for c in contracts:
    print(c)

Display Account Positions

position_data = ibkr.request_positions()
for data in position_data:
    c = data['contract']
    desc = "{0:<10} {1:<10} {2:>20} {3:>30}".format(data['account'], c.local_symbol, data['position'], data['average_cost'])
    print(desc)

Get the Last Year of Daily Prices for XOM

dow30 = Dow30()
# contract = Contract(symbol="XOM", security_type="STK") - Another way to get a contract
contract = dow30.XOM()
duration = "1 Y"
(message_id, request_id, bar_data) = ibkr.request_historical_data(contract, '', duration, "1 day", HDT.TRADES.value, 1, 1, False, [])
print("XOM Daily Closes")
for bar in bar_data:
    print("{0}: {1}".format(bar.date, bar.close))

ClientApplication

To help get you started browse some representative usages of the API

How to Create a Market Scanner Subscription

First create a Scanner object. This will contain the primary criteria to scan the market by. Once we configure the scanner object, all we need to do is call request_scanner_subscription to start receiving data

scanner = Scanner()
scanner.instrument      = "STK"
scanner.location_code   = "STK.US.MAJOR"
scanner.scan_code       = "HOT_BY_VOLUME"
request_id = self.get_local_request_id()
self.request_scanner_subscription(request_id, scanner, None, None)

The Bridge will periodically continue to refresh this information, so if the data is no longer required. It can be stopped by calling cancel_scanner_subscription with the same request id that was supplied to the initial request.

self.cancel_scanner_subscription(request_id)

General Data

This section describes some of the other functionality not already covered above

Getting All Linked Accounts (aka ‘Family Codes’)

To get linked account data, add the line below to either your application’s initialize or act method

Family Codes
Response Description
family_codes Normal response from the bridge
self.request_family_codes()

ibkr_api

ibkr_api package

Subpackages

ibkr_api.base package
Submodules
ibkr_api.base.api_calls module
ibkr_api.base.bridge_connection module
ibkr_api.base.constants module
ibkr_api.base.errors module
ibkr_api.base.message_parser module
ibkr_api.base.messages module
Module contents
ibkr_api.classes package
Subpackages
ibkr_api.classes.contracts package
Module contents
ibkr_api.classes.enum package
Submodules
ibkr_api.classes.enum.bar_size module
ibkr_api.classes.enum.financial_advisor module
ibkr_api.classes.enum.historical_data_type module
ibkr_api.classes.enum.report_type module
ibkr_api.classes.enum.rule_80a module
ibkr_api.classes.enum.tick_type module
Module contents
ibkr_api.classes.stocks package
ibkr_api.classes.stocks.dow30 module
Module contents
Classes
ibkr_api.classes.execution module
ibkr_api.classes.option_chain module
ibkr_api.classes.orders
ibkr_api.classes.order_state module
ibkr_api.classes.scanner module
ibkr_api.classes.soft_dollar_tier module
Module contents

Submodules

ibkr_api.api module

ibkr_api.client_application module

ibkr_api.multiple_client_application module

Module contents

Indices and tables