Building your trading strategy to connect to a broker with the broker’s proprietary API is always dreadful. There are tones of API documentation to read, tones of trial-and-error tests to conduct, and tones of unknown causes and bugs that fail your API test. In this post, I’m going to demonstrate my MVP API template to get my trading strategies to work, so that you can build your own in a way that makes your trading strategies work as well.
If you enjoy reading this and my other articles, feel free to join Medium membership program to read more about Quantitative Trading Strategy.
Previous researches
After completing the research CPPI investment strategy, I need to find a new broker with a new account to start trading. Interactive Broker (IBKR) is the first broker that I am familiar with when I was a student, so I kinda have this obsession to make my trades through it. Years later, I consider myself finally had the luxury to sit down and spend time reading their API documentation. I’ve found the IBKR API doesn’t support retrieving historical transaction data, for example, the orders you placed three days ago and the commissions you paid for each trade wouldn’t be stored anywhere in the IBKR server. However, I need this information to build my performance evaluation report. Therefore, I’ve decided to put it on hold until there’s a good enough solution to come to rescue me. Now, as my knowledge grows, I’ve figured it’s about time to tackle this task.
Interactive Broker (IBKR) is a renowned investment broker that has successfully operated its business across the world. It is also famous for its low trading fees in both the equity and the derivative markets. On the other hand, its proprietary API is notorious for being complicated enough to work with. I’m going to give you my two cents here and hopefully it’ll help people who would like to consider Interactive Broker as their market broker. Here are the things I’m going to talk about:
- IBKR TWS and IB gateway
- IB gateway configurations
- My MVP broker API template
- Introduce ib_insync package and start connecting
- Implement our first IBKR call
IBKR TWS and IB gateway
In order to connect to the broker’s API service, each broker provides different methods to do so. TD Ameritrade API allows you to use their API service remotely through the API token provided. Futu OpenAPI requires you to download extra software on your local PC/laptop, so that your API calls will be able to access their API service through this middleware. As for [IBKR API], it is similar to Futu OpenAPI that all the API calls are connected through its proprietary software to reach the API service.
How does your API call reach the IBKR API service
Interactive broker provides two software applications to help you connect to their API service:
TWS
TWS stands for Trader Workstation. TWS is designed for trades who would like to conduct a series of research and trade equity and derivatives across many markets in one unified platform. Users can read the latest news, study company fundamentals and annual reports, research the stock trend or patterns, and even place orders with it. Also, it embeds the capability of being an intermediary between your desktop/laptop and the IBKR API service.
IBKR TWS Trading Station
IB gateway
Compared to TWS, IB gateway is simply an API gateway without all the User Interface that you can see in the TWS. You can’t buy or sell or do anything with the IB gateway. It allows you to connect to the IBKR API service and nothing more. In general, it is a super lightweight TWS that will consume much less of your desktop/laptop memories and resources.
IBKR IB Gateway
These two software applications have similar configurations but hold separate parameters which they don’t share mutually. Now let’s take a look at the configurations that will concern us before we start programming our API connection to IBKR.
IB gateway configurations
Let’s use IB gateway as an example so that we don’t get distracted by the various features that TWS offers. First of all, we need to log in to the IB gateway software application. I don’t want to mess around with my real money while testing my trading script, I would instead use a paper account. (Tip: You can reset your paper account on your account management page every day.)
Login to your paper account
Here is a few configurations that you need to pay attention to before starting to code:
- In API -> Setting, uncheck the “Read-Only API”.
- In API -> Setting, remember or configure the “Socket port” because you will need it when connecting to this software.
- In API -> Precautions, check the box “Bypass Order Precaution for API Order” to prevent additional errors or warning dialog boxes popped up when you place orders through API.
- If you’re using TWS as your middleman service, you need to check one more box “Enable ActiveX and Socket Client”.
API configuration
API configuration 2
Now we’re all set. Let’s get down to the business.
My MVP broker API template
There are a few actions required in your trading strategies in order to run the basic buy/sell operations properly:
- Connect to and disconnect from the dedicated broker API service.
- Get your basic account info in order to know the account status such as
Total asset value
,Remaining cash balance
,Purchasing power
, … and so on. - Check the trading calendar and trading hours to see whether the market is open for trading or if it’s a holiday today.
- Check the current quote price of a specific symbol in order to know how many shares we would purchase.
- Place orders through the broker API.
- Get the transaction history for performance evaluation later on.
I use the python package abc
(abbreviation for Abstract Base Class) to build my base API template. The most obvious advantage of building a baseclass with an abstract base class is that you can easily extend from it to build another class. For example, you have a class called InteractiveBrokerClass to make trades, and another class called TDAmeritradeBrokerClass to make trades with TD Ameritrade. Both broker classes do similar things and require similar functions. Implementing them using as abstract base class would make your life easier in terms of managing the actions in both derived classes. Here’s my broker base class:
1 | # TradeAPI.py |
Abstract Trading API Template
Implementing any of them could be straightforward and also could be extremely complex, depending on the design of the structure of the proprietary broker API. Like I said earlier that Interactive Broker didn’t support querying historic transactions/trades, we need to build alternative functions on the side in order to support the def get_transactions(self)
in our base template. I’m not going to dive into how to build them now and we will come back to this in another post. I will start by looking at how we are going to connect to the IB gateway by implementing the def connect()
function, and then we can check the quote price and place orders with API calls whenever we want to.
Introduce ib_insync package and start connecting
Instead of using the native ib_api
package to connect to the IBKR API service, I choose to use ib_insync
package developed by Ewald R. de Wit. ib_insync
not only simplifies the way to connect and communicate with the IBKR API service, but it also adds the asynchronous capability so that less CPU time was wasted while requesting data from the server. Here is an introductory post to get you familiar with the functions provided in ib_insync
: ib_insync: Interactive Broker API guide. We can clearly learn that we can connect to the IBKR API service with the following code:
1 | ib = IB() |
You would need to connect to server before you make any request
This established connection ib
was handled and maintained by whoever initiated it. In order to better and easier to handle the connection and close it effectively once we finished using it, I would suggest using contextmanager
so that the context manager will close the connection once we finished using it. We don’t have to explicitly disconnect from the API service. Instead, the context manager will handle it every time when the with
clause is finished.
1 | # test.py |
Connect function implemented with context manager
Implement our first IBKR call
In the last part of this post, let’s try to implement get_account_detail()
call in our broker class so that we could learn the account status.
In the original ib_insync document, I found out that ib.managedAccounts()
can retrieve a list of account names, and ib.accountValues(account:str)
can retrieve all stats under this account parameter. Hence, I’m going to:
- First, use
ib.managedAccounts()
to retrieve all the accounts created. - Use
ib.accountValues()
to get all variables related to this account. - Extract the
TotalCashBalance
andStockMarketValue
concerned USD so that I could tell how much money I have in cash and as well the total value under my account.
1 | # test.py |
Full code
1 | # Output |
Account status output
Noted: Make sure you attach the rest of the unimplemented functions as I did, as this is required in an abstract class. Otherwise, you will see the following error message when you run the test code.1
2
3
4Traceback (most recent call last):
File "/Users/michael/quantitative-strategy/app/trading/test.py", line 86, in <module>
broker = InteractiveBrokerTradeAPI(version_param=SCRIPT_VERSION)
TypeError: Can't instantiate abstract class InteractiveBrokerTradeAPI with abstract methods get_last_price_from_quote, get_transactions, is_market_open, is_market_open_now, place_order
You need to implement all defined functions in the base class
Conclusion
Done! We’re not officially connecting our trading script to the Interactive Broker API service. To make sure this broker class can fully support the functionalities of your trading program, there are still more functions to be implemented. Don’t worry, I’ll see you next time.