REST API for use with Interactive Brokers TWS and IB Gateway
By using Flask-RESTful (and therefore Flask), a web-based API is created which then uses IbPy to connect to an instance of TWS or IB Gateway, and interact with Interactive Brokers. This documentation will generally use "TWS" to mean "TWS or IBGateway"
This API should run on the same machine with TWS so that TWS can be set to only allow connections from the local host. This provides a nice security feature, and lets IP access then be controlled by more advanced firewall software (ie to allow wildcards or IP ranges to access this REST API and therefore the TWS instance it interfaces with).
This API layer between your algorithm code and the IbPy API code is intended for use on Google App Engine where an algoritm may be operating within the GAE system, with TWS running on a Compute Engine VM (ie Brokertron). TWS does not support wildcard IP address (which would be a security hole anyways), and GAE uses many IPs when making outbound connections from one's App (making it neigh impossible to list all possible IPs in TWS' whitelist). However, this project will aim to stay generalized enough so that it can be used outside of GAE.
For running flask as a Docker container, consider this tutorial or use this existing docker-flask image.
TODO: Consider using following GAE features:
- Logging messages to GAE logger
- Storing IB messages to DataStore
- Using Task Queue to get requests from GAE. IB allows 8
client_ids
, which will impose a limit of 8 "simultaneous" tasks at a time with IBREST, unless some kind of task queuing happens (ie Celery)
The IB API is designed to be asynchronous, which adds labor to writing code to interface with it. As IB message exchanges are pretty fast (a couple seconds at most), it's within time margins for use with HTTP requests (~60sec timeouts). Thus, the exposed RESTful API opens a user-friendly synchronous interface with IB.
Use IbPyOptional (ib.opt
module) maximally.
As IBREST is built with IbPy, and IbPy is based on the IB Java API, then IBREST will aim to use maximally similar language as found in those APIs' documentation. The Java API is broken into two main layers:
- EClientSocket - the connection to TWS for sending messages to IB.
- EWrapper - the message processing logic for messages returned by IB. Some messages are streamed in at intervals (ie subscriptions) and will not be exposed as a REST URI. Such are marked
Unexposed data feed
below.
TODO: Consider creating an RSS feed endpoint for such "Unexposed data feed" data.
NOTE: As noted in [Synchronous], TWS only allows 8 connections (client ID's 0-7, where 0 has some special privileges).
An IBREST client only uses one of these allowed connections. To increase throughput, you can create a "proxy" (see
proxy.Dockerfile
) to front 8 IBREST instances, thereby reducing latency in quick, successive calls.
While Python objects are named with_under_scores
, IbPy and its corresponding Java code uses camelCase. The IBREST source code will use camelCase to imply a direct correlation with IbPy. For obejcts which only pertain to IBREST inner logic, under_scored names will be used.
All endpoints return JSON formatted data using keys and values consistent with IbPy and IB Java APIs (case sensitive).
For security, HTTPS is used by default. To create your own cert and key, try:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ibrest.key -out ibrest.crt
The documentation for each of these layers contains these sections, after which IBREST will create endpoints groups when applicable. An endpoint may provide either a synchronous reponse or an atom feed.
IB Documentation | REST endpoint | Sync or Feed |
---|---|---|
Connection and Server | NA: Handled by Flask configuration | |
Market Data | /market/data | Feed |
Orders | /order | Sync |
Account and Portfolio | /account | Sync |
Contract Details | /contract | Sync [TBD] |
Executions | /executions | Sync |
Market Depth | /market/depth | Feed [TBD] |
News Bulletins | /news | Feed [TBD] |
Financial Advisors | /financial | Feed [TBD] |
Historical Data | /historical | Sync [TBD] |
Market Scanners | /market/scanners | Feed [TBD] |
Real Time Bars | /bars | Feed [TBD] |
Fundamental Data | /fundamental | Feed [TBD] |
Display Groups | /displaygroups | Feed [TBD] |
These endpoints return a since single response.
A GET request retrieves a details for all open orders via reqAllOpenOrders
.
A POST request will generate a placeOrder()
EClient call, then wait for the order to be filled .
A DELETE request will call cancelOrder()
.
A GET request to /account/updates
will use reqAccountUpdates()
to return messages received from updateAccountValue/AccountTime()
and updatePortfolio
EWrapper messages, as triggered by accountDownloadEnd()
.
A GET request to /account/summary
will use reqAccountSummary()
to return messages received from updateSummary()
EWrapper message as triggered by accountSummaryEnd()
.
A GET request to /account/positions
will use reqPostions()
to return messages received from position()
EWrapper message as triggered by positionEnd()
.
These endpoints are used for atom feeds. They must be subscribed to or unsubscribed from. They are not yet implemented