Investing in financial products involves risk to your capital.

Close Navigation
Learn more about IBKR accounts

TWS API Documentation

Introduction

The TWS API is a TCP Socket Protocol API based on connectivity to the Trader Workstation or IB Gateway. The API acts as an interface to retrieve and send data autonomously to Interactive Brokers. Interactive Brokers provides code systems in Python, Java, C++, C#, and VisualBasic.

The TWS API is a message protocol as its core, and any library that implements the TWS API, whether created by IB or someone else, is a tool to send and receive these messages over a TCP socket connection with the IB host platform (TWS or IB Gateway). As such the system can be tweaked and modified into any language of interest given the intention to translate the underlying decoder.

In short, a library written in any other languages must be sending and receiving the same data in the same format as any other conformant TWS API library, so users can look at the documentation for our libraries to see what a given request or response consists of (what it must include, in what form, etc.) and implement them in their own structure.

Our TWS API components are aimed at experienced professional developers willing to enhance the current TWS functionality. Before you use TWS API, please make sure you fully understand the concepts of OOP (https://www.geeksforgeeks.org/introduction-of-object-oriented-programming/) and other Computer Science Concepts. Regrettably, Interactive Brokers cannot offer any programming consulting. Before contacting our API support, please always refer to our available documentation, sample applications and Recorded Webinars

This guide references the Java, VB, C#, C++ and Python Testbed sample projects to demonstrate the TWS API functionality. Code snippets are extracted from these projects and we suggest all those users new to the TWS API to get familiar with them in order to quickly understand the fundamentals of our programming interface. The Testbed sample projects can be found within the samples folder of the TWS API’s installation directory.

Notes & Limitations

Limitations

Our programming interface is designed to automate some of the operations a user normally performs manually within the TWS Software such as placing orders, monitoring your account balance and positions, viewing an instrument’s live data… etc. There is no logic within the API other than to ensure the integrity of the exchanged messages. Most validations and checks occur in the backend of TWS and our servers. Because of this it is highly convenient to familiarize with the TWS itself, in order to gain a better understanding on how our platform works. Before spending precious development time troubleshooting on the API side, it is recommended to first experiment with the TWS directly.

Remember: If a certain feature or operation is not available in the TWS, it will not be available on the API side either!

Requests

The TWS/ IB Gateway is designed to accept up to 50 messages per second coming from the client side. Anything coming from the client application to the TWS/ IB Gateway counts as a message (i.e. requesting data, placing orders, requesting your portfolio… etc.). This limitation is applied to all connected clients in the sense where all connected client applications to the same instance of TWS/ IB Gateway combined cannot exceed this number. On the other hand, there are no limits on the amount of messages the TWS can send to the client application.

 

In some use cases, if you plan to send more than 50 orders per second, some orders may be queued and delayed. For this scenario, please consider to switch to FIX API.

For FIX API users in IB Gateway, the limitation is 250 messages per second.

For FIX API users without using IB Gateway or TWS, there is no limitation on messages per second, but less is better.

Paper Trading

If your regular trading account has been approved and funded, you can use your Account Management page to open a Paper Trading Account which lets you use the full range of trading facilities in a simulated environment using real market conditions. Using a Paper Trading Account will allow you not only to get familiar with the TWS API but also to test your trading strategies without risking your capital. Note the paper trading environment has inherent limitations.

Requirements

  • A funded and opened IBKR Pro account
  • The current Stable or Latest release of the TWS or IB Gateway
  • The current Stable or Latest release of the TWS API
  • A working knowledge of the programming language our Testbed sample projects are developed in.

Unset Values

Developers may often find a super-massive value returned from requests like market data, P&L information, and elsewhere. These are known as Unset values. Unset values are used throughout programming systems to indicate that a value is not available. Unset values are used in place of NULL characters to prevent any unexpected error be thrown in your code. Unset values are also used in place of values like 0 to avoid confusing viewers to believe they have an account balance of 0, or that an equity is worth $0.

An unset value is the maximum value of a given data type. So the Unset Double value will appear like 1.7976931348623157E308, which contains approximately 308 digits to intentionally appear extraneous.

Download TWS or IB Gateway

In order to use the TWS API, all customers must install either Trader Workstation or IB Gateway to connect the API to. Both downloads maintain the same level of usage and support; however, they both have equal benefits. For example, IB Gateway will be less resource intensive as there is no UI; however, the Trader Workstation has access all of the same information as the API, if users would like an interface to confirm data.

 

It is recommended for API users to use offline TWS because TWS online version has automatic update. Please use same TWS version to make sure the TWS version and TWS API version are synced. These will help preventing version conflict issue.

 

 

Note:

  1. For IBHK API users, it is commended to use IB Gateway instead of TWS. It is because all IBHK users cannot choose “Never Lock Trader Workstation” in TWS – Global Configuration – Lock and Exit. If there is inactivity, TWS will be locked and there will be API disconnection.
Download Trader Workstation Download IB Gateway

TWS Settings

Some TWS Settings affect API.

TWS Configuration For API Use

In TWS Global Configuration – API – Settings, there are many API settings. Please enable/disable some API settings based on your use case.

In this section, only the most important API settings for API connection and incident troubleshooting are covered.

Please:

  • Enable “ActiveX and Socket Clients”
  • Disable “Read-Only API”
  • Enable “Create API message log file”
  • Enable “Include market data in API log file”
  • Change “Logging Level” to “Detail”

If you want to establish localhost API connection, please enable “Allow connection from localhost only”.

if you want to connect TWS/ IB Gateway from a remote server, please disable “Allow connection from localhost only” and put the IP Address detected in “Accept incoming connection attempt from <IP Address>” into “Trusted IPs”.

The IP Address is usually Private IPv4 Address.

“Trusted IPs” does not accept subnet (e.g. /27, /28). It only accepts single IP Addresses. In the following example, there is a remote computing cluster /27 which has 32 IP Addresses and the remote computing cluster will randomly assign one of the computing nodes to connect to TWS in every connection.  To make this happen, every Private IPv4 Address of the subnet are put into the “Trusted IPs” (You can also exclude the first IP Network Address and the last IP Broadcast Address of the subnet).

For more details, please visit: https://www.interactivebrokers.com/campus/ibkr-api-page/twsapi-doc/#incoming-api-connections

Note:

  1. In TWS, if you don’ t put the remote IP Address into the “Trusted IPs” and you try to establish remote API connection, there will be a message “Accept incoming connection attempt from <IP Address>” which requires you to accept the connection or reject the connection. In IB Gateway, it is compulsory for IB Gateway users to put the remote IP Address into the “Trusted IPs”. Otherwise, there will be no connection attempt detected.

Best Practice: Configure TWS / IB Gateway

The information listed below are not required or necessary in order to operate the TWS API. However, these steps include many references which can help improve the day to day usage of the TWS API that is not explicitly offered as a callable method within the API itself.

Memory Allocation

In TWS/ IB Gateway – “Global Configuration” – “General”, you can adjust the Memory Allocation (in MB)*.

This feature is to control how much memory your computer can assign to the TWS/ IB Gateway application. Usually, higher value allows users to have faster data returning speed.

Normally, it is recommended for API users to set 4000. However, it depends on your computer memory size because setting too high may cause High Memory Usage and application not responding.

For details, please visit: https://www.ibkrguides.com/traderworkstation/increase-tws-memory-size.htm

 

Note:

  1. In IB Gateway Global Configuration – API – settings, there is no “Compatibility Mode: Send ISLAND for US stocks trading on NASDAQ”. Specifying NASDAQ exchange in contract details may cause error if connecting to IB Gateway. For this error, please specify ISLAND exchange.

Daily & Weekly Reauthentication

It is compulsory for TWS users to auto logoff/auto restart TWS daily and manually login TWS weekly.

In TWS/ IB Gateway – “Global Configuration” – “Lock and Exit”, you can choose the time that your TWS will be shut down.

For API users, it is recommended to choose “Never lock Trader Workstation” and “Auto restart”.

 

Note:

  1. IBHK users do not have “Never lock Trader Workstation” and “Auto restart” in TWS.
  2. Windows Sleeping Mode also causes API disconnection. It is strongly suggested to choose “Never Sleep” in Windows.

Order Precautions

In TWS – “Global Configuration” – “API” – “Precautions”, you can enable the following items to stop receiving the order submission messages.

  • Enable “Bypass Order Precautions for API orders”.
  • Enable “Bypass Bond warning for API orders”.
  • Enable “Bypass negative yield to worst confirmation for API orders”.
  • Enable “Bypass Called Bond warning for API orders”.
  • Enable “Bypass “same action pair trade” warning for API orders”.
  • Enable “Bypass price-based volatility risk warning for API orders”.
  • Enable “Bypass US Stocks market data in shares warning for API orders”.
  • Enable “Bypass Redirect Order warning for Stock API orders”.
  • Enable “Bypass No Overfill Protection precaution for destinations where implied natively”.

Connected IB Server Location in TWS

Each IB account has a pre-decided IB server. You can visit this link to know our IB servers’ locations: https://www.interactivebrokers.com/download/IB-Host-and-Ports.pdf

Yet, all IB paper accounts are connected to US server by default and its location cannot be changed.

As IB servers in different regions have different scheduled server maintenance time ( https://www.interactivebrokers.com/en/software/systemStatus.php ), you may need to change the IB server location in order to avoid service downtime.

For checking your connected IB server location, you can go to TWS and click “Data” to see your Primary server. In the below image, the pre-decided IB server location is: cdc1.ibllc.com

If you want to change your live IB account server location in TWS, please submit a web ticket to “Technical Assistance” – “Connectivity” in order to request changing the IB server location.

In the web ticket, you need to provide:

  1. Which account do you want to have IB server location change?
  2. Which IB server location would you like to connect to?
    • TWS AMERICA – EAST (New York)
    • TWS AMERICA – CENTRAL (Chicago)
    • TWS Europe (Zurich)
    • TWS Asia (Hong Kong)
    • TWS Asia – CHINA (For mainland China users, if the account server is hosted in Hong Kong, they will automatically connect with the Shenzhen Gateway mcgw1.ibllc.com.cn)
  3. Which IB scheduled maintenance time do you choose? (Recommended to choose the default schedule maintenance time of its own IB server location)
    • North America
    • Europe
    • Asia

After you submit the ticket, you will receive a web ticket reply which require you to confirm and understand the migration request.

 

Note:

  1. For Internet users, as the connection between IB server and Exchange goes through a dedicated line, it is commonly recommended to choose a IB server location which is closer to your TWS location. For IB connection types, please visit: https://www.interactivebrokers.co.uk/en/software/connectionInterface.php
  2. The pre-decided IB server location connected from TWS is different from the IB Server location connected from IB Client Portal and IBKR Mobile.
    • IB server location connected from TWS is pre-decided. You can submit a web ticket to request the IB server relocation for the TWS connection.
    • IB server location connected from Client Portal, IBKR Mobile is based on your nearest IB server location. You cannot request the IB server relocation for Client Portal and IBKR Mobile connections. However, OAuth CP API users can specify which server they want to connect to by themselves. For details, please visit: https://www.interactivebrokers.com/campus/ibkr-api-page/cpapi-v1/#oauth-base-url

SMART Algorithm

In TWS Global Configuration – Orders – Smart Routing, you can set your SMART order routing algorithm. For available SMART Routing via TWS API, please visit: https://www.interactivebrokers.com/campus/ibkr-api-page/contracts/#smart-routing

Allocation Setup (For Financial Advisors)

In TWS Global Configuration – Advisor Setup – Presets, you can need to choose Allocation Preference in order to avoid wrong allocation result.

Intelligent Order Resubmission

The TWS Setting listed in the Global Configuration under API -> Setting for Maintain and resubmit orders when connection is restored, is enabled by default in TWS 10.28 and above. When this setting is checked, all orders received while connectivity is lost will be saved and automatically resubmitted when connectivity is restored. Please note, if the Trader Workstation is closed during this time, the orders are deleted regardless of the setting.

Disconnect on Invalid Format

The TWS Setting listed in the Global Configuration under API -> Setting for Maintain connection upon receiving incorrectly formatted fields, is enabled by default in TWS 10.28 and above. For clients operating on Client Version 100 and above, users will not disconnect from fields with invalid value submissions when the setting is enabled.

Download the TWS API

Current LTS API version is 10.16 or above. It is STRONGLY RECOMMENDED for 10.16 version below API users to upgrade API.

 

It is recommended for API users to use same TWS API version to make sure the TWS version and TWS API version are synced in order to prevent version conflict issue.

 

Running the Windows version of the API installer creates a directory “C:\TWS API” for the API source code in addition to automatically copying two files into the Windows directory for the DDE and C++ APIs. It is important that the API installs to the C: drive, as otherwise API applications may not be able to find the associated files. The Windows installer also copies compiled dynamic linked libraries (DLL) of the ActiveX control TWSLib.dll, C# API CSharpAPI.dll, and C++ API TwsSocketClient.dll. Starting in API version 973.07, running the API installer is designed to install an ActiveX control TWSLib.dll, and TwsRtdServer control TwsRTDServer.dll which are compatible with both 32 and 64 bit applications.

 

It is important to know that the TWS API is only available through the interactivebrokers.github.io MSI or ZIP file. Any other resource, including pip, NuGet, or any other online repository is not hosted, endorsed, supported, or connected to Interactive Brokers. As such, updates to the installation should always be downloaded from the github directly.

TWS API Download Page

How to install the TWS API Components on Mac / Unix

  1. Download the IB API Stable for Mac/Unix zip file to your local machine
  2. This will direct you to Interactive Brokers API License Agreement, please review it
  3. Once you have clicked “I Agree, refer to the Mac / Unix section to download the API Software version of your preference
    API Software Download List
  1. This will download twsapi_macunix.<Major Version>.<Minor Version>.zip to your computer
    (where <Major Version> and <Minor Version> are the major and minor version numbers respectively)
  2. Open Terminal (Ctrl+Alt+T on most distributions)
    (On Mac press Command+Space to launch Spotlight, then type terminal and press Return)
  3. Navigate to the directory where the installer has been downloaded (normally it should be the Download folder within your home folder) and confirm the file is present

     $  cd ~/Downloads
     $  ls

  1. Unzip the contents the installer into your home folder with the following command (if prompted, enter your password):
    NOTE: replace the values ‘n.m’ with the name of your installed file.
    $  sudo unzip twsapi_macunix.n.m.zip -d $HOME/
    Installation directions Step 3 and Step 4
  2. To access the sample and source files, navigate to the IBJts directory and confirm the subfolders samples and source are present
    $  cd ~/IBJts
    $  ls

 

Note:

  • When running “python3 setup.py install“,  you may get “ModuleNotFoundError: No Module named ‘setuptools’“. As “setuptools” is deprecated, please grant the write permission on the target folder (e.g. source/pythonclient) using “sudo chmod -R 777” in order to avoid “error: could not create ‘ibapi.egg-info’: Permission denied“. After that, run “python3 -m pip install .

TWS API Folder Files & Tools

TWS API Folder Files Explanation:

 

  • “API_VersionNum.txt”

File Path: C:TWS APIAPI_VersionNum.txt 

You can check your API version in this file.

 

  • “IBSampleApp.exe”

File Path: C:TWS APIsamplesCSharpIBSampleAppbinReleaseIBSampleApp.exe

You can manually use the IBSampleApp to test the API functions.

Unique Configurations

While all of the available Trader Workstation API default samples provide equivalent functionality, some languages have unique configurations that must be implemented in order to use our samples or program code with the underlying API.

Implementing the Intel Decimal Library for MacOS and Linux

Due to the malleability of the many Linux distributions including MacOS, Interactive Brokers is unable to provide a pre-built binary for the library. As such, users programming in C++ on a Linux machine must manually build the Intel® Decimal Floating-Point Math Library manually.

As described in the README file from the linked page, you can find the library’s build steps within the ~/IntelRDFPMathLib20U2/LIBRARY/README file.

Download the Intel® Decimal Floating-Point Math Library

Updating The Python Interpreter

Python has a unique system for importing libraries into it’s IDEs. This extends even further when it comes to virtual environments. In order to utilize Python code with the TWS API, you must run our setup file in order to import the code.

1. Open Command Prompt or Terminal

In order to update the Python IDE, these steps MUST be performed through Command Prompt or Terminal. This can not be done through an explorer interface.

As such, users should begin by launching their respective command line interface.

These samples will display Windows commands, though the procedure is identical on Windows, MacOS, and Linux.

Displays the standard cmd

2. Navigate to Python Source

Customers should then change their directory to  {TWS API}sourcepythonclient .

It is then recommend to display the contents of the directory with “ls” for Unix, or “dir” for Windows users.

Displays directory navigation to the python source

3. Run The setup.py File

Customers will now need to run the setup.py steps with the installation parameter. This can be done with the command: python setup.py install

Displays the setup.py install command

4. Confirm Updates

After running the prior command, users should see a large block of text describing various values being updated and added to their system. It is important to confirm that the version installed on your system mirrors the build version displayed. This example represents 10.25; however, you may have a different version.

Displays the updated packages from setup.py

5. Confirm your installation

Finally, users should look to confirm their installation. The simplest way to do this is to confirm their version with pip. Typing this command should show the latest installed version on your system: python -m pip show ibapi

Displays the result of pip show ibapi

Implementing Visual Basic .NET

Our VB.NET code is provided for demonstration purposes only; there is no pure, standalone VB.NET-based TWS API library. Both our “VB_API_Sample” and the VB.NET “Testbed” projects included with our TWS API releases call the C# TWS API source. The provided VB.NET code only interfaces with the C# source. Please keep in mind that these samples are in VB.NET, not Visual Basic for Applications.

Third Party API Platforms

Third party software vendors make use of the TWS’ programming interface (API) to integrate their platforms with Interactive Broker’s. Thanks to the TWS API, well known platforms such as Ninja Trader or Multicharts can interact with the TWS to fetch market data, place orders and/or manage account and portfolio information.

It is important to keep in mind that most third party API platforms are not compatible with all IBKR account structures. Always check first with the software vendor before opening a specific account type or converting an IBKR account type. For instance, many third party API platforms such as NinjaTrader and TradeNavigator are not compatible with IBKR linked account structures, so it is highly recommended to first check with the third party vendor before linking your IBKR accounts.

An ongoing list of common Third Party Connections are available within our documentation. This resource will also link out to connection guides detailing how a user can connect with a given platform.

A non-exhaustive list of third party platforms implementing our interface can be found in our Investor’s Marketplace. As stated in the marketplace, the vendors’ list is in no way a recommendation from Interactive Brokers. If you are interested in a given platform that is not listed, please contact the platform’s vendor directly for further information.

Troubleshooting & Support

The API documentation contains a complete description of all API functions. Additionally the source code of the API itself is distributed freely and is a great resource for more in-depth understanding of how the API works. If after reviewing these resources there are remaining questions about available API functionality, the API Support group is available to help.

-> It is important to keep in mind that IB cannot provide programming assistance or give suggestions on how to code custom applications. The API group can review log files which contain a record of communications between API applications and TWS, and give details about what the API can provide.

General suggestions on starting out with the IB system:

  • Become familiar with the analogous functionality in TWS before using the API: the TWS API is nothing but a communication channel between your client application and TWS. Each API function has a corresponding tool in TWS. For instance, the market data tick types in the API correspond to watchlist columns in TWS. Any order which can be created in the API can first be created in TWS, and it is recommended to do so. Additionally, if information is not available in TWS, it will not be available in the API. Before using IB Gateway with the API, it is recommended to first become familiar with TWS.
  • Make use of the sample API applications: the sample applications distributed with the API download have examples of essentially every API function in each of the available programming languages. If an issue does not occur in the corresponding sample application, that implies there is a problem with the custom implementation.
  • Upgrade TWS or IB Gateway periodically: TWS and IB Gateway often have new software releases that have enhancements, and that can sometimes have bug fixes. Because of this, we strongly recommend our users to keep their software as up to date as possible. There is no problem with staying with a version of the API and upgrading TWS, as TWS/IB Gateway are designed to be backwards compatible with older API versions. If you are experiencing a specific problem that is occurring in TWS or IB Gateway and not in the API program, it is quite possible it does not occur in the more recent software build.

Understanding Order Precautions

By default, the Trader Workstation implements several precautionary settings that will notify customers of potential order risks to make sure users are well informed before transmitting orders. As a result, customers will typically need to acknowledge a precautionary message and manually transmit the orders through the Trader Workstation. These precautionary messages may be disabled if the user is comfortable and aware of the behavior they are disabling.

Disabling Warning Messages

  1. Log in to the Trader Workstation
  2. Open the Global Configuration by selecting the Cog Wheel icon in the top right corner
  3. Navigate to the “Messages” section on the left.
  4. Carefully read each message before disabling it. You can then disable the warning by unchecking the box on the right of the message description.

Modifying Precautionary Settings

  1. Log in to the Trader Workstation
  2. Open the Global Configuration by selecting the Cog Wheel icon in the top right corner
  3. Navigate to the “Presets” section on the left
  4. Select the instrument(s) you are trading
  5. Carefully read each setting before making changes to it. You may modify the values inside the “Precautionary Settings” settings to be more or less restrictive. You may also set the value to ‘0’ to disable the precaution entirely.

Log Files

The log files are essential to provide detailed information about how a custom application may be malfunctioning. They are useful tools for direct review by an API application programmer, and additionally they can be uploaded for review by the API Support group.

API Logs

TWS and IB Gateway can be configured to create a separate log file which has a record of just communications with API applications. This log is not enabled by default; but needs to be enabled by the Global Configuration setting “Create API Message Log File”(picture below).

  • API logs contain a record of exchanged messages between API applications and TWS/IB Gateway. Since only API messages are recorded, the API logs are more compact and easier to handle. However they do not contain general diagnostic information about TWS/IBG as the TWS/IBG logs. The TWS/IBG settings folder is by default C:Jts (or IBJts on Mac/Linux). The API logs are named api.[clientId].[day].log, where [clientId] corresponds to the Id the client application used to connect to the TWS and [day] to the week day (i.e. api.123.Thu.log).
  • There is also a setting “Include Market Data in API Log” that will include streaming market data values in the API log file. Historical candlestick data is always recorded in the API log.

Note: Both the API and TWS logs are encrypted locally. The API logs can be decrypted for review from the associated TWS or IB Gateway session, just like the TWS logs, as shown in the section describing the Local location of logs.

Enabling creation of API logs

TWS:

  1. Navigate to File/Edit → Global Configuration → API → Settings
  2. Check the box Create API message log file
  3. Click Apply and Ok

 

IB Gateway:

  1. Navigate to Configure → Settings → API → Settings
  2. Check the box Create API message log file
  3. Click Apply and Ok

TWS Log Files

The TWS Logging Level must be set to the ‘Detail’ level to record information pertinent to the API. By default it is at the ‘Error’ level which records a minimum of diagnostic information. To capture API messages it is necessary to change the Logging Level to ‘Detail’. Note the ‘Logging Level’, like all TWS/IBG settings, is saved separately for different users and for TWS and IBG.

  • Important: The TWS/IB Gateway log file setting has to be set to ‘Detail’ level before an issue occurs so that information recorded correctly when it manifests. However due to the high amount of information that will be generated under this level, the resulting logs can grow considerably in size. It is therefore recommended to use the ‘Detail’ level only when troubleshooting and/or tracking a very specific issue. This can also be done from the API client itself using the IBApi.EClient.setServerLogLevel function. Some third party applications, such as NinjaTrader, are configured to invoke this function to set the TWS Logging Level every time they connect, and so to set the TWS Log to ‘Detail’ this will have to be done from within the API client program.

TWS:

  1. Navigate to File/Edit → Global Configuration → API → Settings
  2. Set Logging Level to Detail

IB Gateway:

  1. Navigate to Configure → Settings → API → Settings
  2. Set Logging Level to Detail

Local location of logs

Logs are stored in the TWS settings directory, C:Jts by default on a Windows computer (the default can be configured differently on the login screen).

The path to the log file directory can be found from a TWS or IB Gateway session by using the combination Ctrl-Alt-U. This will reveal path such as C:Jtsdetcfsvirl (on Windows).

Due to privacy regulations, logs are encrypted before they are saved to disk. They can be decrypted from the associated TWS or IB Gateway session.

  • In TWS: Classic TWS  Help -> Troubleshooting -> Diagnostics -> TWS Logs.
  • In IB Gateway, File -> Gateway Logs.

Uploading Logs

If API logging has been enabled with the setting “Create API Message Log” during the time when an issue occurs, it can be uploaded to the API group.

To upload logs as a Windows user:

  1. In TWS or IB Gateway, press CTRL+ALT+H to bring up the Upload Diagnostics window.
  2. In the “reason” text field, please type the reason for your upload.
    • Alternatively, type “ATTENTION: ” and then the ticket number you are working with, or the name of your customer service representative.
  3. Find the small arrow in the upper right corner, click it and select “Advanced View”
  4. Make sure “Full internal state of the application” is checked
  5. Make sure “Include previous days logs and settings” is unchecked, unless the error happened on a prior day.
  6. Click Submit

To upload logs as a Mac and Linux user:

  1. In TWS or IB Gateway, press CMD+OPT+H to bring up the Upload Diagnostics window.
  2. In the “reason” text field, please type the reason for your upload.
    • Alternatively, type “ATTENTION: ” and then the ticket number you are working with, or the name of your customer service representative.
  3. Find the small arrow in the upper right corner, click it and select “Advanced View”
  4. Make sure “Full internal state of the application” is checked
  5. Make sure “Include previous days logs and settings” is unchecked, unless the error happened on a prior day.
  6. Click Submit

If logs have been uploaded, please let the API Support group know by creating a webticket in the Message Center in Account Management (under Support) indicating the username of the associated TWS session. In some cases a TWS log may also be requested at the Detailed logging level. The TWS log can grow quite large and may not be uploadable by the automatic method; in this case an alternative means of upload can be found.

Exporting Logs

  1. In TWS, navigate to Help menu >> Troubleshooting >> Diagnostics >> “API Logs” or “TWS Logs”.
  2. In IBG, both “API Logs” and “Gateway Logs” are accessible directly from the File menu.
  3. Click “Export Today Logs…” to decrypt the logs and save them in plaintext (logs are stored encrypted on your local machine)

Reading Exported Logs

Each supported API language of the API contains a message file that translates a given number identifier into their corresponding request. The message identifier numbers used in the underlying wire protocol is the core of the TWS API.

The information on the right documents where each message reader file is located. The {TWS API} listed is the path to the primary TWS API or JTS folder created from the API installation.

By default, this will be saved directly on the C: drive.

Both the Incoming and Outgoing message IDs are listed in one file.

{TWS API}sourcepythonclientibapimessages.py

Incoming Message IDs:
{TWS API}sourceJavaClientcomibclientEDecoder.java

Outgoing Message IDs:
{TWS API}sourceJavaClientcomibclientEClient.java

Incoming Message IDs:
{TWS API}sourceCppClientclientEDecoder.h

Outgoing Message IDs:
{TWS API}sourceCppClientclientEClient.h

Incoming Message IDs:
{TWS API}sourceCSharpClientclientIncomingMessage.cs

Outgoing Message IDs:
{TWS API}sourceCSharpClientclientOutgoingMessages.cs

Depending on the Excel structure used, either C# or Java file path will be used.

For ActiveX and RTD, see C#

For DDE, see Java.

In our API logs, the direction of the message is indicated by the arrow at the beginning:

-> for incoming messages (TWS to client)

<- for outgoing messages (client to TWS)

Thus  <- 3 (outgoing request of type 3) is a placeOrder request, and the subsequent incoming requests are:

-> 5 = openOrder response

-> 11 = executionData response

-> 59 = commissionReport response

Also note that the first openOrder response carries with it an orderStatus response in the same message. If that status were to change later, it would be delivered as a standalone message:

-> 3 = orderStatus response

How To Enable Debug Logging

Enabling DEBUG-level logging for the host platform (TWS or IBG, this does not affect API logs):

  1. Navigate to the root TWS/IBG installation directory
  2. Find jts.ini and open in text editor
  3. Put debug=1 under the [Communication] section
  4. Reboot TWS/IBG

Setting debug=1 has added benefits in TWS.

  1. Debug=1 also allows you to enter conIds into a watchlist to resolve them into symbols. Type/paste the conId in an empty watchlist row, add |C (vertical bar, capital C) at the end, and press Enter. Example: 265598|C will resolve immediately to AAPL (exchange will be SMART where available, primary otherwise).
    • If the instrument is already present in the watchlist, nothing will happen.
  2. Additional detail in the “Description” window for an instrument, normally available by right-clicking on an instrument in a watchlist and selecting Financial Instrument Info >> Description from the context menu. Debug=1 will add the conId, min order sizes, market rules (i.e., min price increments and thresholds), all available order types, and all available exchanges to this interface. Changing the behavior of TWS to bring up that Description window on double-click can make it easier to find.
    1. In TWS, go to Global Configuration >> Display >> Ticker Row
    2. Change “Double-click on Financial Instrument will” dropdown menu to “Open Contract Details”

 

Architecture

The IBApi.EWrapper interface is the mechanism through which the TWS delivers information to the API client application. By implementing this interface the client application will be able to receive and handle the information coming from the TWS. For further information on how to implement interfaces, refer to your programming language’s documentation.

class TestWrapper(wrapper.EWrapper):

 

public class EWrapperImpl implements EWrapper {

 

class TestCppClient : public EWrapper
    {

 

public class EWrapperImpl : EWrapper 
   {

 

Public Class EWrapperImpl
    Implements EWrapper

 

The class used to send messages to TWS is IBApi.EClientSocket. Unlike EWrapper, this class is not overriden as the provided functions in EClientSocket are invoked to send messages to TWS. To use EClientSocket, first it may be necessary to implement the IBApi.EWrapper interface as part of its constructor parameters so that the application can handle all returned messages. Messages sent from TWS as a response to function calls in IBApi.EClientSocket require an EWrapper implementation so they can be processed to meet the needs of the API client.

Another crucial element is the IBApi.EReaderSignal object passed to theEClientSocket’s constructor. With the exception of Python, this object is used in APIs to signal a message is ready for processing in the queue. (In Python the Queue class handles this task directly). We will discuss this object in more detail in the The EReader Thread section.

 

In conclusion:

  • EClient functions are for requesting data to IB server.
  • EWrapper functions are for receiving data from IB server.
  • Missing anyone of them cannot let you successfully request/receive data.
class TestClient(EClient):
     def __init__(self, wrapper):
         EClient.__init__(self, wrapper)
...
class TestApp(TestWrapper, TestClient):
	def __init__(self):
	TestWrapper.__init__(self)
         TestClient.__init__(self, wrapper=self)

Note: The EReaderSignal class is not used for Python API. The Python Queue module is used for inter-thread communication and data exchange.

private EReaderSignal readerSignal;
private EClientSocket clientSocket;
protected int currentOrderId = -1;

public EWrapperImpl() {
    readerSignal = new EJavaSignal();
    clientSocket = new EClientSocket(this, readerSignal);
}

 

EReaderOSSignal m_osSignal;
    EClientSocket * const m_pClient;

TestCppClient::TestCppClient() :
      m_osSignal(2000)//2-seconds timeout
    , m_pClient(new EClientSocket(this, &m_osSignal))
    , m_state(ST_CONNECT)
    , m_sleepDeadline(0)
    , m_orderId(0)
    , m_extraAuth(false)
{
}

 

EClientSocket clientSocket;
public readonly EReaderSignal Signal;

public EWrapperImpl()
{
    Signal = new EReaderMonitorSignal();
    clientSocket = new EClientSocket(this, Signal);
}

 

Public eReaderSignal As EReaderSignal
Public socketClient As EClientSocket

Sub New()
    eReaderSignal = New EReaderMonitorSignal
    socketClient = New EClientSocket(Me, eReaderSignal)
End Sub

 

The Trader Workstation

Our market maker-designed IBKR Trader Workstation (TWS) lets traders, investors, and institutions trade stocks, options, futures, forex, bonds, and funds on over 100 markets worldwide from a single account. The TWS API is a programming interface to TWS, and as such, for an application to connect to the API there must first be a running instance of TWS or IB Gateway.

The IB Gateway

As an alternative to TWS for API users, IBKR also offers IB Gateway (IBGW). From the perspective of an API application, IB Gateway and TWS are identical; both represent a server to which an API client application can open a socket connection after the user has authenticated. With either application (TWS or IBGW), the user must manually enter their username and password into a login window. For security reasons, a headless session of TWS or IBGW without a GUI is not supported. From the user’s perspective, IB Gateway may be advantageous because it is a lighter application which consumes about 40% fewer resources.

Both TWS and IBGW were designed to be restarted daily. This is necessary to perform functions such as re-downloading contract definitions in cases where contracts have been changed or new contracts have been added. Beginning in version 974+ both applications offer an autorestart feature that allows the application to restart daily without user intervention. With this option enabled, TWS or IBGW can potentially run from Sunday to Sunday without re-authenticating. After the nightly server reset on Saturday night it will be necessary to again enter security credentials.

The advantages of TWS over IBGW is that it provides the end user with many tools (Risk Navigator, OptionTrader, BookTrader, etc) and a graphical user interface which can be used to monitor an account or place orders. For beginning API users, it is recommended to first become acquainted with TWS before using IBGW.

For simplicity, this guide will mostly refer to the TWS although the reader should understand that for the TWS API’s purposes, TWS and IB Gateway are synonymous.

Connectivity

A socket connection between the API client application and TWS is established with the IBApi.EClientSocket.eConnect function. TWS acts as a server to receive requests from the API application (the client) and responds by taking appropriate actions. The first step is for the API client to initiate a connection to TWS on a socket port where TWS is already listening. It is possible to have multiple TWS instances running on the same computer if each is configured with a different API socket port number. Also, each TWS session can receive up to 32 different client applications simultaneously. The client ID field specified in the API connection is used to distinguish different API clients.

Establishing an API connection

Once our two main objects have been created, EWrapper and ESocketClient, the client application can connect via the IBApi.EClientSocket object:

app.connect("127.0.0.1", args.port, clientId=0)

 

m_client.eConnect("127.0.0.1", 7497, 2);

 

bool bRes = m_pClient->eConnect( host, port, clientId, m_extraAuth);

 

clientSocket.eConnect("127.0.0.1", 7497, 0);

 

socketClient.eConnect("127.0.0.1", 7497, 0)

 

eConnect starts by requesting from the operating system that a TCP socket be opened to the specified IP address and socket port. If the socket cannot be opened, the operating system (not TWS) returns an error which is received by the API client as error code 502 to IBApi.EWrapper.error (Note: since this error is not generated by TWS it is not captured in TWS log files). Most commonly error 502 will indicate that TWS is not running with the API enabled, or it is listening for connections on a different socket port. If connecting across a network, the error can also occur if there is a firewall or antivirus program blocking connections, or if the router’s IP address is not listed in the “Trusted IPs” in TWS.

After the socket has been opened, there must be an initial handshake in which information is exchanged about the highest version supported by TWS and the API. This is important because API messages can have different lengths and fields in different versions and it is necessary to have a version number to interpret received messages correctly.

  • For this reason it is important that the main EReader object is not created until after a connection has been established. The initial connection results in a negotiated common version between TWS and the API client which will be needed by the EReader thread in interpreting subsequent messages.

After the highest version number which can be used for communication is established, TWS will return certain pieces of data that correspond specifically to the logged-in TWS user’s session. This includes (1) the account number(s) accessible in this TWS session, (2) the next valid order identifier (ID), and (3) the time of connection. In the most common mode of operation the EClient.AsyncEConnect field is set to false and the initial handshake is taken to completion immediately after the socket connection is established. TWS will then immediately provides the API client with this information.

  • Important: The IBApi.EWrapper.nextValidID callback is commonly used to indicate that the connection is completed and other messages can be sent from the API client to TWS. There is the possibility that function calls made prior to this time could be dropped by TWS.

There is an alternative, deprecated mode of connection used in special cases in which the variable AsyncEconnect is set to true, and the call to startAPI is only called from the connectAck() function. All IB samples use the mode AsyncEconnect = False.

The EReader Thread

API programs always have at least two threads of execution. One thread is used for sending messages to TWS, and another thread is used for reading returned messages. The second thread uses the API EReader class to read from the socket and add messages to a queue. Everytime a new message is added to the message queue, a notification flag is triggered to let other threads now that there is a message waiting to be processed. In the two-thread design of an API program, the message queue is also processed by the first thread. In a three-thread design, an additional thread is created to perform this task. The thread responsible for the message queue will decode messages and invoke the appropriate functions in EWrapper. The two-threaded design is used in the IB Python sample Program.py and the C++ sample TestCppClient, while the ‘Testbed’ samples in the other languages use a three-threaded design. Commonly in a Python asynchronous network application, the asyncio module will be used to create a more sequential looking code design.

The class which has functionality for reading and parsing raw messages from TWS is the IBApi.EReader class.

In Python IB API, the code below is included in Client::connect(), so the EReader thread is automatically started upon connection. There is no need for user to start the reader.

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() below, where the message queue is processed in an infinite loop and the EWrapper call-back functions are automatically triggered.

# You don't need to run this in your code!
self.reader = reader.EReader(self.conn, self.msg_queue)
self.reader.start()   # start thread
app.run()

 

For C#, Java, C++, and Visual Basic, we instead maintain a triple thread structure which requires the creation of a reader thread, a queue thread, and then a wrapper thread. The documentation listed here further elaborates on the structure for those languages.

final EReader reader = new EReader(m_client, m_signal); 

reader.start();
//An additional thread is created in this program design to empty the messaging queue
new Thread(() -> {
    while (m_client.isConnected()) {
        m_signal.waitForSignal();
        try {
             reader.processMsgs();
        } catch (Exception e) {
            System.out.println("Exception: "+e.getMessage());
        }
    }
}).start();

 

m_pReader = std::unique_ptr<EReader>( new EReader(m_pClient, &m_osSignal) );
m_pReader->start();

 

//Create a reader to consume messages from the TWS. The EReader will consume the incoming messages and put them in a queue
var reader = new EReader(clientSocket, readerSignal);
reader.Start();
//Once the messages are in the queue, an additional thread can be created to fetch them
new Thread(() => { while (clientSocket.IsConnected()) { readerSignal.waitForSignal(); reader.processMsgs(); } }) { IsBackground = true }.Start();
'Once the messages are in the queue, an additional thread need to fetch them
Dim msgThread As Thread = New Thread(AddressOf messageProcessing)
msgThread.IsBackground = True
If (wrapperImpl.serverVersion() > 0) Then Call msgThread.Start()
Private Sub messageProcessing()
    Dim reader As EReader = New EReader(wrapperImpl.socketClient, wrapperImpl.eReaderSignal)
    reader.Start()
    While (wrapperImpl.socketClient.IsConnected)
        wrapperImpl.eReaderSignal.waitForSignal()
        reader.processMsgs()
    End While
End Sub

 

Now it is time to revisit the role of IBApi.EReaderSignal initially introduced in The EClientSocket Class. As mentioned in the previous paragraph, after the EReader thread places a message in the queue, a notification is issued to make known that a message is ready for processing. In the (C++, C#/.NET, Java) APIs, this is done via the IBApi.EReaderSignal object we initiated within the IBApi.EWrapper’s implementer. In the Python API, it is handled automatically by the Queue class.

The client application is now ready to work with the Trader Workstation! At the completion of the connection, the API program will start receiving events such as IBApi.EWrapper.nextValidId and IBApi.EWrapper.managedAccounts. In TWS (not IB Gateway) if there is an active network connection, there will also immediately be callbacks to IBApi::EWrapper::error with errorId as -1 and errorCode=2104,2106, errorMsg = “Market Data Server is ok” to indicate there is an active connection to the IB market data server. Callbacks to IBApi::EWrapper::error with errorId as -1 do not represent true ‘errors’ but only notifications that a connection has been made successfully to the IB market data farms.

IB Gateway by contrast will not make connections to market data farms until a request is made by the IB client. Until this time the connection indicator in the IB Gateway GUI will show a yellow color of ‘inactive’ rather than an ‘active’ green indication.

When initially making requests from an API application it is important that the verifies that a response is received rather than proceeding assuming that the network connection is ok and the subscription request (portfolio updates, account information, etc) was made successfully.

Accepting an API connection from TWS

For security reasons, by default the API is not configured to automatically accept connection requests from API applications. After a connection attempt, a dialogue will appear in TWS asking the user to manually confirm that a connection can be made:

To prevent the TWS from asking the end user to accept the connection, it is possible to configure it to automatically accept the connection from a trusted IP address and/or the local machine. This can easily be done via the TWS API settings:

Note: you have to make sure the connection has been fully established before attempting to do any requests to the TWS. Failure to do so will result in the TWS closing the connection. Typically this can be done by waiting for a callback from an event and the end of the initial connection handshake, such as IBApi.EWrapper.nextValidId or IBApi.EWrapper.managedAccounts.

In rare cases in which IB Gateway or TWS has a momentarily delay in establishing connecting to the IB servers, messages sent immediately after receiving the nextValidId could be dropped and would need to be resent. If the API client has not receive the expected callbacks from issued requests, it should not proceed assumming the connection is ok.

Logging into multiple applications

It is not possible to login to multiple trading applications simultaneously with the same username. However, it is possible to create additional usernames for an account that can be used in different trading applications simultaneously, as long as there is not more than a single trading application logged in with a given username at a time. There are some additional cases in which it is also useful to create additional usernames:

  • If TWS or IBGW is logged in with a username that is used to login to Client Portal during that session, that application will not be able to automatically reconnect to the server after the next disconnection (such as the server reset).
  • A TWS or IBGW session logged into a paper trading account will not to receive market data if it is sharing data from a live user which is used to login to Client Portal.

If a different username is utilized to login to Client Portal in either of these cases, then it will not affect the TWS/IBGW session.

How to add additional usernames in Account Management

  • It is important to note that market data subscriptions are setup independently for each live username.

Broken API socket connection

If there is a problem with the socket connection between TWS and the API client, for instance if TWS suddenly closes, this will trigger an exception in the EReader thread which is reading from the socket. This exception will also occur if an API client attempts to connect with a client ID that is already in use.

The socket EOF is handled slightly differently in different API languages. For instance in Java, it is caught and sent to the client application to IBApi::EWrapper::error with errorCode 507: “Bad Message”. In C# it is caught and sent to IBApi::EWrapper::error with errorCode -1. The client application needs to handle this error message and use it to indicate that an exception has been thrown in the socket connection. Associated functions such as IBApi::EWrapper::connectionClosed and IBApi::EClient::IsConnected functions are not called automatically by the API code but need to be handled at the API client-level*.

Account & Portfolio Data

The IBApi.EClient.reqAccountSummary method creates a subscription for the account data displayed in the TWS Account Summary window. It is commonly used with multiple-account structures. Introducing broker (IBroker) accounts with more than 50 subaccounts or configured for on-demand account lookup cannot use reqAccountSummary with group=”All”. A profile name can be accepted in place of group. See Unification of Groups and Profiles

The TWS offers a comprehensive overview of your account and portfolio through its Account and Portfolio windows. This information can be obtained via the TWS API through three different kind of requests/operations.

Account Summary

The initial invocation of reqAccountSummary will result in a list of all requested values being returned, and then every three minutes those values which have changed will be returned. The update frequency of 3 minutes is the same as the TWS Account Window and cannot be changed.

Requesting Account Summary

Requests a specific account’s summary. This method will subscribe to the account summary as presented in the TWS’ Account Summary tab. Customers can specify the data received by using a specific tags value. See the Account Summary Tags section for available options.

Alternatively, many languages offer the import of AccountSummaryTags with a method to retrieve all tag values.

EClient.reqAccountSummary (

reqId: int. The unique request identifier.

group: String. set to “All” to return account summary data for all accounts, or set to a specific Advisor Account Group name that has already been created in TWS Global Configuration.

tags: String. A comma separated list with the desired tags

)

Important: only two active summary subscriptions are allowed at a time!

self.reqAccountSummary(9001, "All", AccountSummaryTags.AllTags)

 

Code example:

from ibapi.client import *
from ibapi.wrapper import *
from ibapi.contract import Contract
import time

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

    def accountSummary(self, reqId: int, account: str, tag: str, value: str,currency: str):
        print("AccountSummary. ReqId:", reqId, "Account:", account,"Tag: ", tag, "Value:", value, "Currency:", currency)
    
    def accountSummaryEnd(self, reqId: int):
        print("AccountSummaryEnd. ReqId:", reqId)
    
app = TradeApp()      
app.connect("127.0.0.1", 7496, clientId=1)

time.sleep(1)

app.reqAccountSummary(9001, "All", 'NetLiquidation')
app.run()

 

client.reqAccountSummary(9001, "All", "AccountType,NetLiquidation,TotalCashValue,SettledCash,AccruedCash,BuyingPower,EquityWithLoanValue,PreviousEquityWithLoanValue,GrossPositionValue,ReqTEquity,ReqTMargin,SMA,InitMarginReq,MaintMarginReq,AvailableFunds,ExcessLiquidity,Cushion,FullInitMarginReq,FullMaintMarginReq,FullAvailableFunds,FullExcessLiquidity,LookAheadNextChange,LookAheadInitMarginReq ,LookAheadMaintMarginReq,LookAheadAvailableFunds,LookAheadExcessLiquidity,HighestSeverity,DayTradesRemaining,Leverage");

 

m_pClient->reqAccountSummary(9001, "All", AccountSummaryTags::getAllTags());

 

client.reqAccountSummary(9001, "All", AccountSummaryTags.GetAllTags());

 

client.reqAccountSummary(9001, "All", AccountSummaryTags.GetAllTags())

 

Account Summary Tags

AccountType Identifies the IB account structure
NetLiquidation The basis for determining the price of the assets in your account. Total cash value + stock value + options value + bond value
TotalCashValue Total cash balance recognized at the time of trade + futures PNL
SettledCash Cash recognized at the time of settlement – purchases at the time of trade – commissions – taxes – fees
AccruedCash Total accrued cash value of stock, commodities and securities
BuyingPower Buying power serves as a measurement of the dollar value of securities that one may purchase in a securities account without depositing additional funds
EquityWithLoanValue Forms the basis for determining whether a client has the necessary assets to either initiate or maintain security positions. Cash + stocks + bonds + mutual funds
PreviousEquityWithLoanValue Marginable Equity with Loan value as of 16:00 ET the previous day
GrossPositionValue The sum of the absolute value of all stock and equity option positions
RegTEquity Regulation T equity for universal account
RegTMargin Regulation T margin for universal account
SMA Special Memorandum Account: Line of credit created when the market value of securities in a Regulation T account increase in value
InitMarginReq Initial Margin requirement of whole portfolio
MaintMarginReq Maintenance Margin requirement of whole portfolio
AvailableFunds This value tells what you have available for trading
ExcessLiquidity This value shows your margin cushion, before liquidation
Cushion Excess liquidity as a percentage of net liquidation value
FullInitMarginReq Initial Margin of whole portfolio with no discounts or intraday credits
FullMaintMarginReq Maintenance Margin of whole portfolio with no discounts or intraday credits
FullAvailableFunds Available funds of whole portfolio with no discounts or intraday credits
FullExcessLiquidity Excess liquidity of whole portfolio with no discounts or intraday credits
LookAheadNextChange Time when look-ahead values take effect
LookAheadInitMarginReq Initial Margin requirement of whole portfolio as of next period’s margin change
LookAheadMaintMarginReq Maintenance Margin requirement of whole portfolio as of next period’s margin change
LookAheadAvailableFunds This value reflects your available funds at the next margin change
LookAheadExcessLiquidity This value reflects your excess liquidity at the next margin change
HighestSeverity A measure of how close the account is to liquidation
DayTradesRemaining The Number of Open/Close trades a user could put on before Pattern Day Trading is detected. A value of “-1” means that the user can put on unlimited day trades.
Leverage GrossPositionValue / NetLiquidation
$LEDGER Single flag to relay all cash balance tags*, only in base currency.
$LEDGER:CURRENCY Single flag to relay all cash balance tags*, only in the specified currency.
$LEDGER:ALL Single flag to relay all cash balance tags* in all currencies.

Receiving Account Summary

EWrapper.accountSummary (

reqId: int. the request’s unique identifier.

account: String. the account id

tag: String. the account’s attribute being received.

value: String. the account’s attribute’s value.

currency: String. the currency on which the value is expressed.

)

Receives the account information. This method will receive the account information just as it appears in the TWS’ Account Summary Window.

def accountSummary(self, reqId: int, account: str, tag: str, value: str,currency: str):
  print("AccountSummary. ReqId:", reqId, "Account:", account,"Tag: ", tag, "Value:", value, "Currency:", currency)
@Override
public void accountSummary(int reqId, String account, String tag, String value, String currency) {
    System.out.println(EWrapperMsgGenerator.accountSummary(reqId, account, tag, value, currency));
}

 

void TestCppClient::accountSummary( int reqId, const std::string& account, const std::string& tag, const std::string& value, const std::string& currency) {
    printf( "Acct Summary. ReqId: %d, Account: %s, Tag: %s, Value: %s, Currency: %sn", reqId, account.c_str(), tag.c_str(), value.c_str(), currency.c_str());
}
public virtual void accountSummary(int reqId, string account, string tag, string value, string currency)
{
    Console.WriteLine("Acct Summary. ReqId: " + reqId + ", Acct: " + account + ", Tag: " + tag + ", Value: " + value + ", Currency: " + currency);
}
Public Sub accountSummary(reqId As Integer, account As String, tag As String, value As String, currency As String) Implements IBApi.EWrapper.accountSummary
    Console.WriteLine("AccountSummary - ReqId [" & reqId & "] Account [" & account & "] Tag [" & tag & "] Value [" & value & "] Currency [" & currency & "]")
End Sub

EWrapper.accountSummaryEnd(

reqId: String. The request’s identifier.

)

Notifies when all the accounts’ information has ben received. Requires TWS 967+ to receive accountSummaryEnd in linked account structures.

def accountSummaryEnd(self, reqId: int):
    print("AccountSummaryEnd. ReqId:", reqId)

 

@Override
public void accountSummaryEnd(int reqId) {
    System.out.println("Account Summary End. Req Id: " + EWrapperMsgGenerator.accountSummaryEnd(reqId));
}
void TestCppClient::accountSummaryEnd( int reqId) {
    printf( "AccountSummaryEnd. Req Id: %dn", reqId);
}

 

public virtual void accountSummaryEnd(int reqId)
{
    Console.WriteLine("AccountSummaryEnd. Req Id: "+reqId+"n");
}
Public Sub accountSummaryEnd(reqId As Integer) Implements IBApi.EWrapper.accountSummaryEnd
    Console.WriteLine("AccountSummaryEnd - ReqId [" & reqId & "]")
End Sub

 

Cancel Account Summary

Once the subscription to account summary is no longer needed, it can be cancelled via the IBApi::EClient::cancelAccountSummary method:

EClient.cancelAccountSummary (

reqId: int. The identifier of the previously performed account request

)

self.cancelAccountSummary(9001)

 

m_pClient->cancelAccountSummary(9001);

 

Account Updates

The IBApi.EClient.reqAccountUpdates function creates a subscription to the TWS through which account and portfolio information is delivered. This information is the exact same as the one displayed within the TWS’ Account Window. Just as with the TWS’ Account Window, unless there is a position change this information is updated at a fixed interval of three minutes.

Unrealized and Realized P&L is sent to the API function IBApi.EWrapper.updateAccountValue function after a subscription request is made with IBApi.EClient.reqAccountUpdates. This information corresponds to the data in the TWS Account Window, and has a different source of information, a different update frequency, and different reset schedule than PnL data in the TWS Portfolio Window and associated API functions (below). In particular, the unrealized P&L information shown in the TWS Account Window which is sent to updatePortfolioValue will update either (1) when a trade for that particular instrument occurs or (2) every 3 minutes. The realized P&L data in the TWS Account Window is reset to 0 once per day.

It is important to keep in mind that the P&L data shown in the Account Window and Portfolio Window will sometimes differ because there is a different source of information and a different reset schedule.

See Profit & Loss for alternative PnL data

Requesting Account Updates

Subscribes to a specific account’s information and portfolio. Through this method, a single account’s subscription can be started/stopped. As a result from the subscription, the account’s information, portfolio and last update time will be received at EWrapper::updateAccountValue, EWrapper::updateAccountPortfolio, EWrapper::updateAccountTime respectively. All account values and positions will be returned initially, and then there will only be updates when there is a change in a position, or to an account value every 3 minutes if it has changed. Only one account can be subscribed at a time. A second subscription request for another account when the previous one is still active will cause the first one to be canceled in favor of the second one.

EClient.reqAccountUpdates (

subscribe: bool. Set to true to start the subscription and to false to stop it.

acctCode: String. The account id (i.e. U123456) for which the information is requested.

)

self.reqAccountUpdates(True, self.account)

 

Code example:

from ibapi.client import *
from ibapi.wrapper import *
from ibapi.contract import Contract
import time

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

    def updateAccountValue(self, key: str, val: str, currency: str,accountName: str):
        print("UpdateAccountValue. Key:", key, "Value:", val, "Currency:", currency, "AccountName:", accountName)
    
    def updatePortfolio(self, contract: Contract, position: Decimal,marketPrice: float, marketValue: float, averageCost: float, unrealizedPNL: float, realizedPNL: float, accountName: str):
        print("UpdatePortfolio.", "Symbol:", contract.symbol, "SecType:", contract.secType, "Exchange:",contract.exchange, "Position:", decimalMaxString(position), "MarketPrice:", floatMaxString(marketPrice),"MarketValue:", floatMaxString(marketValue), "AverageCost:", floatMaxString(averageCost), "UnrealizedPNL:", floatMaxString(unrealizedPNL), "RealizedPNL:", floatMaxString(realizedPNL), "AccountName:", accountName)

    def updateAccountTime(self, timeStamp: str):
        print("UpdateAccountTime. Time:", timeStamp)

    def accountDownloadEnd(self, accountName: str):
        print("AccountDownloadEnd. Account:", accountName)
    
app = TradeApp()      
app.connect("127.0.0.1", 7496, clientId=1)

time.sleep(1)

app.reqAccountUpdates(True, 'U123456')
app.run()

 

client.reqAccountUpdates(true, "U1234567");

 

m_pClient->reqAccountUpdates(true, "U150462");

 

client.reqAccountUpdates(true, "U1234567");

 

client.reqAccountUpdates(True, "U1234567")

 

Receiving Account Updates

Resulting account and portfolio information will be delivered via the IBApi.EWrapper.updateAccountValue, IBApi.EWrapper.updatePortfolio, IBApi.EWrapper.updateAccountTime and IBApi.EWrapper.accountDownloadEnd

EWrapper.updateAccountValue (

key: String. The value being updated.

value: String. up-to-date value

currency: String. The currency on which the value is expressed.

accountName: String. The account identifier.
)

Receives the subscribed account’s information. Only one account can be subscribed at a time. After the initial callback to updateAccountValue, callbacks only occur for values which have changed. This occurs at the time of a position change, or every 3 minutes at most. This frequency cannot be adjusted.

def updateAccountValue(self, key: str, val: str, currency: str,accountName: str):
    print("UpdateAccountValue. Key:", key, "Value:", val, "Currency:", currency, "AccountName:", accountName)

 

@Override
public void updateAccountValue(String key, String value, String currency, String accountName) {
    System.out.println(EWrapperMsgGenerator.updateAccountValue( key, value, currency, accountName));
}

 

void TestCppClient::updateAccountValue(const std::string& key, const std::string& val, const std::string& currency, const std::string& accountName) {
    printf("UpdateAccountValue. Key: %s, Value: %s, Currency: %s, Account Name: %sn", key.c_str(), val.c_str(), currency.c_str(), accountName.c_str());
}

 

public virtual void updateAccountValue(string key, string value, string currency, string accountName)
{
    Console.WriteLine("UpdateAccountValue. Key: " + key + ", Value: " + value + ", Currency: " + currency + ", AccountName: " + accountName);
}

 

Public Sub updateAccountValue(key As String, value As String, currency As String, accountName As String) Implements IBApi.EWrapper.updateAccountValue
        Console.WriteLine("UpdateAccountValue. Key: " & key & ", Value: " & value & ", Currency: " & currency & ", AccountName: " & accountName)
End Sub

 

EWrapper.updatePortfolio (

contract: Contract. The Contract for which a position is held.

position: Decimal. The number of positions held.

marketPrice: Double. The instrument’s unitary price

marketValue: Double. Total market value of the instrument.

averageCost: Double. Average cost of the overall position.

unrealizedPNL: Double. Daily unrealized profit and loss on the position.

realizedPNL: Double. Daily realized profit and loss on the position.

accountName: String. Account ID for the update.

)

Receives the subscribed account’s portfolio. This function will receive only the portfolio of the subscribed account. After the initial callback to updatePortfolio, callbacks only occur for positions which have changed.

def updatePortfolio(self, contract: Contract, position: Decimal,marketPrice: float, marketValue: float, averageCost: float, unrealizedPNL: float, realizedPNL: float, accountName: str):
    print("UpdatePortfolio.", "Symbol:", contract.symbol, "SecType:", contract.secType, "Exchange:",contract.exchange, "Position:", decimalMaxString(position), "MarketPrice:", floatMaxString(marketPrice),"MarketValue:", floatMaxString(marketValue), "AverageCost:", floatMaxString(averageCost), "UnrealizedPNL:", floatMaxString(unrealizedPNL), "RealizedPNL:", floatMaxString(realizedPNL), "AccountName:", accountName)

 

@Override
public void updatePortfolio(Contract contract, Decimal position, double marketPrice, double marketValue, double averageCost, double unrealizedPNL, double realizedPNL, String accountName) {
    System.out.println(EWrapperMsgGenerator.updatePortfolio( contract, position, marketPrice, marketValue, averageCost, unrealizedPNL, realizedPNL, accountName));
}

 

void TestCppClient::updatePortfolio(const Contract& contract, Decimal position, double marketPrice, double marketValue, double averageCost, double unrealizedPNL, double realizedPNL, const std::string& accountName){
    printf("UpdatePortfolio. %s, %s @ %s: Position: %s, MarketPrice: %s, MarketValue: %s, AverageCost: %s, UnrealizedPNL: %s, RealizedPNL: %s, AccountName: %sn", (contract.symbol).c_str(), (contract.secType).c_str(), (contract.primaryExchange).c_str(), decimalStringToDisplay(position).c_str(), Utils::doubleMaxString(marketPrice).c_str(), Utils::doubleMaxString(marketValue).c_str(), Utils::doubleMaxString(averageCost).c_str(), Utils::doubleMaxString(unrealizedPNL).c_str(), Utils::doubleMaxString(realizedPNL).c_str(), accountName.c_str());
}

 

public virtual void updatePortfolio(Contract contract, decimal position, double marketPrice, double marketValue, double averageCost, double unrealizedPNL, double realizedPNL, string accountName)
{
    Console.WriteLine("UpdatePortfolio. " + contract.Symbol + ", " + contract.SecType + " @ " + contract.Exchange + ": Position: " + Util.DecimalMaxString(position) + ", MarketPrice: " + Util.DoubleMaxString(marketPrice) + ", MarketValue: " + Util.DoubleMaxString(marketValue) +  ", AverageCost: " + Util.DoubleMaxString(averageCost) + ", UnrealizedPNL: " + Util.DoubleMaxString(unrealizedPNL) + ", RealizedPNL: " + Util.DoubleMaxString(realizedPNL) +  ", AccountName: " + accountName);
}

 

Public Sub updatePortfolio(contract As IBApi.Contract, position As Decimal, marketPrice As Double, marketValue As Double, averageCost As Double, unrealizedPNL As Double, realizedPNL As Double, accountName As String) Implements IBApi.EWrapper.updatePortfolio
        Console.WriteLine("UpdatePortfolio. " & contract.Symbol & ", " & contract.SecType & " @ " & contract.Exchange & ": Position: " & Util.DecimalMaxString(position) & ", MarketPrice: " & Util.DoubleMaxString(marketPrice) & ", MarketValue: " & Util.DoubleMaxString(marketValue) & ", AverageCost: " & Util.DoubleMaxString(averageCost) & ", UnrealizedPNL: " & Util.DoubleMaxString(unrealizedPNL) & ", RealizedPNL: " & Util.DoubleMaxString(realizedPNL) & ", AccountName: " & accountName)
End Sub

 

EWrapper.updateAccountTime (

timestamp: String. the last update system time.

)

Receives the last time on which the account was updated.

def updateAccountTime(self, timeStamp: str):
     print("UpdateAccountTime. Time:", timeStamp)

 

@Override
public void updateAccountTime(String timeStamp) {
    System.out.println(EWrapperMsgGenerator.updateAccountTime( timeStamp));
}

 

void TestCppClient::updateAccountTime(const std::string& timeStamp) {
    printf( "UpdateAccountTime. Time: %sn", timeStamp.c_str());
}

 

public virtual void updateAccountTime(string timestamp)
{
        Console.WriteLine("UpdateAccountTime. Time: " + timestamp+"n");
}

 

Public Sub updateAccountTime(timestamp As String) Implements IBApi.EWrapper.updateAccountTime
    Console.WriteLine("UpdateAccountTime. Time: " & timestamp)
End Sub

 

EWrapper.accountDownloadEnd (

account: String. The account identifier.

)

Notifies when all the account’s information has finished.

def accountDownloadEnd(self, accountName: str):
    print("AccountDownloadEnd. Account:", accountName)

 

@Override
public void accountDownloadEnd(String accountName) {
    System.out.println(EWrapperMsgGenerator.accountDownloadEnd(accountName));
}

 

void TestCppClient::accountDownloadEnd(const std::string& accountName) {
    printf( "Account download finished: %sn", accountName.c_str());
}

 

public virtual void accountDownloadEnd(string account)
{
    Console.WriteLine("Account download finished: "+account+"n");
}

 

Public Sub accountDownloadEnd(account As String) Implements IBApi.EWrapper.accountDownloadEnd
    Console.WriteLine("accountDownloadEnd - Account[" & account & "]")
End Sub

 

Account Value Keys

When requesting reqAccountUpdates customers will receive values corresponding to various account key/value pairs. The table below documents potential responses and what they mean.

Account values delivered via IBApi.EWrapper.updateAccountValue can be classified in the following way:

  • Commodities: suffixed by a “-C”
  • Securities: suffixed by a “-S”
  • Totals: no suffix
Key Description
AccountCode The account ID number
AccountOrGroup “All” to return account summary data for all accounts, or set to a specific Advisor Account Group name that has already been created in TWS Global Configuration
AccountReady For internal use only
AccountType Identifies the IB account structure
AccruedCash Total accrued cash value of stock, commodities and securities
AccruedCash-C Reflects the current’s month accrued debit and credit interest to date, updated daily in commodity segment
AccruedCash-S Reflects the current’s month accrued debit and credit interest to date, updated daily in security segment
AccruedDividend Total portfolio value of dividends accrued
AccruedDividend-C Dividends accrued but not paid in commodity segment
AccruedDividend-S Dividends accrued but not paid in security segment
AvailableFunds This value tells what you have available for trading
AvailableFunds-C Net Liquidation Value – Initial Margin
AvailableFunds-S Equity with Loan Value – Initial Margin
Billable Total portfolio value of treasury bills
Billable-C Value of treasury bills in commodity segment
Billable-S Value of treasury bills in security segment
BuyingPower Cash Account: Minimum (Equity with Loan Value, Previous Day Equity with Loan Value)-Initial Margin, Standard Margin Account: Minimum (Equity with Loan Value, Previous Day Equity with Loan Value) – Initial Margin *4
CashBalance Cash recognized at the time of trade + futures PNL
CorporateBondValue Value of non-Government bonds such as corporate bonds and municipal bonds
Currency Open positions are grouped by currency
Cushion Excess liquidity as a percentage of net liquidation value
DayTradesRemaining Number of Open/Close trades one could do before Pattern Day Trading is detected
DayTradesRemainingT+1 Number of Open/Close trades one could do tomorrow before Pattern Day Trading is detected
DayTradesRemainingT+2 Number of Open/Close trades one could do two days from today before Pattern Day Trading is detected
DayTradesRemainingT+3 Number of Open/Close trades one could do three days from today before Pattern Day Trading is detected
DayTradesRemainingT+4 Number of Open/Close trades one could do four days from today before Pattern Day Trading is detected
EquityWithLoanValue Forms the basis for determining whether a client has the necessary assets to either initiate or maintain security positions
EquityWithLoanValue-C Cash account: Total cash value + commodities option value – futures maintenance margin requirement + minimum (0, futures PNL) Margin account: Total cash value + commodities option value – futures maintenance margin requirement
EquityWithLoanValue-S Cash account: Settled Cash Margin Account: Total cash value + stock value + bond value + (non-U.S. & Canada securities options value)
ExcessLiquidity This value shows your margin cushion, before liquidation
ExcessLiquidity-C Equity with Loan Value – Maintenance Margin
ExcessLiquidity-S Net Liquidation Value – Maintenance Margin
ExchangeRate The exchange rate of the currency to your base currency
FullAvailableFunds Available funds of whole portfolio with no discounts or intraday credits
FullAvailableFunds-C Net Liquidation Value – Full Initial Margin
FullAvailableFunds-S Equity with Loan Value – Full Initial Margin
FullExcessLiquidity Excess liquidity of whole portfolio with no discounts or intraday credits
FullExcessLiquidity-C Net Liquidation Value – Full Maintenance Margin
FullExcessLiquidity-S Equity with Loan Value – Full Maintenance Margin
FullInitMarginReq Initial Margin of whole portfolio with no discounts or intraday credits
FullInitMarginReq-C Initial Margin of commodity segment’s portfolio with no discounts or intraday credits
FullInitMarginReq-S Initial Margin of security segment’s portfolio with no discounts or intraday credits
FullMaintMarginReq Maintenance Margin of whole portfolio with no discounts or intraday credits
FullMaintMarginReq-C Maintenance Margin of commodity segment’s portfolio with no discounts or intraday credits
FullMaintMarginReq-S Maintenance Margin of security segment’s portfolio with no discounts or intraday credits
FundValue Value of funds value (money market funds + mutual funds)
FutureOptionValue Real-time market-to-market value of futures options
FuturesPNL Real-time changes in futures value since last settlement
FxCashBalance Cash balance in related IB-UKL account
GrossPositionValue Gross Position Value in securities segment
GrossPositionValue-S Long Stock Value + Short Stock Value + Long Option Value + Short Option Value
IndianStockHaircut Margin rule for IB-IN accounts
InitMarginReq Initial Margin requirement of whole portfolio
InitMarginReq-C Initial Margin of the commodity segment in base currency
InitMarginReq-S Initial Margin of the security segment in base currency
IssuerOptionValue Real-time mark-to-market value of Issued Option
Leverage-S GrossPositionValue / NetLiquidation in security segment
LookAheadNextChange Time when look-ahead values take effect
LookAheadAvailableFunds This value reflects your available funds at the next margin change
LookAheadAvailableFunds-C Net Liquidation Value – look ahead Initial Margin
LookAheadAvailableFunds-S Equity with Loan Value – look ahead Initial Margin
LookAheadExcessLiquidity This value reflects your excess liquidity at the next margin change
LookAheadExcessLiquidity-C Net Liquidation Value – look ahead Maintenance Margin
LookAheadExcessLiquidity-S Equity with Loan Value – look ahead Maintenance Margin
LookAheadInitMarginReq Initial margin requirement of whole portfolio as of next period’s margin change
LookAheadInitMarginReq-C Initial margin requirement as of next period’s margin change in the base currency of the account
LookAheadInitMarginReq-S Initial margin requirement as of next period’s margin change in the base currency of the account
LookAheadMaintMarginReq Maintenance margin requirement of whole portfolio as of next period’s margin change
LookAheadMaintMarginReq-C Maintenance margin requirement as of next period’s margin change in the base currency of the account
LookAheadMaintMarginReq-S Maintenance margin requirement as of next period’s margin change in the base currency of the account
MaintMarginReq Maintenance Margin requirement of whole portfolio
MaintMarginReq-C Maintenance Margin for the commodity segment
MaintMarginReq-S Maintenance Margin for the security segment
MoneyMarketFundValue Market value of money market funds excluding mutual funds
MutualFundValue Market value of mutual funds excluding money market funds
NetDividend The sum of the Dividend Payable/Receivable Values for the securities and commodities segments of the account
NetLiquidation The basis for determining the price of the assets in your account
NetLiquidation-C Total cash value + futures PNL + commodities options value
NetLiquidation-S Total cash value + stock value + securities options value + bond value
NetLiquidationByCurrency Net liquidation for individual currencies
OptionMarketValue Real-time mark-to-market value of options
PASharesValue Personal Account shares value of whole portfolio
PASharesValue-C Personal Account shares value in commodity segment
PASharesValue-S Personal Account shares value in security segment
PostExpirationExcess Total projected “at expiration” excess liquidity
PostExpirationExcess-C Provides a projected “at expiration” excess liquidity based on the soon-to expire contracts in your portfolio in commodity segment
PostExpirationExcess-S Provides a projected “at expiration” excess liquidity based on the soon-to expire contracts in your portfolio in security segment
PostExpirationMargin Total projected “at expiration” margin
PostExpirationMargin-C Provides a projected “at expiration” margin value based on the soon-to expire contracts in your portfolio in commodity segment
PostExpirationMargin-S Provides a projected “at expiration” margin value based on the soon-to expire contracts in your portfolio in security segment
PreviousDayEquityWithLoanValue Marginable Equity with Loan value as of 16:00 ET the previous day in securities segment
PreviousDayEquityWithLoanValue-S IMarginable Equity with Loan value as of 16:00 ET the previous day
RealCurrency Open positions are grouped by currency
RealizedPnL Shows your profit on closed positions, which is the difference between your entry execution cost and exit execution costs, or (execution price + commissions to open the positions) – (execution price + commissions to close the position)
RegTEquity Regulation T equity for universal account
RegTEquity-S Regulation T equity for security segment
RegTMargin Regulation T margin for universal account
RegTMargin-S Regulation T margin for security segment
SMA Line of credit created when the market value of securities in a Regulation T account increase in value
SMA-S Regulation T Special Memorandum Account balance for security segment
SegmentTitle Account segment name
StockMarketValue Real-time mark-to-market value of stock
TBondValue Value of treasury bonds
TBillValue Value of treasury bills
TotalCashBalance Total Cash Balance including Future PNL
TotalCashValue Total cash value of stock, commodities and securities
TotalCashValue-C CashBalance in commodity segment
TotalCashValue-S CashBalance in security segment
TradingType-S Account Type
UnrealizedPnL The difference between the current market value of your open positions and the average cost, or Value – Average Cost
WarrantValue Value of warrants
WhatIfPMEnabled To check projected margin requirements under Portfolio Margin model

Cancel Account Updates

Once the subscription to account updates is no longer needed, it can be cancelled by invoking the IBApi.EClient.reqAccountUpdates method while specifying the susbcription flag to be False.

Note: An important key passed back in IBApi.EWrapper.updateAccountValue after a call to IBApi.EClient.reqAccountUpdates is a boolean value ‘accountReady’. If an accountReady value of false is returned that means that the IB server is in the process of resetting at that moment, i.e. the account is ‘not ready’. When this occurs subsequent key values returned to IBApi::EWrapper::updateAccountValue in the current update can be out of date or incorrect.

Important: only one account at a time can be subscribed at a time. Attempting a second subscription without previously cancelling an active one will not yield any error message although it will override the already subscribed account with the new one. With Financial Advisory (FA) account structures there is an alternative way of specifying the account code such that information is returned for ‘All’ sub accounts- this is done by appending the letter ‘A’ to the end of the account number, i.e. reqAccountUpdates(true, “F123456A”)

EClient.reqAccountUpdates (

subscribe: bool. Set to true to start the subscription and to false to stop it.

acctCode: String. The account id (i.e. U123456) for which the information is requested.

)

self.reqAccountUpdates(False, self.account)

 

client.reqAccountUpdates(false, "U1234567");

 

m_pClient->reqAccountUpdates(true, "U150462");

 

client.reqAccountUpdates(true, "U1234567");

 

client.reqAccountUpdates(True, "U1234567")

 

Account Update by Model

Requesting Account Update by Model

The IBApi.EClient.reqAccountUpdatesMulti can be used in any account structure to create simultaneous account value subscriptions from one or multiple accounts and/or models. As with IBApi.EClient.reqAccountUpdates the data returned will match that displayed within the TWS Account Window.

EClient.reqAccountUpdatesMulti (

reqId: int. Identifier to label the request

account: String. Account values can be requested for a particular account

modelCode: String. Values can also be requested for a model

ledgerAndNLV: bool. returns light-weight request; only currency positions as opposed to account values and currency positions

)

Requests account updates for account and/or model.

IBApi.EClient.reqAccountUpdatesMulti cannot be used with Account=”All” in IBroker accounts with more than 50 subaccounts.

A profile name can be accepted in place of group in the account parameter for Financial Advisors

self.reqAccountUpdatesMulti(reqId, self.account, "", True)

 

Code example:

from ibapi.client import *
from ibapi.wrapper import *
import time

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

    def accountUpdateMulti(self, reqId: int, account: str, modelCode: str, key: str, value: str, currency: str):
        print("AccountUpdateMulti. RequestId:", reqId, "Account:", account, "ModelCode:", modelCode, "Key:", key, "Value:", value, "Currency:", currency)

    def accountUpdateMultiEnd(self, reqId: int):
        print("AccountUpdateMultiEnd. RequestId:", reqId)
    
app = TradeApp()      
app.connect("127.0.0.1", 7496, clientId=1)

time.sleep(1)

app.reqAccountUpdatesMulti(103, 'U123456', "", True)

app.run()

 

client.reqAccountUpdatesMulti(reqId, "U1234567", "", true);

 

m_pClient->reqAccountUpdatesMulti(reqId, "U1234567", "", true);

 

client.reqAccountUpdatesMulti(reqId, "U1234567", "", true);

 

client.reqAccountUpdatesMulti(reqId, "U1234567", "", True)

 

Receiving Account Updates by Model

The resulting account and portfolio information will be delivered via the IBApi.EWrapper.accountUpdateMulti and IBApi.EWrapper.accountUpdateMultiEnd

EWrapper.accountUpdateMulti (

requestId: int. The id of request.

account: String. The account with updates.

modelCode: String. The model code with updates.

key: String. The name of parameter.

value: String. The value of parameter.

currency: String. The currency of parameter.
)

Provides the account updates.

def accountUpdateMulti(self, reqId: int, account: str, modelCode: str, key: str, value: str, currency: str):
  print("AccountUpdateMulti. RequestId:", reqId, "Account:", account, "ModelCode:", modelCode, "Key:", key, "Value:", value, "Currency:", currency)

 

@Override
public void accountUpdateMulti(int reqId, String account, String modelCode, String key, String value, String currency) {
    System.out.println("Account Update Multi: " + EWrapperMsgGenerator.accountUpdateMulti(reqId, account, modelCode, key, value, currency));
}

 

void TestCppClient::accountUpdateMulti( int reqId, const std::string& account, const std::string& modelCode, const std::string& key, const std::string& value, const std::string& currency) {
    printf("AccountUpdate Multi. Request: %d, Account: %s, ModelCode: %s, Key, %s, Value: %s, Currency: %sn", reqId, account.c_str(), modelCode.c_str(), key.c_str(), value.c_str(), currency.c_str());
}

 

public virtual void accountUpdateMulti(int reqId, string account, string modelCode, string key, string value, string currency)
{
    Console.WriteLine("Account Update Multi. Request: " + reqId + ", Account: " + account + ", ModelCode: " + modelCode + ", Key: " + key + ", Value: " + value + ", Currency: " + currency + "n");
}

 

Public Sub accountUpdateMulti(requestId As Integer, account As String, modelCode As String, key As String, value As String, currency As String) Implements IBApi.EWrapper.accountUpdateMulti
    Console.WriteLine("accountUpdateMulti. Id: " & requestId & ", Account: " & account & ", modelCode: " & modelCode & ", key: " & key & ", value: " & value & ", currency: " & currency)
End Sub

 

EWrapper.accountUpdateMultiEnd (

requestId: int. The id of request

)

Indicates all the account updates have been transmitted.

def accountUpdateMultiEnd(self, reqId: int):
    print("AccountUpdateMultiEnd. RequestId:", reqId)

 

@Override
public void accountUpdateMultiEnd(int reqId, ) {
    System.out.println( "Account Update Multi End: " + EWrapperMsgGenerator.accountUpdateMultiEnd(reqId));
}

 

void TestCppClient::accountUpdateMultiEnd( int reqId) {
    printf("Account Update Multi End. Request: %dn", reqId);
}

 

public virtual void accountUpdateMultiEnd(int reqId)
{
    Console.WriteLine("Account Update Multi End. Request: " + reqId + "n");
}

 

Public Sub accountUpdateMultiEnd(requestId As Integer) Implements IBApi.EWrapper.accountUpdateMultiEnd
    Console.WriteLine("accountUpdateMultiEnd. id: " & requestId)
End Sub

 

Cancel Account Updates by Model

EClient.reqAccountUpdatesMulti (

reqId: int. Identifier to label the request

account: String. Account values can be requested for a particular account

modelCode: String. Values can also be requested for a model

ledgerAndNLV: bool. Specify false to cancel your subscription.

)

self.reqAccountUpdatesMulti(reqId, self.account, "", False)

 

client.reqAccountUpdatesMulti(reqId, "U1234567", "", false);

 

m_pClient->reqAccountUpdatesMulti(reqId, "U1234567", "", true);

 

client.reqAccountUpdatesMulti(reqId, "U1234567", "", false);

 

client.reqAccountUpdatesMulti(reqId, "U1234567", "", False)

 

Family Codes

It is possible to determine from the API whether an account exists under an account family, and find the family code using the function reqFamilyCodes.

For instance, if individual account U112233 is under a financial advisor with account number F445566, if the function reqFamilyCodes is invoked for the user of account U112233, the family code “F445566A” will be returned, indicating that it belongs within that account family.

Request Family Codes

EClient.reqFamilyCodes()

Requests family codes for an account, for instance if it is a FA, IBroker, or associated account.

self.reqFamilyCodes()

 

client.reqFamilyCodes();

 

m_pClient->reqFamilyCodes();

 

client.reqFamilyCodes()

 

client.reqFamilyCodes()

 

Receive Family Codes

EWrapper.familyCodes(

familyCodes: FamilyCodes[]. Unique family codes array of accountIds.

)

Returns array of family codes.

def familyCodes(self, familyCodes: ListOfFamilyCode):
    print("Family Codes:", familyCode)

 

@Override
public void familyCodes(FamilyCode[] familyCodes) {
    System.out.print(EWrapperMsgGenerator.familyCodes(familyCodes));
}

 

void TestCppClient::familyCodes(const std::vector<FamilyCode> &familyCodes) {
    printf("Family codes (%lu):n", familyCodes.size());
    for (unsigned int i = 0; i < familyCodes.size(); i++) {
        printf("Family code [%d] - accountID: %s familyCodeStr: %sn", i, familyCodes[i].accountID.c_str(), familyCodes[i].familyCodeStr.c_str());
    }
}

 

public void familyCodes(FamilyCode[] familyCodes)
{
  Console.WriteLine("Family Codes:");
  foreach (var familyCode in familyCodes)
  {
    Console.WriteLine("Account ID: {0}, Family Code Str: {1}", familyCode.AccountID, familyCode.FamilyCodeStr);
  }
}

 

Public Sub familyCodes(familyCodes As FamilyCode()) Implements EWrapper.familyCodes
  Console.WriteLine("Family Codes:")
  For Each familyCode In familyCodes
    Console.WriteLine("Account ID: " & familyCode.AccountID & " Family Code Str: " & familyCode.FamilyCodeStr)
  Next
End Sub

 

Managed Accounts

A single user name can handle more than one account. As mentioned in the Connectivity section, the TWS will automatically send a list of managed accounts once the connection is established. The list can also be fetched via the IBApi.EClient.reqManagedAccts method.

Request Managed Accounts

EClient.reqManagedAccts()

Requests the accounts to which the logged user has access to.

self.reqManagedAccts()

 

client.reqManagedAccts();

 

m_pClient->reqManagedAccts();

 

client.reqManagedAccts();

 

client.reqManagedAccts()

 

Receive Managed Accounts

EWrapper.managedAccounts (

accountsList: String. A comma-separated string with the managed account ids.

)

Returns a string of all available accounts for the logged in user. Occurs automatically on initial API client connection.

def managedAccounts(self, accountsList: str):
    print("Account list:", accountsList)

 

@Override
public void managedAccounts(String accountsList) {
	System.out.println("Account list: " + accountsList);
}

 

void TestCppClient::managedAccounts( const std::string& accountsList) {
    printf( "Account List: %sn", accountsList.c_str());
}

 

public virtual void managedAccounts(string accountsList) 
{
	Console.WriteLine("Account list: "+accountsList);
}

 

Public Sub managedAccounts(accountsList As String) Implements IBApi.EWrapper.managedAccounts
	Console.WriteLine("ManagedAccounts - AccountsList [" & accountsList & "]")
End Sub

 

Positions

A limitation of the function IBApi.EClient.reqAccountUpdates is that it can only be used with a single account at a time. To create a subscription for position updates from multiple accounts, the function IBApi.EClient.reqPositions is available.

Note: The reqPositions function is not available in Introducing Broker or Financial Advisor master accounts that have very large numbers of subaccounts (> 50) to optimize the performance of TWS/IB Gateway. Instead the function reqPositionsMulti can be used to subscribe to updates from individual subaccounts. Also not available with IBroker accounts configured for on-demand account lookup.

After initially invoking reqPositions, information about all positions in all associated accounts will be returned, followed by the IBApi::EWrapper::positionEnd callback. Thereafter, when a position has changed an update will be returned to the IBApi::EWrapper::position function. To cancel a reqPositions subscription, invoke IBApi::EClient::cancelPositions.

Request Positions

EClient.reqPositions()

Subscribes to position updates for all accessible accounts. All positions sent initially, and then only updates as positions change.

self.reqPositions()

 

Code example:

from ibapi.client import *
from ibapi.wrapper import *
import threading
import time

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

    def position(self, account: str, contract: Contract, position: Decimal, avgCost: float):
        print("Position.", "Account:", account, "Contract:", contract, "Position:", position, "Avg cost:", avgCost)
        
    def positionEnd(self):
       print("PositionEnd")
       
def websocket_con():
    app.run()
    
app = TradingApp()      
app.connect("127.0.0.1", 7496, clientId=1)

con_thread = threading.Thread(target=websocket_con, daemon=True)
con_thread.start()
time.sleep(1) 

app.reqPositions()
time.sleep(1)

 

client.reqPositions();

 

m_pClient->reqPositions();

 

client.reqPositions();

 

client.reqPositions()

 

Receive Positions

EWrapper.position(

account: String. The account holding the position.

contract: Contract. The position’s Contract

pos: decimal. The number of positions held. avgCost the average cost of the position.

avgCost: double. The total average cost of all trades for the currently held position.
)

Provides the portfolio’s open positions. After the initial callback (only) of all positions, the IBApi.EWrapper.positionEnd function will be triggered.

For futures, the exchange field will not be populated in the position callback as some futures trade on multiple exchanges

def position(self, account: str, contract: Contract, position: Decimal, avgCost: float):
  print("Position.", "Account:", account, "Contract:", contract, "Position:", position, "Avg cost:", avgCost)

 

@Override
public void position(String account, Contract contract, Decimal pos, double avgCost) {
    System.out.println(EWrapperMsgGenerator.position(account, contract, pos, avgCost));
}

 

@Override
public void position(String account, Contract contract, Decimal pos, double avgCost) {
    System.out.println(EWrapperMsgGenerator.position(account, contract, pos, avgCost));
}

 

public virtual void position(string account, Contract contract, decimal pos, double avgCost)
{
Console.WriteLine("Position. " + account + " - Symbol: " + contract.Symbol + ", SecType: " + contract.SecType + ", Currency: " + contract.Currency + ", Position: " + Util.DecimalMaxString(pos) + ", Avg cost: " + Util.DoubleMaxString(avgCost));
}

 

Public Sub position(account As String, contract As IBApi.Contract, pos As Decimal, avgCost As Double) Implements IBApi.EWrapper.position
  Console.WriteLine("Position. " & account & " - Symbol: " & contract.Symbol & ", SecType: " & contract.SecType & ", Currency: " &  contract.Currency & ", Position: " & Util.DecimalMaxString(pos) & ", Avg cost: " & Util.DoubleMaxString(avgCost))
End Sub

 

Ewrapper.positionEnd() 

Indicates all the positions have been transmitted. Only returned after the initial callback of EWrapper.position.

def positionEnd(self):
  print("PositionEnd")

 

@Override
public void positionEnd() {
	System.out.println("Position End: " + EWrapperMsgGenerator.positionEnd());
}

 

void TestCppClient::positionEnd() {
    printf( "PositionEndn");
}

 

public virtual void positionEnd()
{
	Console.WriteLine("PositionEnd n");
}

 

Public Sub positionEnd() Implements IBApi.EWrapper.positionEnd
	Console.WriteLine("PositionEnd")
End Sub

 

Cancel Positions Request

EClient.cancelPositions()

Cancels a previous position subscription request made with EClient.reqPositions().

self.cancelPositions()

 

client.cancelPositions();

 

m_pClient->cancelPositions();

 

client.cancelPositions()

 

client.cancelPositions()

 

Positions By Model

The function IBApi.EClient.reqPositionsMulti can be used with any account structure to subscribe to positions updates for multiple accounts and/or models. The account and model parameters are optional if there are not multiple accounts or models available. It is more efficient to use this function for a specific subset of accounts than using IBApi.EClient.reqPositions. A profile name can be accepted in place of group in the account parameter.

Request Positions By Model

EClient.reqPositionsMulti(

requestId: int. Request’s identifier.

account: String. If an account Id is provided, only the account’s positions belonging to the specified model will be delivered.

modelCode: String. The code of the model’s positions we are interested in.
)

Requests position subscription for account and/or model Initially all positions are returned, and then updates are returned for any position changes in real time.

self.reqPositionsMulti(requestid, "U1234567", "")

 

Code example:

from ibapi.client import *
from ibapi.wrapper import *
import threading
import time

class TradingApp(EWrapper, EClient):
    def __init__(self):
        EClient.__init__(self,self)
            
    def positionMulti(self, reqId: int, account: str, modelCode: str, contract: Contract, pos: Decimal, avgCost: float):
       print("PositionMulti. RequestId:", reqId, "Account:", account, "ModelCode:", modelCode, "Contract:", contract, ",Position:", pos, "AvgCost:", avgCost)         
        
    def positionMultiEnd(self, reqId: int):
        print("")
        print("PositionMultiEnd. RequestId:", reqId)       

def websocket_con():
    app.run()
    
app = TradingApp()      
app.connect("127.0.0.1", 7497, clientId=1)

con_thread = threading.Thread(target=websocket_con, daemon=True)
con_thread.start()
time.sleep(1) 

app.reqPositionsMulti(2, "DU1234567", "")  #To specify a U-account number
time.sleep(1)

app.reqPositionsMulti(3, "Group1", "")     #To specify a Financial Advisor Group / Profile 
time.sleep(1)

 

client.reqPositionsMulti(requestid, "U1234567", "");

 

m_pClient->reqPositionsMulti(requestid, "U1234567", "");

 

client.reqPositionsMulti(requestid, "U1234567", "");

 

client.reqPositionsMulti(requestid, "U1234567", "")

 

Receive Positions By Model

EWrapper.positionMulti(

requestId: int. The id of request

account: String. The account holding the position.

modelCode: String. The model code holding the position.

contract: Contract. The position’s Contract

pos: decimal. The number of positions held.

avgCost: double. The average cost of the position.
)

Provides the portfolio’s open positions.

def positionMulti(self, reqId: int, account: str, modelCode: str, contract: Contract, pos: Decimal, avgCost: float):
  print("PositionMulti. RequestId:", reqId, "Account:", account, "ModelCode:", modelCode, "Contract:", contract, ",Position:", pos, "AvgCost:", avgCost)

 

@Override
public void positionMulti(int reqId, String account, String modelCode, Contract contract, Decimal pos, double avgCost) {
	System.out.println(EWrapperMsgGenerator.positionMulti(reqId, account, modelCode, contract, pos, avgCost));
}

 

void TestCppClient::positionMulti( int reqId, const std::string& account,const std::string& modelCode, const Contract& contract, Decimal pos, double avgCost) {
    printf("Position Multi. Request: %d, Account: %s, ModelCode: %s, Symbol: %s, SecType: %s, Currency: %s, Position: %s, Avg Cost: %sn", reqId, account.c_str(), modelCode.c_str(), contract.symbol.c_str(), contract.secType.c_str(), contract.currency.c_str(), decimalStringToDisplay(pos).c_str(), Utils::doubleMaxString(avgCost).c_str());
}

 

public virtual void positionMulti(int reqId, string account, string modelCode, Contract contract, decimal pos, double avgCost)
{
	Console.WriteLine("Position Multi. Request: " + reqId + ", Account: " + account + ", ModelCode: " + modelCode + ", contract: " + contract + ", Position: " + Util.DecimalMaxString(pos) + ", Avg cost: " + Util.DoubleMaxString(avgCost) + "n");
}

 

Public Sub positionMulti(requestId As Integer, account As String, modelCode As String, contract As Contract, pos As Decimal, avgCost As Double) Implements IBApi.EWrapper.positionMulti
	Console.WriteLine("PositionMulti. Id: " & requestId & ", Account: " & account & ", ModelCode: " & modelCode & ", Contract: " & contract.Symbol & ", pos: " & Util.DecimalMaxString(pos) & ", avgCost: " & Util.DoubleMaxString(avgCost))
End Sub

 

EWrapper.positionMultiEnd(

requestId: int. The id of request
)

Indicates all the positions have been transmitted.

def positionMultiEnd(self, reqId: int):
	print("PositionMultiEnd. RequestId:", reqId)

 

@Override
public void positionMultiEnd(int reqId) {
	System.out.println("Position Multi End: " + EWrapperMsgGenerator.positionMultiEnd(reqId));
}

 

void TestCppClient::positionMultiEnd( int reqId) {
    printf("Position Multi End. Request: %dn", reqId);
}

 

public virtual void positionMultiEnd(int reqId)
{
	Console.WriteLine("Position Multi End. Request: " + reqId + "n");
}

 

Public Sub positionMultiEnd(requestId As Integer) Implements IBApi.EWrapper.positionMultiEnd
	Console.WriteLine("PositionMultiEnd")
End Sub

 

Cancel Positions By Model

EClient.cancelPositionsMulti (

requestId: int. The identifier of the request to be canceled.

)

Cancels positions request for account and/or model.

self.cancelPositionsMulti(requestid)

 

client.cancelPositionsMulti(requestid);

 

m_pClient->cancelPositionsMulti(requestid);

 

client.cancelPositionsMulti(requestid);

 

client.cancelPositionsMulti(requestid)

 

Profit & Loss (PnL)

Requests can be made to receive real time updates about the daily P&L and unrealized P&L for an account, or for individual positions. Financial Advisors can also request P&L figures for ‘All’ subaccounts, or for a portfolio model. This is further extended to include realized P&L information at the account or individual position level.

The P&L API functions demonstrated below return the data which is displayed in the TWS Portfolio Window in current versions of TWS. As such, the P&L values are calculated based on the reset schedule specified in TWS Global Configuration (by default an instrument-specific reset schedule) and this setting affects values sent to the associated API functions as well. Also in TWS, P&L data from virtual forex positions will be included in the account P&L if and only if the Virtual Fx section of the Account Window is expanded.

See Account Updates for alternative PnL data.

Request P&L for individual positions

Subscribe using the IBApi::EClient::reqPnLSingle function Cannot be used with IBroker accounts configured for on-demand lookup with account = ‘All’. Currently updates are returned to IBApi.EWrapper.pnlSingle approximately once per second*.

  • If a P&L subscription request is made for an invalid conId or contract not in the account, there will not be a response.
  • As elsewhere in the API, a max double value will indicate an ‘unset’ value. This corresponds to an empty cell in TWS.
  • Introducing broker accounts without a large number of subaccounts (<50) can receive aggregate data by specifying the account as “All”.
  • *Cannot be used with IBroker accounts configured for on-demand lookup with account = ‘All’

*subject to change in the future.

EClient.reqPnLSingle (

reqId: int. Request identifier for to track the data.

account: String. Account in which position exists

modelCode: String. Model in which position exists

conId: int. Contract ID (conId) of contract to receive daily PnL updates for. Note: does not return message if invalid conId is entered

)

Requests real time updates for daily PnL of individual positions.

self.reqPnLSingle(requestId, "U1234567", "", 265598)

 

Code example:

from ibapi.client import *
from ibapi.wrapper import *
import time

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

    def pnlSingle(self, reqId: int, pos: Decimal, dailyPnL: float, unrealizedPnL: float, realizedPnL: float, value: float):
        print("Daily PnL Single. ReqId:", reqId, "Position:", pos, "DailyPnL:", dailyPnL, "UnrealizedPnL:", unrealizedPnL, "RealizedPnL:", realizedPnL, "Value:", value)
    
app = TradeApp()      
app.connect("127.0.0.1", 7496, clientId=1)

time.sleep(1)
app.reqPnLSingle(101, "U123456", "", 8314) #IBM conId: 8314

app.run()

 

client.reqPnLSingle(requestId, "U1234567", "", 265598);

 

m_pClient->reqPnLSingle(requestId, "U1234567", "", 265598);

 

client.reqPnLSingle(requestId, "U1234567", "", 265598);

 

client.reqPnLSingle(requestId, "U1234567", "", 265598)

 

Receive P&L for individual positions

EWrapper.pnlSingle (

reqId: int. Request identifier used for tracking.

pos: decimal. Current size of the position

dailyPnL: double. DailyPnL for the position

unrealizedPnL: double. Total unrealized PnL for the position (since inception) updating in real time

realizedPnL: double. Total realized PnL for the position (since inception) updating in real time

value: double. Current market value of the position.
)

Receives real time updates for single position daily PnL values

def pnlSingle(self, reqId: int, pos: Decimal, dailyPnL: float, unrealizedPnL: float, realizedPnL: float, value: float):
  print("Daily PnL Single. ReqId:", reqId, "Position:", pos, "DailyPnL:", dailyPnL, "UnrealizedPnL:", unrealizedPnL, "RealizedPnL:", realizedPnL, "Value:", value)

 

@Override
public void pnlSingle(int reqId, Decimal pos, double dailyPnL, double unrealizedPnL, double realizedPnL, double value) {
  System.out.println(EWrapperMsgGenerator.pnlSingle(reqId, pos, dailyPnL, unrealizedPnL, realizedPnL, value));                
}

 

void TestCppClient::pnlSingle(int reqId, Decimal pos, double dailyPnL, double unrealizedPnL, double realizedPnL, double value) {
    printf("PnL Single. ReqId: %d, pos: %s, daily PnL: %s, unrealized PnL: %s, realized PnL: %s, value: %sn", reqId, decimalStringToDisplay(pos).c_str(), Utils::doubleMaxString(dailyPnL).c_str(), Utils::doubleMaxString(unrealizedPnL).c_str(), Utils::doubleMaxString(realizedPnL).c_str(), Utils::doubleMaxString(value).c_str());
}

 

public void pnlSingle(int reqId, decimal pos, double dailyPnL, double unrealizedPnL, double realizedPnL, double value)
{
	Console.WriteLine("PnL Single. Request Id: {0}, Pos {1}, Daily PnL {2}, Unrealized PnL {3}, Realized PnL: {4}, Value: {5}", reqId, Util.DecimalMaxString(pos), Util.DoubleMaxString(dailyPnL), Util.DoubleMaxString(unrealizedPnL),
		Util.DoubleMaxString(realizedPnL), Util.DoubleMaxString(value));
}

 

Public Sub pnlSingle(reqId As Integer, pos As Decimal, dailyPnL As Double, unrealizedPnL As Double, realizedPnL As Double, value As Double) Implements EWrapper.pnlSingle
	Console.WriteLine("PnL Single. Request Id: {0}, pos: {1}, daily PnL: {2}, unrealized PnL: {3}, realized PnL: {4}, value: {5}", reqId, Util.DecimalMaxString(pos), Util.DoubleMaxString(dailyPnL), Util.DoubleMaxString(unrealizedPnL), Util.DoubleMaxString(realizedPnL), Util.DoubleMaxString(value))
End Sub

 

Cancel P&L request for individual positions

EClient.cancelPnLSingle (

reqId: int. Request identifier to cancel the P&L subscription for.
)

Cancels real time subscription for a positions daily PnL information.

self.cancelPnLSingle(requestId);

 

client.cancelPnLSingle(reqId);

 

m_pClient->cancelPnLSingle(reqId);

 

client.cancelPnLSingle(reqId);

 

client.cancelPnLSingle(reqId);

 

Request P&L for accounts

Subscribe using the IBApi::EClient::reqPnL function. Updates are sent to IBApi.EWrapper.pnl.

  • Introducing broker accounts with less than 50 subaccounts can receive aggregate PnL for all subaccounts by specifying ‘All’ as the account code.
  • With requests for advisor accounts with many subaccounts and/or positions can take several seconds for aggregated P&L to be computed and returned.
  • For account P&L data the TWS setting “Prepare portfolio PnL data when downloading positions” must be checked.

EClient.reqPnL (

reqId: int. Request ID to track the data.

account: String. Account for which to receive PnL updates

modelCode: String. Specify to request PnL updates for a specific model.
)

Creates subscription for real time daily PnL and unrealized PnL updates.

self.reqPnL(reqId, "U1234567", "")

 

Code example:

from ibapi.client import *
from ibapi.wrapper import *
import time

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

    def pnl(self, reqId: int, dailyPnL: float, unrealizedPnL: float, realizedPnL: float):
        print("Daily PnL. ReqId:", reqId, "DailyPnL:", dailyPnL, "UnrealizedPnL:", unrealizedPnL, "RealizedPnL:", realizedPnL)
    
app = TradeApp()      
app.connect("127.0.0.1", 7496, clientId=1)

time.sleep(1)
app.reqPnL(102, "U123456", "")

app.run()

 

client.reqPnL(reqId, "U1234567", "");

 

m_pClient->reqPnL(reqId, "U1234567", "");

 

client.reqPnL(reqId, "U1234567", "");

 

client.reqPnL(reqId, "U1234567", "")

 

Receive P&L for accounts

EWrapper.pnl (

reqId: int. Request identifier for tracking data.

dailyPnL: double. DailyPnL updates for the account in real time

unrealizedPnL: double. Total Unrealized PnL updates for the account in real time

realizedPnL: double. Total Realized PnL updates for the account in real time

)

def pnl(self, reqId: int, dailyPnL: float, unrealizedPnL: float, realizedPnL: float):
  print("Daily PnL. ReqId:", reqId, "DailyPnL:", dailyPnL, "UnrealizedPnL:", unrealizedPnL, "RealizedPnL:", realizedPnL)

 

@Override
public void pnl(int reqId, double dailyPnL, double unrealizedPnL, double realizedPnL) {
	System.out.println(EWrapperMsgGenerator.pnl(reqId, dailyPnL, unrealizedPnL, realizedPnL));
}

 

void TestCppClient::pnl(int reqId, double dailyPnL, double unrealizedPnL, double realizedPnL) {
    printf("PnL. ReqId: %d, daily PnL: %s, unrealized PnL: %s, realized PnL: %sn", reqId, Utils::doubleMaxString(dailyPnL).c_str(), Utils::doubleMaxString(unrealizedPnL).c_str(), 
        Utils::doubleMaxString(realizedPnL).c_str());
}

 

public void pnl(int reqId, double dailyPnL, double unrealizedPnL, double realizedPnL)
{
	Console.WriteLine("PnL. Request Id: {0}, Daily PnL: {1}, Unrealized PnL: {2}, Realized PnL: {3}", reqId, Util.DoubleMaxString(dailyPnL), Util.DoubleMaxString(unrealizedPnL), Util.DoubleMaxString(realizedPnL));
}

 

 Public Sub pnl(reqId As Integer, dailyPnL As Double, unrealizedPnL As Double, realizedPnL As Double) Implements EWrapper.pnl
	Console.WriteLine("PnL. Request Id: {0}, daily PnL: {1}, unrealized PnL: {2}, realized PnL: {3}", reqId, Util.DoubleMaxString(dailyPnL), Util.DoubleMaxString(unrealizedPnL), Util.DoubleMaxString(realizedPnL))
End Sub

 

Cancel P&L subscription requests for accounts

EClient.cancelPnL (

reqId: int. Request identifier for tracking data.
)

Cancels subscription for real time updated daily PnL params reqId

self.cancelPnL(reqId)

 

client.cancelPnL(reqId);

 

m_pClient->cancelPnL(7001);

 

client.cancelPnL(reqId);

 

client.cancelPnL(reqId)

 

White Branding User Info

This function will return White Branding ID associated with the user.

Please note, that nothing will be returned if requesting username is not associated with any White Branding entity.

Requesting White Branding Info

EClient.reqUserInfo(

reqId: int. Request ID

)

self.reqUserInfo(reqId)

 

client.reqUserInfo(reqId);

 

m_pClient->reqUserInfo(0);

 

client.reqUserInfo(reqId);

 

client.reqUserInfo(reqId)

 

Receiving White Branding Info

EWrapper.userInfo (

reqId: int. Identifier for the given request.

whiteBrandingId: String. Identifier for the white branded entity.
)

def userInfo(self, reqId: int, whiteBrandingId: str):
	print("UserInfo.", "ReqId:", reqId, "WhiteBrandingId:", whiteBrandingId)

 

@Override
public void userInfo(int reqId, String whiteBrandingId) {
	System.out.println(EWrapperMsgGenerator.userInfo(reqId, whiteBrandingId));
}

 

void TestCppClient::userInfo(int reqId, const std::string& whiteBrandingId) {
    printf("User Info. ReqId: %d, WhiteBrandingId: %sn", reqId, whiteBrandingId.c_str());
}

 

public void userInfo(int reqId, string whiteBrandingId)
{
	Console.WriteLine($"User Info. ReqId: {reqId}, WhiteBrandingId: {whiteBrandingId}");
}

 

Public Sub userInfo(reqId As Integer, whiteBrandingId As String) Implements EWrapper.userInfo
  Console.WriteLine($"User Info. ReqId: {reqId}, WhiteBrandingId: {whiteBrandingId}")
End Sub

 

Bulletins

From time to time, IB sends out important News Bulletins, which can be accessed via the TWS API through the EClient.reqNewsBulletins. Bulletins are delivered via IBApi.EWrapper.updateNewsBulletin whenever there is a new bulletin. In order to stop receiving bulletins you need to cancel the subscription.

Request IB Bulletins

EClient.reqNewsBulletins (

allMessages: bool. If set to true, will return all the existing bulletins for the current day, set to false to receive only the new bulletins.
)

Subscribes to IB’s News Bulletins.

self.reqNewsBulletins(True)

 

client.reqNewsBulletins(true);

 

m_pClient->reqNewsBulletins(true);

 

client.reqNewsBulletins(true);

 

client.reqNewsBulletins(True)

 

Receive IB Bulletins

EWrapper.updateNewsBulletin (

msgId: int. The bulletin’s identifier.

msgType: int. 1: Regular news bulletin; 2: Exchange no longer available for trading; 3: Exchange is available for trading.

message: String. The news bulletin context.

origExchange: String. The exchange where the message comes from.
)

Provides IB’s bulletins

def updateNewsBulletin(self, msgId: int, msgType: int, newsMessage: str, originExch: str):
  print("News Bulletins. MsgId:", msgId, "Type:", msgType, "Message:", newsMessage, "Exchange of Origin: ", originExch)

 

@Override
public void updateNewsBulletin(int msgId, int msgType, String message, String origExchange) {
	System.out.println("News Bulletin: " + EWrapperMsgGenerator.updateNewsBulletin( msgId, msgType, message, origExchange));
}

 

void TestCppClient::updateNewsBulletin(int msgId, int msgType, const std::string& newsMessage, const std::string& originExch) {
    printf( "News Bulletins. %d - Type: %d, Message: %s, Exchange of Origin: %sn", msgId, msgType, newsMessage.c_str(), originExch.c_str());
}

 

public virtual void updateNewsBulletin(int msgId, int msgType, String message, String origExchange)
{
	Console.WriteLine("News Bulletins. "+msgId+" - Type: "+msgType+", Message: "+message+", Exchange of Origin: "+origExchange+"n");
}

 

Public Sub updateNewsBulletin(msgId As Integer, msgType As Integer, message As String, origExchange As String) Implements IBApi.EWrapper.updateNewsBulletin
	Console.WriteLine("News Bulletins. " & msgId & " - Type: " & msgType & ", Message: " & message & ", Exchange of Origin: " & origExchange)
End Sub

 

Cancel Bulletin Request

EClient.cancelNewsBulletin ()

Cancels IB’s news bulletin subscription.

self.cancelNewsBulletins()

 

client.cancelNewsBulletins();

 

m_pClient->cancelNewsBulletins();

 

client.cancelNewsBulletin();

 

client.cancelNewsBulletin()

 

Contracts (Financial Instruments)

An IBApi.Contract object represents trading instruments such as a stocks, futures or options. Every time a new request that requires a contract (i.e. market data, order placing, etc.) is sent to TWS, the platform will try to match the provided contract object with a single candidate.

The Contract Object

The Contract object is an object used throughout the TWS API to define the target of your requests. Contract objects will be used for market data, portfolios, orders, executions, and even some news request. This is the staple structure used for all of the TWS API.

In all contracts, the minimum viable structure requires at least a conId and exchange, or a symbol, secType, exchange, primaryExchange, and currency. Derivatives will require additional fields, such as lastTradeDateOrExpiration, tradingClass, multiplier, strikes, and so on.

The values to the right represent the most common Contract values to pass for complete contracts. For a more comprehensive list of contract structures, please see the Contracts page.

Contract()

ConId: int. Identifier to specify an exact contract.

Symbol: String. Ticker symbol of the underlying instrument.

SecType: String. Security type of the traded instrument.

Exchange: String. Exchange for which data or trades should be routed.

PrimaryExchange: String. Primary listing exchange of the instrument.

Currency: String. Base currency the instrument is traded on.

LastTradeDateOrContractMonth: String. For derivatives, the expiration date of the contract.

Strike: double. For derivatives, the strike price of the instrument.

Right: String. For derivatives, the right (P/C) of the instrument.

TradingClass: String. For derivatives, the trading class of the instrument.
May be used to indicate between a monthly or a weekly contract.

Given additional structures for contracts are ever evolving, it is recommended to review the relevant Contract class in your programming language for a comprehensive review of what fields are available.

Contract Class Reference

Finding Contract Details in Trader Workstation

If there is more than one contract matching the same description, TWS will return an error notifying you there is an ambiguity. In these cases the TWS needs further information to narrow down the list of contracts matching the provided description to a single element.

The best way of finding a contract’s description is within the TWS itself. Within the TWS, you can easily check a contract’s description either by double clicking it or through the Contract Info -> Description menu, which you access by right-clicking a contract in TWS:

The description will then appear:

Note: you can see the extended contract details by choosing Contract Info -> Details. This option will open a web page showing all available information on the contract.

Whenever a contract description is provided via the TWS API, the TWS will try to match the given description to a single contract. This mechanism allows for great flexibility since it gives the possibility to define the same contract in multiple ways.

The simplest way to define a contract is by providing its symbol, security type, currency and exchange. The vast majority of stocks, CFDs, Indexes or FX pairs can be uniquely defined through these four attributes. More complex contracts such as options and futures require some extra information due to their nature. Below are several examples for different types of instruments.

Contract Details

Complete details about a contract in IB’s database can be retrieved using the function IBApi.EClient.reqContractDetails. This includes information about a contract’s conID, symbol, local symbol, currency, etc. which is returned in a IBApi.ContractDetails object. reqContractDetails takes as an argument a Contract object which may uniquely match one contract, and unlike other API functions it can also take a Contract object which matches multiple contracts in IB’s database. When there are multiple matches, they will each be returned individually to the function IBApi::EWrapper::contractDetails.

Request for Bond details will be returned to IBApi::EWrapper::bondContractDetails instead. Because of bond market data license restrictions, there are only a few available fields to be returned in a bond contract description, namely the minTick, exchange, and short name.

Note: Invoking reqContractDetails with a Contract object which has currency = USD will only return US contracts, even if there are non-US instruments which have the USD currency.

Another function of IBApi::EClient::reqContractDetails is to request the trading schedule of an instrument via the TradingHours and LiquidHours fields. The corresponding timeZoneId field will then indicate the time zone for the trading schedule of the instrument. TWS sends these timeZoneId strings to the API from the schedule responses as-is, and may not exactly match the time zones displayed in the TWS contract description.

Possible timeZoneId values are:

  • Europe/Riga
  • Australia/NSW
  • Europe/Warsaw
  • US/Pacific
  • Europe/Tallinn
  • Japan
  • US/Eastern
  • GB-Eire
  • Africa/Johannesburg
  • Israel
  • Europe/Vilnius
  • MET
  • Europe/Helsinki
  • US/Central
  • Europe/Budapest
  • Asia/Calcutta
  • Hongkong
  • Europe/Moscow
  • GMT

Request Contract Details

EClient.reqContractDetails (

reqId: int. Request identifier to track data.

contract: ContractDetails. the contract used as sample to query the available contracts.
Typically contains at least the Symbol, SecType, Exchange, and Currency.
)

Receives the full contract’s definitions This method will return all contracts matching the requested via EClientSocket::reqContractDetails. For example, one can obtain the whole option chain with it.

self.reqContractDetails(reqId, contract)
client.reqContractDetails(reqId, contract)

 

m_pClient->reqContractDetails(reqId, contract);

 

client.reqContractDetails(reqId, contract);

 

client.reqContractDetails(reqId, contract)

 

Receive Contract Details

EWrapper.contractDetails (

reqId: int. Request identifier to track data.

contract: ContractDetails. Contains the full contract object contents including all information about a specific traded instrument.
)

Receives the full contract’s definitions This method will return all contracts matching the requested via EClientSocket::reqContractDetails. For example, one can obtain the whole option chain with it.

def contractDetails(self, reqId: int, contractDetails: ContractDetails):
  print(reqId, contractDetails)

 

@Override
public void contractDetails(int reqId, ContractDetails contractDetails) {
	System.out.println(EWrapperMsgGenerator.contractDetails(reqId, contractDetails)); 
}

 

void TestCppClient::contractDetails( int reqId, const ContractDetails& contractDetails) {
    printf( "ContractDetails. ReqId: %dn", reqId);
    printContractDetailsMsg(contractDetails);
}

 

public virtual void contractDetails(int reqId, ContractDetails contractDetails)
{
	Console.WriteLine("ContractDetails. ReqId: " + reqId);
	printContractDetailsMsg(contractDetails);
}

 

Public Sub contractDetails(reqId As Integer, contractDetails As IBApi.ContractDetails) Implements IBApi.EWrapper.contractDetails
	Console.WriteLine("ContractDetails. ReqId: " & reqId)
	printContractDetailsMsg(contractDetails)
End Sub

 

EWrapper.contractDetailsEnd (

reqId: int. Request identifier to track data.
)

After all contracts matching the request were returned, this method will mark the end of their reception.

def contractDetailsEnd(self, reqId: int):
	print("ContractDetailsEnd. ReqId:", reqId)

 

@Override
public void contractDetailsEnd(int reqId) {
	System.out.println("Contract Details End: " + EWrapperMsgGenerator.contractDetailsEnd(reqId));
}

 

void TestCppClient::contractDetailsEnd( int reqId) {
    printf( "ContractDetailsEnd. %dn", reqId);
}

 

public virtual void contractDetailsEnd(int reqId)
{
	Console.WriteLine("ContractDetailsEnd. "+reqId+"n");
}

 

 Public Sub contractDetailsEnd(reqId As Integer) Implements IBApi.EWrapper.contractDetailsEnd
            Console.WriteLine("ContractDetailsEnd - ReqId [" & reqId & "]")
        End Sub

 

Receive Bond Details

EWrapper.bondContractDetails (

reqId: int. Request identifier to track data.

contract: ContractDetails. Contains the full contract object contents including all information about a specific traded instrument.
)

Delivers the Bond contract data after this has been requested via reqContractDetails.

def bondContractDetails(self, reqId: int, contractDetails: ContractDetails):
  printinstance(reqId, contractDetails)

 

@Override
public void bondContractDetails(int reqId, ContractDetails contractDetails) {
	System.out.println(EWrapperMsgGenerator.contractDetails(reqId, contractDetails)); 
}

 

void TestCppClient::bondContractDetails( int reqId, const ContractDetails& contractDetails) {
    printf( "BondContractDetails. ReqId: %dn", reqId);
    printContractDetailsMsg(contractDetails);
}

 

public virtual void bondContractDetails(int reqId, ContractDetails contractDetails)
{
	Console.WriteLine("BondContractDetails. ReqId: " + reqId);
	printContractDetailsMsg(contractDetails);
}

 

Public Sub bondContractDetails(reqId As Integer, contractDetails As IBApi.ContractDetails) Implements IBApi.EWrapper.contractDetails
	Console.WriteLine("BondContractDetails. ReqId: " & reqId)
	printContractDetailsMsg(contractDetails)
End Sub

 

Option Chains

The option chain for a given security can be returned using the function EClient.reqContractDetails. If an option contract is incompletely defined (for instance with the strike undefined) and used as an argument to EClient.reqContractDetails, a list of all matching option contracts will be returned.

One limitation of this technique is that the return of option chains will be throttled and take a longer time the more ambiguous the contract definition. The function EClient.reqSecDefOptParams was introduced that does not have the throttling limitation.

  • It is not recommended to use EClient.reqContractDetails to receive complete option chains on an underlying, e.g. all combinations of strikes/rights/expiries.
  • For very large option chains returned from EClient.reqContractDetails, unchecking the setting in TWS Global Configuration at API -> Settings -> “Expose entire trading schedule to the API” will decrease the amount of data returned per option and help to return the contract list more quickly.

EClient.reqSecDefOptParams returns a list of expiries and a list of strike prices. In some cases, it is possible there are combinations of strike and expiry that would not give a valid option contract.

Request Option Chains

EClient.reqSecDefOptParams (

reqId: int. The ID chosen for the request

underlyingSymbol: String. Contract symbol of the underlying.

futFopExchange: String. The exchange on which the returned options are trading. Can be set to the empty string “” for all exchanges.

underlyingSecType: String. The type of the underlying security, i.e. STK

underlyingConId: int. The contract ID of the underlying security.
)

Requests security definition option parameters for viewing a contract’s option chain.

self.reqSecDefOptParams(0, "IBM", "", "STK", 8314)

 

client.reqSecDefOptParams(0, "IBM", "", "STK", 8314);

 

m_pClient->reqSecDefOptParams(0, "IBM", "", "STK", 8314);

 

client.reqSecDefOptParams(0, "IBM", "", "STK", 8314);

 

client.reqSecDefOptParams(0, "IBM", "", "STK", 8314)

 

Receive Option Chains

EWrapper.securityDefinitionOptionParameter (

reqId: int. ID of the request initiating the callback.

underlyingConId: int. The conID of the underlying security.

tradingClass: String. The option trading class.

multiplier: String. The option multiplier.

exchange: String. Exchange for which the derivative is hosted.

expirations: HashSet. A list of the expiries for the options of this underlying on this exchange.

strikes: HashSet. A list of the possible strikes for options of this underlying on this exchange.
)

Returns the option chain for an underlying on an exchange specified in reqSecDefOptParams There will be multiple callbacks to securityDefinitionOptionParameter if multiple exchanges are specified in reqSecDefOptParams

def securityDefinitionOptionParameter(self, reqId: int, exchange: str, underlyingConId: int, tradingClass: str, multiplier: str, expirations: SetOfString, strikes: SetOfFloat):
  print("SecurityDefinitionOptionParameter.", "ReqId:", reqId, "Exchange:", exchange, "Underlying conId:", underlyingConId, "TradingClass:", tradingClass, "Multiplier:", multiplier, "Expirations:", expirations, "Strikes:", strikes)

 

@Override
public void securityDefinitionOptionalParameter(int reqId, String exchange, int underlyingConId, String tradingClass, String multiplier, Set expirations, Set strikes) {
	System.out.println("Security Definition Optional Parameter: " + EWrapperMsgGenerator.securityDefinitionOptionalParameter(reqId, exchange, underlyingConId, tradingClass, multiplier, expirations, strikes));
}

 

void TestCppClient::securityDefinitionOptionalParameter(int reqId, const std::string& exchange, int underlyingConId, const std::string& tradingClass,
                                                        const std::string& multiplier, const std::set& expirations, const std::set& strikes) {
    printf("Security Definition Optional Parameter. Request: %d, Trading Class: %s, Multiplier: %sn", reqId, tradingClass.c_str(), multiplier.c_str());
}

 

public void securityDefinitionOptionParameter(int reqId, string exchange, int underlyingConId, string tradingClass, string multiplier, HashSet expirations, HashSet strikes)
{
	Console.WriteLine("Security Definition Option Parameter. Reqest: {0}, Exchange: {1}, Undrelying contract id: {2}, Trading class: {3}, Multiplier: {4}, Expirations: {5}, Strikes: {6}", reqId, exchange, Util.IntMaxString(underlyingConId), tradingClass, multiplier, string.Join(", ", expirations), string.Join(", ", strikes));
}

 

Public Sub securityDefinitionOptionParameter(reqId As Integer, exchange As String, underlyingConId As Integer, tradingClass As String, multiplier As String, expirations As HashSet(Of String), strikes As HashSet(Of Double)) Implements EWrapper.securityDefinitionOptionParameter
            Console.WriteLine("securityDefinitionOptionParameter: " & reqId & " tradingClass: " & tradingClass & " multiplier: ")
End Sub

 

Request Stock Contract Search

EClient.reqMatchingSymbols ( 

reqId: int. Request identifier used to track data.

pattern: String. Either start of ticker symbol or (for larger strings) company name.
)

Requests matching stock symbols.

self.reqMatchingSymbols(reqId, "IBM")

 

client.reqMatchingSymbols(reqId, "IB");

 

m_pClient->reqMatchingSymbols(reqId, "IBM");

 

client.reqMatchingSymbols(reqId, "IBM");

 

client.reqMatchingSymbols(reqId, "IBM")

 

Receive Searched Stock Contract

EWrapper.symbolSamples (

reqID: int. Request identifier used to track data.

contractDescription: ContractDescription[]. Provide an array of contract objects matching the requested descriptoin.
)

Returns array of sample contract descriptions

def symbolSamples(self, reqId: int, contractDescriptions: ListOfContractDescription):
	print("Symbol Samples. Request Id: ", reqId)
	for contractDescription in contractDescriptions:
		derivSecTypes = ""
		for derivSecType in contractDescription.derivativeSecTypes:
			derivSecTypes += " "
			derivSecTypes += derivSecType
			print("Contract: conId:%s, symbol:%s, secType:%s primExchange:%s, "
				"currency:%s, derivativeSecTypes:%s, description:%s, issuerId:%s" % (
				contractDescription.contract.conId,
				contractDescription.contract.symbol,
				contractDescription.contract.secType,
				contractDescription.contract.primaryExchange,
				contractDescription.contract.currency, derivSecTypes,
				contractDescription.contract.description,
				contractDescription.contract.issuerId))

 

@Override
public void symbolSamples(int reqId, ContractDescription[] contractDescriptions) {
	System.out.println(EWrapperMsgGenerator.symbolSamples(reqId, contractDescriptions));
}

 

void TestCppClient::symbolSamples(int reqId, const std::vector &contractDescriptions) {
    printf("Symbol Samples (total=%lu) reqId: %dn", contractDescriptions.size(), reqId);
    for (unsigned int i = 0; i < contractDescriptions.size(); i++) {
        Contract contract = contractDescriptions[i].contract;
        std::vector derivativeSecTypes = contractDescriptions[i].derivativeSecTypes;
        printf("Contract (%u): conId: %ld, symbol: %s, secType: %s, primaryExchange: %s, currency: %s, ", i, contract.conId, contract.symbol.c_str(), contract.secType.c_str(), contract.primaryExchange.c_str(), contract.currency.c_str());
        printf("Derivative Sec-types (%lu):", derivativeSecTypes.size());
        for (unsigned int j = 0; j < derivativeSecTypes.size(); j++) {
            printf(" %s", derivativeSecTypes[j].c_str());
        }
        printf(", description: %s, issuerId: %s", contract.description.c_str(), contract.issuerId.c_str());
        printf("n");
    }
}

 

public void symbolSamples(int reqId, ContractDescription[] contractDescriptions) 
{
	string derivSecTypes;
	Console.WriteLine("Symbol Samples. Request Id: {0}", reqId);
	foreach (var contractDescription in contractDescriptions)
	{
		derivSecTypes = "";
		foreach (var derivSecType in contractDescription.DerivativeSecTypes)
		{
			derivSecTypes += derivSecType;
			derivSecTypes += " ";
		}
		Console.WriteLine("Contract: conId - {0}, symbol - {1}, secType - {2}, primExchange - {3}, currency - {4}, derivativeSecTypes - {5}, description - {6}, issuerId - {7}", 
			contractDescription.Contract.ConId, contractDescription.Contract.Symbol, contractDescription.Contract.SecType, 
			contractDescription.Contract.PrimaryExch, contractDescription.Contract.Currency, derivSecTypes, contractDescription.Contract.Description, contractDescription.Contract.IssuerId);
	}
}

 

Public Sub symbolSamples(reqId As Integer, contractDescriptions As ContractDescription()) Implements EWrapper.symbolSamples
	Dim derivSecTypes As String
	Console.WriteLine("Symbol Samples. Request Id: " & reqId)
	For Each contractDescription In contractDescriptions
		derivSecTypes = ""
		For Each derivSecType In contractDescription.DerivativeSecTypes
			derivSecTypes += derivSecType
			derivSecTypes += " "
		Next
		Console.WriteLine("Contract conId: " & contractDescription.Contract.ConId & ", symbol: " & contractDescription.Contract.Symbol &
						  ", secType: " & contractDescription.Contract.SecType & ", primExchange: " & contractDescription.Contract.PrimaryExch &
						  ", currency: " & contractDescription.Contract.Currency & ", derivativeSecTypes: " & derivSecTypes &
						  ", description: " & contractDescription.Contract.Description & ", issuerId: " & contractDescription.Contract.IssuerId)
	Next
End Sub

 

Error Handling

When a client application sends a message to TWS which requires a response which has an expected response (i.e. placing an order, requesting market data, subscribing to account updates, etc.), TWS will almost either always 1) respond with the relevant data or 2) send an error message to EWrapper.error().

  • Exceptions when no response can occur: Also, if a request is made prior to full establishment of connection (denoted by a returned 2104 or 2106 error code “Data Server is Ok”), there may not be a response from the request.

Error messages sent by the TWS are handled by the EWrapper.error() method. The EWrapper.error() event contains the originating request Id (or the orderId in case the error was raised when placing an order), a numeric error code and a brief description. It is important to keep in mind that this function is used for true error messages as well as notifications that do not mean anything is wrong.

API Error Messages when TWS is not set to the English Language

  • Currently on the Windows platform, error messages are sent using Latin1 encoding. If TWS is launched in a non-Western language, it is recommended to enable the setting at Global Configuration -> API -> Settings to “Show API error messages in English”.

Understanding Message Codes

The TWS uses the EWrapper.error method not only to deliver errors but also warnings or informative messages. This is done mostly for simplicity’s sake. Below is a table with all the messages which can be sent by the TWS/IB Gateway. All messages delivered by the TWS are usually accompanied by a brief but meaningful description pointing in the direction of the problem.

Remember that the TWS API simply connects to a running TWS/IB Gateway which most of times will be running on your local network if not in the same host as the client application. It is your responsibility to provide reliable connectivity between the TWS and your client application.

System Message Codes

The messages in the table below are not a consequence of any action performed by the client application. They are notifications about the connectivity status between the TWS and our servers. Your client application must pay special attention to them and handle the situation accordingly. You are very likely to lose connectivity to our servers at least once a day due to our daily server maintenance downtime as clearly detailed in our Current System Status page. Note that after the system reset, the TWS/IB Gateway will automatically reconnect to our servers and you can resume your operations normally.

 

Note:

  1. During a reset period, there may be an interruption in the ability to log in or manage orders. Existing orders (native types) will operate normally although execution reports and simulated orders will be delayed until the reset is complete. It is not recommended to operate during the scheduled reset times.
Code TWS message Additional notes
1100 Connectivity between IB and the TWS has been lost. Your TWS/IB Gateway has been disconnected from IB servers. This can occur because of an internet connectivity issue, a nightly reset of the IB servers, or a competing session.
1101 Connectivity between IB and TWS has been restored- data lost.* The TWS/IB Gateway has successfully reconnected to IB’s servers. Your market data requests have been lost and need to be re-submitted.
1102 Connectivity between IB and TWS has been restored- data maintained. The TWS/IB Gateway has successfully reconnected to IB’s servers. Your market data requests have been recovered and there is no need for you to re-submit them.
1300 TWS socket port has been reset and this connection is being dropped. Please reconnect on the new port – <port_num> The port number in the TWS/IBG settings has been changed during an active API connection.

Error Codes

Error codes in different ranges have different indications.

Code TWS message Additional notes
100 Max rate of messages per second has been exceeded. The client application has exceeded the rate of 50 messages/second. The TWS will likely disconnect the client application after this message.
101 Max number of tickers has been reached. “The current number of active market data subscriptions in TWS and the API altogether has been exceeded. This number is calculated based on a formula which is based on the equity, commissions, and quote booster packs in an account. Active lines can be checked in Tws using the Ctrl-Alt-= combination”
102 Duplicate ticker ID. A market data request used a ticker ID which is already in use by an active request.
103 Duplicate order ID. An order was placed with an order ID that is less than or equal to the order ID of a previous order from this client
104 Can’t modify a filled order. An attempt was made to modify an order which has already been filled by the system.
105 Order being modified does not match original order. An order was placed with an order ID of a currently open order but basic parameters differed (aside from quantity or price fields)
106 Can’t transmit order ID:
107 Cannot transmit incomplete order. Order is missing a required field.
109 Price is out of the range defined by the Percentage setting at order defaults frame. The order will not be transmitted. Price entered is outside the range of prices set in TWS or IB Gateway Order Precautionary Settings
110 The price does not conform to the minimum price variation for this contract. An entered price field has more digits of precision than is allowed for this particular contract. Minimum increment information can be found on the IB Contracts and Securities Search page.
111 The TIF (Tif type) and the order type are incompatible. The time in force specified cannot be used with this order type. Please refer to order tickets in TWS for allowable combinations.
113 The Tif option should be set to DAY for MOC and LOC orders. Market-on-close or Limit-on-close orders should be sent with time in force set to ‘DAY’
114 Relative orders are valid for stocks only. This error is deprecated.
115 “Relative orders for US stocks can only be submitted to SMART, SMART_ECN, INSTINET, or PRIMEX.” This error is deprecated.
116 The order cannot be transmitted to a dead exchange. Exchange field is invalid.
117 The block order size must be at least 50.
118 VWAP orders must be routed through the VWAP exchange.
119 Only VWAP orders may be placed on the VWAP exchange. “When an order is routed to the VWAP exchange, the type of the order must be defined as ‘VWAP’.”
120 It is too late to place a VWAP order for today. The cutoff has passed for the current day to place VWAP orders.
121 “Invalid BD flag for the order. Check “”Destination”” and “”BD”” flag.” This error is deprecated.
122 No request tag has been found for order:
123 No record is available for conid: The specified contract ID cannot be found. This error is deprecated.
124 No market rule is available for conid:
125 Buy price must be the same as the best asking price.
126 Sell price must be the same as the best bidding price.
129 VWAP orders must be submitted at least three minutes before the start time. The start time specified in the VWAP order is less than 3 minutes after when it is placed.
131 “The sweep-to-fill flag and display size are only valid for US stocks routed through SMART, and will be ignored.”
132 This order cannot be transmitted without a clearing account.
133 Submit new order failed.
134 Modify order failed.
135 Can’t find order with ID = An attempt was made to cancel an order not currently in the system.
136 This order cannot be cancelled. “An attempt was made to cancel an order than cannot be cancelled, for instance because”
137 VWAP orders can only be cancelled up to three minutes before the start time.
138 Could not parse ticker request:
139 Parsing error: Error in command syntax generated parsing error.
140 The size value should be an integer: The size field in the Order class has an invalid type.
141 The price value should be a double: A price field in the Order type has an invalid type.
142 Institutional customer account does not have account info
143 Requested ID is not an integer number. The IDs used in API requests must be integer values.
144 “Order size does not match total share allocation. To adjust the share allocation, right-click on the order and select “Modify > Share Allocation.â€?”
145 Error in validating entry fields – An error occurred with the syntax of a request field.
146 Invalid trigger method. The trigger method specified for a method such as stop or trail stop was not one of the allowable methods.
147 The conditional contract info is incomplete.
148 Conditional submission of orders is supported for Limit, Market, MidPrice, Relative and Snap order types only. Conditional cancelation of orders is supported for Limit and MidPrice order types only.
151 This order cannot be transmitted without a user name. In DDE the user name is a required field in the place order command.
152 “The “”hidden”” order attribute may not be specified for this order.” The order in question cannot be placed as a hidden order. See- https://www.interactivebrokers.com/en/index.php?f=596
153 EFPs can only be limit orders. This error is deprecated.
154 Orders cannot be transmitted for a halted security. A security was halted for trading when an order was placed.
155 A sizeOp order must have a user name and account. This error is deprecated.
156 A SizeOp order must go to IBSX This error is deprecated.
157 An order can be EITHER Iceberg or Discretionary. Please remove either the Discretionary amount or the Display size. In the Order class extended attributes the fields ‘Iceberg’ and ‘Discretionary’ cannot
158 You must specify an offset amount or a percent offset value. TRAIL and TRAIL STOP orders must have an absolute offset amount or offset percentage specified.
159 The percent offset value must be between 0% and 100%. A percent offset value was specified outside the allowable range of 0% and 100%.
160 The size value cannot be zero. The size of an order must be a positive quantity.
161 Cancel attempted when order is not in a cancellable state. Order permId = An attempt was made to cancel an order not active at the time.
162 Historical market data Service error message.
163 The price specified would violate the percentage constraint specified in the default order settings. The order price entered is outside the allowable range specified in the Order Precautionary Settings of TWS or IB Gateway
164 There is no market data to check price percent violations. No market data is available for the specified contract to determine whether the specified price is outside the price percent precautionary order setting.
165 Historical market Data Service query message. “There was an issue with a historical data request, such is no such data in IB’s database. Note this message is not specific to the API.”
166 HMDS Expired Contract Violation. Historical data is not available for the specified expired contract.
167 VWAP order time must be in the future. The start time of a VWAP order has already passed.
168 Discretionary amount does not conform to the minimum price variation for this contract. The discretionary field is specified with a number of degrees of precision higher than what is allowed for a specified contract.
200 No security definition has been found for the request. “The specified contract does not match any in IB’s database, usually because of an incorrect or missing parameter.”
200 The contract description specified for is ambiguous Ambiguity may occur when the contract definition provided is not unique.
200 “For some stocks that has the same Symbol, Currency and Exchange, you need to specify the IBApi.Contract.PrimaryExch attribute to avoid ambiguity. Please refer to a sample stock contract here.”
200 “For futures that has multiple multipliers for the same expiration, You need to specify the IBApi.Contract.Multiplier attribute to avoid ambiguity. Please refer to a sample futures contract here.”
201 Order rejected – Reason: An attempted order was rejected by the IB servers. See Order Placement Considerations for additional information/considerations for these errors.
202 Order cancelled – Reason: An active order on the IB server was cancelled. See Order Placement Considerations for additional information/considerations for these errors.
203 The security is not available or allowed for this account. The specified security has a trading restriction with a specific account.
300 Can’t find EId with ticker Id: An attempt was made to cancel market data for a ticker ID that was not associated with a current subscription. With the DDE API this occurs by clearing the spreadsheet cell.
301 Invalid ticker action:
302 Error parsing stop ticker string:
303 Invalid action: An action field was specified that is not available for the account. For most accounts this is only BUY or SELL. Some institutional accounts also have the options SSHORT or SLONG available.
304 Invalid account value action:
305 “Request parsing error, the request has been ignored.” The syntax of a DDE request is invalid.
306 Error processing DDE request: An issue with a DDE request prevented it from processing.
307 Invalid request topic: The ‘topic’ field in a DDE request is invalid.
308 Unable to create the ‘API’ page in TWS as the maximum number of pages already exists. “An order placed from the API will automatically open a new page in classic TWS, however there are already the maximum number of pages open.”
309 “Max number (3) of market depth requests has been reached. Note: TWS currently limits users to a maximum of 3 distinct market depth requests. This same restriction applies to API clients, however API clients may make multiple market depth requests for the same security.”
310 Can’t find the subscribed market depth with tickerId: An attempt was made to cancel market depth for a ticker not currently active.
311 The origin is invalid. The origin field specified in the Order class is invalid.
312 The combo details are invalid. Combination contract specified has invalid parameters.
313 The combo details for leg ” are invalid. A combo leg was not defined correctly.
314 Security type ‘BAG’ requires combo leg details. When specifying security type as ‘BAG’ make sure to also add combo legs with details.
315 Stock combo legs are restricted to SMART order routing. Make sure to specify ‘SMART’ as an exchange when using stock combo contracts.
316 Market depth data has been HALTED. Please re-subscribe. You need to re-subscribe to start receiving market depth data again.
317 Market depth data has been RESET. Please empty deep book contents before applying any new entries.
319 Invalid log level Make sure that you are setting a log level to a value in range of 1 to 5.
320 Server error when reading an API client request.
321 Server error when validating an API client request.
322 Server error when processing an API client request.
323 Server error: cause – s
324 Server error when reading a DDE client request (missing information). Make sure that you have specified all the needed information for your request.
325 Discretionary orders are not supported for this combination of exchange and order type. Make sure that you are specifying a valid combination of exchange and order type for the discretionary order.
326 Unable to connect as the client id is already in use. Retry with a unique client id. Another client application is already connected with the specified client id.
327 Only API connections with clientId set to 0 can set the auto bind TWS orders property.
328 Trailing stop orders can be attached to limit or stop-limit orders only. Indicates attempt to attach trail stop to order which was not a limit or stop-limit.
329 Order modify failed. Cannot change to the new order type. You are not allowed to modify initial order type to the specific order type you are using.
330 Only FA or STL customers can request managed accounts list. Make sure that your account type is either FA or STL.
331 Internal error. FA or STL does not have any managed accounts. You do not have any managed accounts.
332 The account codes for the order profile are invalid. You need to check that the account codes you specified for your request are valid.
333 Invalid share allocation syntax.
334 Invalid Good Till Date order Check you order settings.
335 Invalid delta: The delta must be between 0 and 100.
336 “The time or time zone is invalid. The correct format is hh:mm:ss xxx where xxx is an optionally specified time-zone. E.g.: 15:59:00 EST Note that there is a space between the time and the time zone. If no time zone is specified, local time is assumed.”
337 “The date, time, or time-zone entered is invalid. The correct format is yyyymmdd hh:mm:ss xxx where yyyymmdd and xxx are optional. E.g.: 20031126 15:59:00 ESTNote that there is a space between the date and time, and between the time and time-zone.”
338 Good After Time orders are currently disabled on this exchange.
339 Futures spread are no longer supported. Please use combos instead.
340 Invalid improvement amount for box auction strategy.
341 “Invalid delta. Valid values are from 1 to 100. You can set the delta from the “”Pegged to Stock”” section of the Order Ticket Panel, or by selecting Page/Layout from the main menu and adding the Delta column.”
342 Pegged order is not supported on this exchange. You can review all order types and supported exchanges on the Order Types and Algos page.
343 “The date, time, or time-zone entered is invalid. The correct format is yyyymmdd hh:mm:ss xxx”
344 The account logged into is not a financial advisor account. You are trying to perform an action that is only available for the financial advisor account.
345 Generic combo is not supported for FA advisor account.
346 Not an institutional account or an away clearing account.
347 Short sale slot value must be 1 (broker holds shares) or 2 (delivered from elsewhere). Make sure that your slot value is either 1 or 2.
348 Order not a short sale – type must be SSHORT to specify short sale slot. Make sure that the action you specified is ‘SSHORT’.
349 “Generic combo does not support “”Good After”” attribute.”
350 Minimum quantity is not supported for best combo order.
351 “The “”Regular Trading Hours only”” flag is not valid for this order.”
352 Short sale slot value of 2 (delivered from elsewhere) requires location. You need to specify designatedLocation for your order.
353 Short sale slot value of 1 requires no location be specified. You do not need to specify designatedLocation for your order.
354 Not subscribed to requested market data. You do not have live market data available in your account for the specified instruments. For further details please refer to Streaming Market Data.
355 Order size does not conform to market rule. Check order size parameters for the specified contract from the TWS Contract Details.
356 Smart-combo order does not support OCA group. Remove OCA group from your order.
357 Your client version is out of date.
358 Smart combo child order not supported.
359 Combo order only supports reduce on fill without block(OCA).
360 No whatif check support for smart combo order. Pre-trade commissions and margin information is not available for this type of order.
361 Invalid trigger price.
362 Invalid adjusted stop price.
363 Invalid adjusted stop limit price.
364 Invalid adjusted trailing amount.
365 No scanner subscription found for ticker id: Scanner market data subscription request with this ticker id has either been cancelled or is not found.
366 No historical data query found for ticker id: Historical market data request with this ticker id has either been cancelled or is not found.
367 Volatility type if set must be 1 or 2 for VOL orders. Do not set it for other order types.
368 Reference Price Type must be 1 or 2 for dynamic volatility management. Do not set it for non-VOL orders.
369 Volatility orders are only valid for US options. Make sure that you are placing an order for US OPT contract.
370 “Dynamic Volatility orders must be SMART routed, or trade on a Price Improvement Exchange.”
371 VOL order requires positive floating point value for volatility. Do not set it for other order types.
372 Cannot set dynamic VOL attribute on non-VOL order. Make sure that your order type is ‘VOL’.
373 Can only set stock range attribute on VOL or RELATIVE TO STOCK order.
374 “If both are set, the lower stock range attribute must be less than the upper stock range attribute.”
375 Stock range attributes cannot be negative.
376 The order is not eligible for continuous update. The option must trade on a cheap-to-reroute exchange.
377 Must specify valid delta hedge order aux. price.
378 Delta hedge order type requires delta hedge aux. price to be specified. Make sure your order has delta attribute.
379 Delta hedge order type requires that no delta hedge aux. price be specified. Make sure you do not specify aux. delta hedge price.
380 This order type is not allowed for delta hedge orders. “Limit, Market or Relative orders are supported.”
381 Your DDE.dll needs to be upgraded.
382 The price specified violates the number of ticks constraint specified in the default order settings.
383 The size specified violates the size constraint specified in the default order settings.
384 Invalid DDE array request.
385 Duplicate ticker ID for API scanner subscription. Make sure you are using a unique ticker ID for your new scanner subscription.
386 Duplicate ticker ID for API historical data query. Make sure you are using a unique ticker ID for your new historical market data query.
387 Unsupported order type for this exchange and security type. You can review all order types and supported exchanges on the Order Types and Algos page.
388 Order size is smaller than the minimum requirement. Check order size parameters for the specified contract from the TWS Contract Details.
389 Supplied routed order ID is not unique.
390 Supplied routed order ID is invalid.
391 The time or time-zone entered is invalid. The correct format is hh:mm:ss xxx
392 Invalid order: contract expired. You can not place an order for the expired contract.
393 Short sale slot may be specified for delta hedge orders only.
394 Invalid Process Time: must be integer number of milliseconds between 100 and 2000. Found:
395 “Due to system problems, orders with OCA groups are currently not being accepted.” Check TWS bulletins for more information.
396 “Due to system problems, application is currently accepting only Market and Limit orders for this contract.” Check TWS bulletins for more information.
397 “Due to system problems, application is currently accepting only Market and Limit orders for this contract.”
398 cannot be used as a condition trigger. Please make sure that you specify a valid condition
399 Order message error
400 Algo order error.
401 Length restriction.
402 Conditions are not allowed for this contract. Condition order type does not support for this contract
403 Invalid stop price. The Stop Price you specified for the order is invalid for the contract
404 Shares for this order are not immediately available for short sale. The order will be held while we attempt to locate the shares. You order is held by the TWS because you are trying to sell a contract but you do not have any long position and the market does not have short sale available. You order will be transmitted once there is short sale available on the market
405 The child order quantity should be equivalent to the parent order size. This error is deprecated.
406 The currency is not allowed. Please specify a valid currency
407 The symbol should contain valid non-unicode characters only. Please check your contract Symbol
408 Invalid scale order increment.
409 Invalid scale order. You must specify order component size. ScaleInitLevelSize specified is invalid
410 Invalid subsequent component size for scale order. ScaleSubsLevelSize specified is invalid
411 “The “”Outside Regular Trading Hours”” flag is not valid for this order.” Trading outside of regular trading hours is not available for this security
412 The contract is not available for trading.
413 What-if order should have the transmit flag set to true. You need to set IBApi.Order.Transmit to TRUE
414 Snapshot market data subscription is not applicable to generic ticks. You must leave Generic Tick List to be empty when requesting snapshot market data
415 Wait until previous RFQ finishes and try again.
416 RFQ is not applicable for the contract. Order ID:
417 Invalid initial component size for scale order. ScaleInitLevelSize specified is invalid
418 Invalid scale order profit offset. ScaleProfitOffset specified is invalid
419 Missing initial component size for scale order. You need to specify the ScaleInitLevelSize
420 Invalid real-time query. Information about pacing violations
421 Invalid route. This error is deprecated.
422 The account and clearing attributes on this order may not be changed.
423 Cross order RFQ has been expired. THI committed size is no longer available. Please open order dialog and verify liquidity allocation.
424 FA Order requires allocation to be specified. This error is deprecated.
425 FA Order requires per-account manual allocations because there is no common clearing instruction. Please use order dialog Adviser tab to enter the allocation. This error is deprecated.
426 None of the accounts have enough shares. You are not able to enter short position with Cash Account
427 Mutual Fund order requires monetary value to be specified. This error is deprecated.
428 Mutual Fund Sell order requires shares to be specified. This error is deprecated.
429 Delta neutral orders are only supported for combos (BAG security type).
430 “We are sorry, but fundamentals data for the security specified is not available.”
431 What to show field is missing or incorrect. This error is deprecated.
432 Commission must not be negative. This error is deprecated.
433 “Invalid “”Restore size after taking profit”” for multiple account allocation scale order.”
434 The order size cannot be zero.
435 You must specify an account. The function you invoked only works on a single account
436 “You must specify an allocation (either a single account, group, or profile).” “When you try to place an order with a Financial Advisor account, you must specify the order to be routed to either a single account, a group, or a profile.”
437 Order can have only one flag Outside RTH or Allow PreOpen. This error is deprecated.
438 The application is now locked. This error is deprecated.
439 Order processing failed. Algorithm definition not found. Please double check your specification for IBApi.Order.AlgoStrategy and IBApi.Order.AlgoParams
440 Order modify failed. Algorithm cannot be modified.
441 Algo attributes validation failed: Please double check your specification for IBApi.Order.AlgoStrategy and IBApi.Order.AlgoParams
442 Specified algorithm is not allowed for this order.
443 Order processing failed. Unknown algo attribute. Specification for IBApi.Order.AlgoParams is incorrect
444 Volatility Combo order is not yet acknowledged. Cannot submit changes at this time. The order is not in a state that is able to be modified
445 The RFQ for this order is no longer valid.
446 Missing scale order profit offset. ScaleProfitOffset is not properly specified
447 Missing scale price adjustment amount or interval. ScalePriceAdjustValue or ScalePriceAdjustInterval is not specified properly
448 Invalid scale price adjustment interval. ScalePriceAdjustInterval specified is invalid
449 Unexpected scale price adjustment amount or interval. ScalePriceAdjustValue or ScalePriceAdjustInterval specified is invalid
481 Order size reduced.
501 Already Connected. Your client application is already connected to the TWS.
502 “Couldn’t connect to TWS. Confirm that “”Enable ActiveX and Socket Clients”” is enabled and connection port is the same as “”Socket Port”” on the TWS “”Edit->Global Configuration…->API->Settings”” menu.” When you receive this error message it is either because you have not enabled API connectivity in the TWS and/or you are trying to connect on the wrong port. Refer to the TWS’ API Settings as explained in the error message. See also Connectivity
503 The TWS is out of date and must be upgraded. Indicates TWS or IBG is too old for use with the current API version. Can also be triggered if the TWS version does not support a specific API function.
504 Not connected. You are trying to perform a request without properly connecting and/or after connection to the TWS has been broken probably due to an unhandled exception within your client application.
505 Fatal Error: Unknown message id.
507 Bad Message Length (Java-only) “Indicates EOF exception was caught while reading from the socket. This can occur if there is an attempt to connect to TWS with a client ID that is already in use, or if TWS is locked, closes, or breaks the connection. It should be handled by the client application and used to indicate that the socket connection is not valid.”
585 FA Profile is not supported anymore, use FA Group instead “Indicates FaDataTypeEnum.PROFILES is deprecated. Use FaDataTypeEnum.GROUPS or 1 instead”
2100 New account data requested from TWS. API client has been unsubscribed from account data. “The TWS only allows one IBApi.EClient.reqAccountUpdates request at a time. If the client application attempts to subscribe to a second account without canceling the previous subscription, the new request will override the old one and the TWS will send this message notifying so.”
2101 Unable to subscribe to account as the following clients are subscribed to a different account. “If a client application invokes IBApi.EClient.reqAccountUpdates when there is an active subscription started by a different client, the TWS will reject the new subscription request with this message.”
2102 Unable to modify this order as it is still being processed. “If you attempt to modify an order before it gets processed by the system, the modification will be rejected. Wait until the order has been fully processed before modifying it. See Placing Orders for further details.”
2103 A market data farm is disconnected. “Indicates a connectivity problem to an IB server. Outside of the nightly IB server reset, this typically indicates an underlying ISP connectivity issue.”
2104 Market data farm connection is OK “A notification that connection to the market data server is ok. This is a notification and not a true error condition, and is expected on first establishing connection.”
2105 A historical data farm is disconnected. “Indicates a connectivity problem to an IB server. Outside of the nightly IB server reset, this typically indicates an underlying ISP connectivity issue.”
2106 A historical data farm is connected. “A notification that connection to the market data server is ok. This is a notification and not a true error condition, and is expected on first establishing connection.”
2107 A historical data farm connection has become inactive but should be available upon demand. “Whenever a connection to the historical data farm is not being used because there is not an active historical data request, the connection will go inactive in IB Gateway. This does not indicate any connectivity issue or problem with IB Gateway. As soon as a historical data request is made the status will change back to active.”
2108 A market data farm connection has become inactive but should be available upon demand. “Whenever a connection to our data farms is not needed, it will become dormant. There is nothing abnormal nor wrong with your client application nor with the TWS. You can safely ignore this message.”
2109 “Order Event Warning: Attribute “”Outside Regular Trading Hours”” is ignored based on the order type and destination. PlaceOrder is now processed.” Indicates the outsideRth flag was set for an order for which there is not a regular vs outside regular trading hour distinction
2110 Connectivity between TWS and server is broken. It will be restored automatically. Indicates a connectivity problem between TWS or IBG and the IB server. This will usually only occur during the IB nightly server reset; cases at other times indicate a problem in the local ISP connectivity.
2111 The Start and/or End Time for algo order BUY/SELL a contract was adjusted to use the next trading date. To modify this setting, use the Auto-adjust algo order date item on the Orders configuration page Please go to TWS Global Configuration – “Orders” – “Settings” to correct the configuration.
2119 Market data farm is connecting.
2130 Warning: products are trading on the basis of currency price with factor.
2137 Cross Side Warning “This warning message occurs in TWS version 955 and higher. It occurs when an order will change the position in an account from long to short or from short to long. To bypass the warning, a new feature has been added to IB Gateway 956 (or higher) and TWS 957 (or higher) so that once can go to Global Configuration > Messages and disable the “”Cross Side Warning””.”
2152 Market depth smart depth exchanges.
2158 Sec-def data farm connection is OK “A notification that connection to the Security definition data server is ok. This is a notification and not a true error condition, and is expected on first establishing connection.”
2168 Etrade Only Not Supported Warning The EtradeOnly IBApi.Order attribute is no longer supported. Error received with TWS versions 983+. Remove attribute to place order.
2169 Firm Quote Only Not Supported Warning The firmQuoteOnly IBApi.Order attribute is no longer supported. Error received with TWS versions 983+. Remove attribute to place order.
10000 Cross currency combo error.
10001 Cross currency vol error.
10002 Invalid non-guaranteed legs.
10003 IBSX not allowed.
10005 Read-only models.
10006 Missing parent order. The parent order ID specified cannot be found. In some cases this can occur with bracket orders if the child order is placed immediately after the parent order; a brief pause of 50 ms or less will be necessary before the child order is transmitted to TWS/IBG.
10007 Invalid hedge type.
10008 Invalid beta value.
10009 Invalid hedge ratio.
10010 Invalid delta hedge order.
10011 Currency is not supported for Smart combo.
10012 Invalid allocation percentage FaPercentage specified is not valid
10013 Smart routing API error (Smart routing opt-out required).
10014 PctChange limits. This error is deprecated
10015 Trading is not allowed in the API.
10016 Contract is not visible. This error is deprecated
10017 Contracts are not visible. This error is deprecated
10018 Orders use EV warning.
10019 Trades use EV warning.
10020 Display size should be smaller than order size./td> The display size should be smaller than the total quantity
10021 Invalid leg2 to Mkt Offset API. This error is deprecated
10022 Invalid Leg Prio API. This error is deprecated
10023 Invalid combo display size API. This error is deprecated
10024 Invalid don’t start next legin API. This error is deprecated
10025 Invalid leg2 to Mkt time1 API. This error is deprecated
10026 Invalid leg2 to Mkt time2 API. This error is deprecated
10027 Invalid combo routing tag API. This error is deprecated
10090 Part of requested market data is not subscribed. “Indicates that some tick types requested require additional market data subscriptions not held in the account. This commonly occurs for instance if a user has options subscriptions but not the underlying stock so the system cannot calculate the real time greek values (other default ticks will be returned). Or alternatively, if generic tick types are specified in a market data request without the associated subscriptions.”
10147 Order to be canceled was not found.
10148 “OrderId that needs to be cancelled can not be cancelled, state:” An attempt was made to cancel an order that had already been filled by the system.
10186 Requested market data is not subscribed. Delayed market data is not enabled See Market Data Types on how to enable delayed data.
10187 Failed to request historical ticks:No market data permissions
10189 Failed to request tick-by-tick data. Invalid Real-time Query Trading TWS session is connected from a different IP address. Or, No market data permissions
10197 No market data during competing session “Indicates that the user is logged into the paper account and live account simultaneously trying to request live market data using both the accounts. In such a scenario preference would be given to the live account, for more details please refer: https://ibkr.info/node/1719”
10225 “Bust event occurred, current subscription is deactivated. Please resubscribe real-time bars immediately”
10230 “You have unsaved FA changes. Please retry ‘request FA’ operation later, when ‘replace FA’ operation is complete” There are pending Financial Advisor configuration changes. See Financial Advisors
10231 The following Groups and/or Profiles contain invalid accounts: “If the account(s) inside Groups or Profiles is/are incorrect in xml-formatted configuration string of replaceFA request, then the error shows list of such Groups and/or Profiles.”
10233 Defaults were inherited from CASH preset during the creation of this order.
10234 The Decision Maker field is required and not set for this order (non-desktop).
10235 The Decision Maker field is required and not set for this order (ibbot).
10236 Child has to be AON if parent order is AON
10237 All or None ticket can route entire unfilled size only
10238 Some error occured during communication with Advisor Setup web-app
10239 This order will affect one or more accounts that are flagged because they do not fit the required risk score criteria prescribed by the group/profile/model allocation.
10240 You must enter a valid Price Cap.
10241 Order Quantity is expressed in monetary terms. Modification is not supported via API. Please use desktop version to revise this order.
10242 Fractional-sized order cannot be modified via API. Please use desktop version to revise this order.
10243 Fractional-sized order cannot be placed via API. Please use desktop version to place this order.
10244 Cash Quantity cannot be used for this order
10245 This financial instrument does not support fractional shares trading
10246 This order doesn’t support fractional shares trading
10247 Only IB SmartRouting supports fractional shares
10248 doesn’t have permission to trade fractional shares
10249 “=””””> order doesn’t support fractional shares”
10250 The size does not conform to the minimum variation of for this contract
10251 Fractional shares are not supported for allocation orders
10252 This non-close-position order doesn’t support fractional shares trading
10253 Clear Away orders are not supported for multi-leg combo with attached hedge.
10254 Invalid Order: bond expired
10268 The ‘EtradeOnly’ order attribute is not supported The EtradeOnly IBApi.Order attribute is no longer supported. Error received with TWS versions 983+
10269 The ‘firmQuoteOnly’ order attribute is not supported The firmQuoteOnly IBApi.Order attribute is no longer supported. Error received with TWS versions 983+
10270 The ‘nbboPriceCap’ order attribute is not supported The nbboPriceCap IBApi.Order attribute is no longer supported. Error received with TWS versions 983+
10276 News feed is not allowed The API client is not permissioned for receiving WSH news feed.
10277 News feed permissions required The API client is not subscribed to receive WSH news feed
10278 Duplicate WSH metadata request A request is already pending for the same API client.
10279 Failed request WSH metadata A general error occurred when processing the request.
10280 Failed cancel WSH metadata A general error occurred when processing the request.
10281 Duplicate WSH event data request A request is already pending for the same API client.
10282 WSH metadata not requested WSH metadata was not requested by first sending a reqWshMetaData request.
10283 Fail request WSH event data A general error occurred when processing the request.
10284 Fail cancel WSH event data A general error occurred when processing the request.
10285 Your API version does not support fractional sizing rules. Please upgrade to at least version 163
WinError 10038 An operation was attempted on something that is not a socket. This indicates socket connection was closed improperly. Typically for Python clients. You may refer : https://stackoverflow.com/questions/15210178/python-socket-programming-oserror-winerror-10038-an-operation-was-attempted-o

Receiving Error Messages

EWrapper.error(

reqId: int. The request identifier corresponding to the most recent reqId that maintained the error stream.
This does not pertain to the orderId from placeOrder, but whatever the most recent requestId is.

errorCode: int. The code identifying the error.

errorMsg: String. The error’s description.

advancedOrderRejectJson: String. Advanced order reject description in json format.
)

def error(self, reqId: TickerId, errorCode: int, errorString: str, advancedOrderRejectJson = ""):
  print("Error. Id:", reqId, "Code:", errorCode, "Msg:", errorString, "AdvancedOrderRejectJson:", advancedOrderRejectJson)

 

@Override
public void error(int id, int errorCode, String errorMsg, String advancedOrderRejectJson) {
  String str = "Error. Id: " + id + ", Code: " + errorCode + ", Msg: " + errorMsg;
  if (advancedOrderRejectJson != null) {
    str += (", AdvancedOrderRejectJson: " + advancedOrderRejectJson);
  }
  System.out.println(str + "n");
}

 

void TestCppClient::error(int id, int errorCode, const std::string& errorString, const std::string& advancedOrderRejectJson)
{
    printf("Error. Id: %d, Code: %d, Msg: %s, AdvancedOrderRejectJson: %sn", id, errorCode, errorString.c_str(), advancedOrderRejectJson.c_str());
}

 

public virtual void error(int id, int errorCode, string errorMsg, string advancedOrderRejectJson)
{
  Console.WriteLine("Error. Id: " + id + ", Code: " + errorCode + ", Msg: " + errorMsg + ", AdvancedOrderRejectJson: " + advancedOrderRejectJson + "n");
}

 

Public Sub [error](id As Integer, errorCode As Integer, errorMsg As String, advancedOrderRejectJson As String) Implements IBApi.EWrapper.error
            Console.WriteLine("Error - Id [" & id & "] ErrorCode [" & errorCode & "] ErrorMsg [" & errorMsg & "] AdvancedOrderRejectJson [" & advancedOrderRejectJson & "]")
End Sub

 

Financial Advisors

Financial Advisors are able to manage their allocation groups from the TWS API.

Note: Modifications made through the API will effect orders placed through TWS, the TWS API, Client Portal, and the Client Portal API.

Request FA Groups and Profiles

EClient.requestFA (

faDataType: int. The configuration to change. Set to 1 or 3 as defined in the table below.
)

Requests the FA configuration as set in TWS for the given FA Group or Profile.

self.requestFA(1)

 

client.requestFA(1);

 

m_pClient->requestFA(1);

 

client.requestFA(1);

 

client.requestFA(1)

 

 

requestFA FA Data Types

 

Type Code Type Name Description
1 Groups offer traders a way to create a group of accounts and apply a single allocation method to all accounts in the group.
3 Account Aliases let you easily identify the accounts by meaningful names rather than account numbers.

Receiving FA Groups and Profiles

EWrapper.receiveFA (

faDataType: int. Receive the faDataType value specified in the requestFA. See FA Data Types

faXmlData: String. The xml-formatted configuration.
)

Receives the Financial Advisor’s configuration available in the TWS.

def receiveFA(self, faData: FaDataType, cxml: str):
	print("Receiving FA: ", faData)
	open('log/fa.xml', 'w').write(cxml)

 

@Override
public void receiveFA(int faDataType, String xml) {
	System.out.println("Receiving FA: " + faDataType + " - " + xml);
}

 

void TestCppClient::receiveFA(faDataType pFaDataType, const std::string& cxml) {
    std::cout << "Receiving FA: " << (int)pFaDataType << std::endl << cxml << std::endl;
}

 

public virtual void receiveFA(int faDataType, string faXmlData)
{
	Console.WriteLine("Receing FA: "+faDataType+" - "+faXmlData);
}

 

Public Sub receiveFA(faDataType As Integer, faXmlData As String) Implements IBApi.EWrapper.receiveFA
  Console.WriteLine("Receing FA: " & faDataType & " - " & faXmlData)
End Sub

 

Replace FA Allocations

EClient.replaceFA (

reqId: int. Request identifier used to track data.

faDataType: int. The configuration structure to change. Set to 1 or 3 as defined above.

xml: String. XML configuration for allocation profiles or group. See Allocation Method XML Format for more details.
)

self.replaceFa(reqId, 1, xml)

 

client.replaceFa(reqId, 1, xml);

 

m_pClient->replaceFa(reqId, 1, xml);

 

client.replaceFa(reqId, 1, xml);

 

client.replaceFa(reqId, 1, xml)

 

 

replaceFA FA Data Types

 

replaceFA Type Code Type Name Description
1 Groups offer traders a way to create a group of accounts and apply a single allocation method to all accounts in the group.
2 Account Aliases let you easily identify the accounts by meaningful names rather than account numbers.

 

Note: 

In order to confirm that your FA changes were saved, you may wait for the EWrapper.replaceFAEnd callback, which provides the corresponding reqId. In addition, after saving changes, it is advised to verify the new FA setup via EClient.requestFA. If it is called before changes are fully saved, you may receive an error, such as error 10230. See Message Codes.

 

EClient.replaceFA only accepts faDataType 1 now. Otherwise, it may trigger error 585.

EWrapper.replaceFAEnd (

reqId: int. Request identifier used to track data.

text: String. the message text.

)

Marks the ending of the replaceFA reception.

 

def replaceFAEnd(self, reqId: int, text: str):
    super().replaceFAEnd(reqId, text)
    print("ReplaceFAEnd.", "ReqId:", reqId, "Text:", text)

 

@Override
public void replaceFAEnd(int reqId, String text) {
        System.out.println(EWrapperMsgGenerator.replaceFAEnd(reqId, text));
}
void TestCppClient::replaceFAEnd(int reqId, const std::string& text) {
    printf("Replace FA End. Request: %d, Text:%sn", reqId, text.c_str());
}

 

public virtual void replaceFAEnd(int reqId, string text)
{
    Console.WriteLine("Replace FA End. ReqId: " + reqId + ", Text: " + text + "n");
}

 

Public Sub replaceFAEnd(reqId As Integer, text As String) Implements IBApi.EWrapper.replaceFAEnd
    Console.WriteLine("replaceFAEnd. ReqId: {0}, Text: {1}", reqId, text)
End Sub

 

Allocation Methods and Groups

A number of methods for account allocations are available with Financial Advisor and IBroker account structures to specify how trades should be distributed across multiple accounts.

Allocation Groups can be created or modified in the Trader Workstation directly as described in TWS: Allocations and Transfers.

Alternatively, allocation groups can be created or modified through the EClient.replaceFA() method in the API.

Interactive Brokers supports two forms of allocation methods. Allocation methods that have calculations completed by Interactive Brokers, and a set of allocation methods calculated by the user and then specified.

IB-computed allocation methods

User-specified allocation methods

Formerly known as Allocation Profiles

Allocation Method XML Format

Allocation methods for financial advisor’s allocation groups are created using an XML format. The content below signifies the supported allocation groups and how to format them in their respective XML.

Available Equity

Requires you to specify an order size. This method distributes shares based on the amount of available equity in each account. The system calculates ratios based on the Available Equity in each account and allocates shares based on these ratios.

 

Example: You transmit an order for 700 shares of stock XYZ. The account group includes three accounts, A, B and C with available equity in the amounts of $25,000, $50,000 and $100,000 respectively. The system calculates a ratio of 1:2:4 and allocates 100 shares to Client A, 200 shares to Client B, and 400 shares to Client C.

<?xml version="1.0" encoding="UTF-8"?>
<ListOfGroups>
  <Group>
    <name>MyTestProfile2</name>
    <defaultMethod>AvailableEquity</defaultMethod>
    <ListOfAccts varName="list">
      <Account>
        <acct>DU6202167</acct>
      </Account>
      <Account>
        <acct>DU6202168</acct>
      </Account>
    </ListOfAccts>
  </Group>
</ListOfGroups>

 

Contracts Or Shares

This method allocates the absolute number of shares you enter to each account listed. If you use this method, the order size is calculated by adding together the number of shares allocated to each account in the profile.

 

Example:

Assume an order for 300 shares of stock ABC is transmitted.

In the example code shown in the right side, you can see that:

  1. Account A is set to receive 100.0 shares while Account B is set to receive 200.0 shares. Account A should receive 100 shares and Account B should receive 200 shares.
<?xml version="1.0" encoding="UTF-8"?>
<ListOfGroups>
  <Group>
  <name>MyTestProfile2</name>
  <defaultMethod>ContractsOrShares</defaultMethod>
  
  <ListOfAccts varName="list">
  <Account>
    <acct>DU6202167</acct>
    <amount>100.0</amount>
  </Account>
  <Account>
    <acct>DU6202168</acct>
    <amount>200.0</amount>
  </Account>
  </ListOfAccts>
  </Group>
</ListOfGroups>

 

Equal Quantity

Requires you to specify an order size. This method distributes shares equally between all accounts in the group.

 

Example: You transmit an order for 400 shares of stock ABC. If your Account Group includes four accounts, each account receives 100 shares. If your Account Group includes six accounts, each account receives 66 shares, and then 1 share is allocated to each account until all are distributed.

<?xml version="1.0" encoding="UTF-8"?>
<ListOfGroups>
  <Group>
    <name>MyTestProfile2</name>
    <defaultMethod>Equal</defaultMethod>
    <ListOfAccts varName="list">
      <Account>
        <acct>DU6202167</acct>
      </Account>
      <Account>
        <acct>DU6202168</acct>
      </Account>
    </ListOfAccts>
  </Group>
</ListOfGroups>

MonetaryAmount

The Monetary Amount method calculates the number of units to be allocated based on the monetary value assigned to each account.

<?xml version="1.0" encoding="UTF-8"?>
<ListOfGroups>
  <Group>
  <name>MyTestProfile2</name>
  <defaultMethod>MonetaryAmount</defaultMethod>
  
  <ListOfAccts varName="list">
  <Account>
    <acct>DU6202167</acct>
    <amount>1000.0</amount>
  </Account>
  <Account>
    <acct>DU6202168</acct>
    <amount>2000.0</amount>
  </Account>
  </ListOfAccts>
  </Group>
</ListOfGroups>

 

Net Liquidation Value

Requires you to specify an order size. This method distributes shares based on the net liquidation value of each account. The system calculates ratios based on the Net Liquidation value in each account and allocates shares based on these ratios.

 

Example: You transmit an order for 700 shares of stock XYZ. The account group includes three accounts, A, B and C with Net Liquidation values of $25,000, $50,000 and $100,000 respectively. The system calculates a ratio of 1:2:4 and allocates 100 shares to Client A, 200 shares to Client B, and 400 shares to Client C.

<?xml version="1.0" encoding="UTF-8"?>
<ListOfGroups>
  <Group>
    <name>MyTestProfile2</name>
    <defaultMethod>NetLiq</defaultMethod>
    <ListOfAccts varName="list">
      <Account>
        <acct>DU6202167</acct>
      </Account>
      <Account>
        <acct>DU6202168</acct>
      </Account>
    </ListOfAccts>
  </Group>
</ListOfGroups>

Percentages

This method will split the total number of shares in the order between listed accounts based on the percentages you indicate.

 

Example:

Assume an order for 300 shares of stock ABC is transmitted.

In the example code shown in the right side, you can see that:

  1. Account A is set to have 60.0 percentage while Account B is set to have 40.0 percentage. Account A should receive 180 shares and Account B should receive 120 shares.

 

While making modifications to allocations for profiles, the method uses an enumerated value. The number shown below demonstrates precisely what profile corresponds to which value.

BUY ORDER Positive Percent Negative Percent
Long Position Increases position No effect
Short Position No effect Decreases position
SELL ORDER Positive Percent Negative Percent
Long Position No effect Decreases position
Short Position Increases position No effect

 

Note:
Do not specify an order size. Since the quantity is calculated by the system, the order size is displayed in the Quantity field after the order is acknowledged. This method increases or decreases an already existing position. Positive percents will increase a position, negative percents will decrease a position. For exmaple, to fully close out a position, you just need to specify percentage to be -100.

 

<?xml version="1.0" encoding="UTF-8"?>
<ListOfGroups>
  <Group>
  <name>MyTestProfile2</name>
  <defaultMethod>Percent</defaultMethod>
  <ListOfAccts varName="list">
  <Account>
    <acct>DU6202167</acct>
    <amount>60.0</amount>
  </Account>
  <Account>
    <acct>DU6202168</acct>
    <amount>40.0</amount>
  </Account>
  </ListOfAccts>
  </Group>
</ListOfGroups>

 

Ratios

This method calculates the allocation of shares based on the ratios you enter.

Example:

Assume an order for 300 shares of stock ABC is transmitted.

In the example code shown in the right side, you can see that:

  1. A ratio of 1.0 and 2.0 is set to Account A and Account B. Account A should receive 100 shares and Account B should receive 200 shares.
<?xml version="1.0" encoding="UTF-8"?>
<ListOfGroups>
  <Group>
  <name>MyTestProfile2</name>
  <defaultMethod>Ratio</defaultMethod>
  
  <ListOfAccts varName="list">
  <Account>
    <acct>DU6202167</acct>
    <amount>1.0</amount>
  </Account>
  <Account>
    <acct>DU6202168</acct>
    <amount>2.0</amount>
  </Account>
  </ListOfAccts>
  </Group>
</ListOfGroups>

 

Model Portfolios and the API

Advisors can use Model Portfolios to easily invest some or all of a client’s assets into one or multiple custom-created portfolios, rather than tediously managing individual investments in single instruments.

More about Model Portfolios

The TWS API can access model portfolios in accounts where this functionality is available and a specific model has previously been setup in TWS. API functionality allows the client application to request model position update subscriptions, request model account update subscriptions, or place orders to a specific model.

Model Portfolio functionality not available in the TWS API:

  • Portfolio Model Creation
  • Portfolio Model Rebalancing
  • Portfolio Model Position or Cash Transfer

To request position updates from a specific model, the function IBApi::EClient::reqPositionsMulti can be used: Position Update Subscription by Model

To request model account updates, there is the function IBApi::EClient::reqAccountUpdatesMulti, see: Account Value Update Subscriptions by Model

To place an order to a model, the IBApi.Order.ModelCode field must be set accordingly, for example:

modelOrder = Order()
modelOrder.account = "DF12345"
modelOrder.modelCode = "Technology" # model for tech stocks first created in TWS
self.placeOrder(self.nextOrderId(), contract, modelOrder)

 

Order modelOrder = Order();
modelOrder.account("DF12345");  // master FA account number
modelOrder.modelCode("Technology"); // model for tech stocks first created in TWS
client.placeOrder(nextOrderId++, contract, modelOrder);

 

Order modelOrder = Order();
modelOrder.account = "DF12345";
modelOrder.modelCode = "Technology";
m_pClient->placeOrder(m_orderId++, contract, modelOrder);

 

Order modelOrder = Order();
modelOrder.Account = "DF12345";  // master FA account number
modelOrder.ModelCode = "Technology"; // model for tech stocks first created in TWS
client.placeOrder(nextOrderId++, contract, modelOrder);

 

Dim modelOrder As Order = Order()
modelOrder.Account = "DF12345" 'master FA account number
modelOrder.ModelCode = "Technology" 'model for tech stocks first created in TWS
client.placeOrder(increment(nextOrderId), contract, modelOrder)

 

Unification of Groups and Profiles

With TWS/IBGW build 983+, the API settings will have a new flag/checkbox, “Use Account Groups with Allocation Methods” (enabled by default for new users). If not enabled, groups and profiles would behave the same as before. If it is checked, group and profile functionality will be merged.

With TWS/IBGW Build 10.20+, this setting is now enabled by default, and moving forward into new versions, the two systems can be deemed as interchangeable for modifying allocation groups, placing orders, requesting account or portfolio summaries, or requesting multiple positions.

Order Placement

For advisors to place orders to their allocation groups users would simply declare their allocation group name in the order object. This would be done with the Order’s faGroup field. The example to the right references a standard market order placed to our allocation group, MyTestProfile.

order = Order()
order.action = "BUY"
order.orderType = "MKT"
order.totalQuantity = 50
order.faGroup = "MyTestProfile"

 

Order order = new Order();
order.action("BUY");
order.orderType("MKT");
order.totalQuantity(50);
order.faGroup("MyTestProfile");

 

Order order;
order.action = "BUY";
order.orderType = "MKT";
order.totalQuantity = 50;
order.faGroup = "MyTestProfile";

 

 

Order order = new Order();
order.Action = "BUY";
order.OrderType = "MKT";
order.TotalQuantity = 50;
order.FaGroup = "MyTestProfile";

 

Dim order As Order = New Order
order.Action = "BUY"
order.OrderType = "MKT"
order.TotalQuantity = 50
order.FaGroup = "MyTestProfile"

 

Market Data: Delayed

Delayed market data can only used with EClient.reqMktData and EClient.reqHistoricalData. This does not function for tick data.

The API can request Live, Frozen, Delayed and Delayed Frozen market data from Trader Workstation by switching market data type via the EClient.reqMarketDataType before making a market data request. A successful switch to a different (non-live) market data type for a particular market data request will be indicated by a callback to EWrapper.marketDataType with the ticker ID of the market data request which is returning a different type of data.

  • A EClient.reqMarketDataType callback of 1 will occur automatically after invoking reqMktData if the user has live data permissions for the instrument.
Market Data Type ID Description
Live 1 Live market data is streaming data relayed back in real time. Market data subscriptions are required to receive live market data.
Frozen 2 Frozen market data is the last data recorded at market close. In TWS, Frozen data is displayed in gray numbers. When you set the market data type to Frozen, you are asking TWS to send the last available quote when there is not one currently available. For instance, if a market is currently closed and real time data is requested, -1 values will commonly be returned for the bid and ask prices to indicate there is no current bid/ask data available. TWS will often show a ‘frozen’ bid/ask which represents the last value recorded by the system. To receive the last know bid/ask price before the market close, switch to market data type 2 from the API before requesting market data. API frozen data requires TWS/IBG v.962 or higher and the same market data subscriptions necessary for real time streaming data.
Delayed 3

Free, delayed data is 15 – 20 minutes delayed. In TWS, delayed data is displayed in brown background. When you set market data type to delayed, you are telling TWS to automatically switch to delayed market data if the user does not have the necessary real time data subscription. If live data is available a request for delayed data would be ignored by TWS. Delayed market data is returned with delayed Tick Types (Tick ID 66~76).

Delayed Frozen 4 Requests delayed “frozen” data for a user without market data subscriptions.

Market Data Type Behavior

1) If user sends reqMarketDataType(1) – TWS will start sending only regular (1) market data.

2) If user sends reqMarketDataType(2) – frozen, TWS will start sending regular (1) as default and frozen (2) market data. TWS sends marketDataType callback (1 or 2) indicating what market data will be sent after this callback. It can be regular or frozen.

3) If user sends reqMarketDataType(3) – delayed, TWS will start sending regular (1) as default and delayed (3) market data.

4) If user sends reqMarketDataType(4) – delayed-frozen, TWS will start sending regular (1) as default, delayed (3) and delayed-frozen (4) market data.

Interactive Brokers data will always try to provide the most up to date market data possible, but will permit additional delayed or frozen data if available upon request.

Request Market Data Type

EClient.reqMarketDataType (

marketDataType: int. Type of market data to retrieve.
)

Switches data type returned from reqMktData request to Live (1), Frozen (2), Delayed (3), or Frozen-Delayed (4).

self.reqMarketDataType(3)

 

client.reqMarketDataType(2);

 

m_pClient->reqMarketDataType(3);

 

client.reqMarketDataType(3);

 

client.reqMarketDataType(4)

 

Receive Market Data Type

EWrapper.marketDataType (

reqId: int. Request identifier used to track data.

marketDataType: int. Type of market data to retrieve.
)

def marketDataType(self, reqId: TickerId, marketDataType: int):
	print("MarketDataType. ReqId:", reqId, "Type:", marketDataType)

 

@Override
public void marketDataType(int reqId, int marketDataType) {
	System.out.println("MarketDataType: " + EWrapperMsgGenerator.marketDataType(reqId, marketDataType));
}

 

void TestCppClient::marketDataType(TickerId reqId, int marketDataType) {
    printf( "MarketDataType. ReqId: %ld, Type: %dn", reqId, marketDataType);
}

 

public virtual void marketDataType(int reqId, int marketDataType)
{
	Console.WriteLine("MarketDataType. "+reqId+", Type: "+marketDataType+"n");
}

 

Public Sub marketDataType(reqId As Integer, marketDataType As Integer) Implements IBApi.EWrapper.marketDataType
	Console.WriteLine("MarketDataType - ReqId [" & reqId & "] MarketDataType [" & marketDataType & "]")
End Sub

 

Market Data: Historical

Historical Market data is available for Interactive Brokers market data subscribers in a range of methods and structures. This includes requests for historical bars, identical to the Trader Workstation, historical Time & Sales, as well as Histogram data.

Historical Data Limitations

Historical market data has it’s own set of market data limitations unique to other requests such as real time market data. This section will cover all limitations that effect historical market data in the Trader Workstation API.

Historical Data Filtering

Historical data at IB is filtered for trade types which occur away from the NBBO such as combo legs, block trades, and derivative trades. For that reason the daily volume from the (unfiltered) real time data functionality will generally be larger than the (filtered) historical volume reported by historical data functionality. Also, differences are expected in other fields such as the VWAP between the real time and historical data feeds.

 

As historical data at IB gets adjusted, compressed and filtered by default, there may be historical data differences if you request historical data at different time points.

Pacing Violations for Small Bars (30 secs or less)

Although Interactive Brokers offers our clients high quality market data, IB is not a specialised market data provider and as such it is forced to put in place restrictions to limit traffic which is not directly associated to trading. A Pacing Violation occurs whenever one or more of the following restrictions is not observed:

Important: these limitations apply to all our clients and it is not possible to overcome them. If your trading strategy’s market data requirements are not met by our market data services please consider contacting a specialized provider.

 

  • Making identical historical data requests within 15 seconds.
  • Making six or more historical data requests for the same Contract, Exchange and Tick Type within two seconds.
  • Making more than 60 requests within any ten minute period.
  • Note that when BID_ASK historical data is requested, each request is counted twice. In a nutshell, the information above can simply be put as “do not request too much data too quick”.

Unavailable Historical Data

The other historical data limitations listed are general limitations for all trading platforms:

  • Bars whose size is 30 seconds or less older than six months
  • Expired futures data older than two years counting from the future’s expiration date.
  • Expired options, FOPs, warrants and structured products.
  • End of Day (EOD) data for options, FOPs, warrants and structured products.
  • Data for expired future spreads
  • Data for securities which are no longer trading.
  • Native historical data for combos. Historical data is not stored in the IB database separately for combos.; combo historical data in TWS or the API is the sum of data from the legs.
  • Historical data for securities which move to a new exchange will often not be available prior to the time of the move.
  • Studies and indicators such as Weighted Moving Averages or Bollinger Bands are not available from the API.

Finding the Earliest Available Data Point

For many functions, such as EClient.reqHistoricalData, you will need to request market data for a contract. Given that you may not know how long a symbol has been available, you can use EClient.reqHeadTimestamp to find the first available point of data for a given whatToShow value.

ReqHeadTimeStamp counts as an ongoing historical data request, similar to using EClient.reqHistoricalData’s keepUpToDate=True flag. As a result, users should always:

Requesting the Earliest Data Point

EClient.reqHeadTimestamp (

tickerId: int., A unique identifier which will serve to identify the incoming data.

contract: Contract. The IBApi.Contract you are interested in.

whatToShow: String. The type of data to retrieve. See Historical Data Types

useRTH: int. Whether (1) or not (0) to retrieve data generated only within Regular Trading Hours (RTH)

formatDate: int. Using 1 will return UTC time in YYYYMMDD-hh:mm:ss format. Using 2 will return epoch time.
)

Returns the timestamp of earliest available historical data for a contract and data type.

self.reqHeadTimeStamp(1, ContractSamples.USStockAtSmart(), "TRADES", 1, 1)

 

client.reqHeadTimestamp(4003, contract, "TRADES", 1, 1);

 

m_pClient->reqHeadTimestamp(14001, contract, "MIDPOINT", 1, 1);

 

client.reqHeadTimestamp(14001, contract, "TRADES", 1, 1);

 

client.reqHeadTimestamp(14001, ContractSamples.USStock(), "TRADES", 1, 1)

 

Receiving the Earliest Data Point

EWrapper.headTimestamp (

requestId: int. Request identifier used to track data.

headTimestamp: String. Value identifying earliest data date
)

The data requested will be returned to EWrapper.headTimeStamp.

def headTimestamp(self, reqId, headTimestamp):
        print(reqId, headTimestamp)

 

@Override
public void headTimestamp(int reqId, String headTimestamp) {
	System.out.println(EWrapperMsgGenerator.headTimestamp(reqId, headTimestamp));
}

 

void TestCppClient::headTimestamp(int reqId, const std::string& headTimestamp) {
    printf( "Head time stamp. ReqId: %d - Head time stamp: %s,n", reqId, headTimestamp.c_str());
}

 

public void headTimestamp(int reqId, string headTimestamp)
{
	Console.WriteLine("Head time stamp. Request Id: {0}, Head time stamp: {1}", reqId, headTimestamp);
}

 

Public Sub headTimestamp(requestId As Integer, timeStamp As String) Implements IBApi.EWrapper.headTimestamp
	Console.WriteLine("Head time stamp. Request Id: {0}, Head time stamp: {1}", requestId, timeStamp)
End Sub

 

Cancelling Timestamp Requests

EWrapper.cancelHistogramData (

tickerId: int. Request identifier used to track data.
)

A reqHeadTimeStamp request can be cancelled with EClient.cancelHeadTimestamp

self.cancelHeadTimeStamp(reqId)

 

client.cancelHeadTimestamp(4003);

 

m_pClient->cancelHeadTimestamp(14001);

 

client.cancelHeadTimestamp(14001);

 

client.cancelHeadTimestamp(14001)

 

Historical Bars

Historical Bar data returns a candlestick value based on the requested duration and bar size. This will always return an open, high, low, and close values. Based on which whatToShow value is used, you may also receive volume data. See the whatToShow section for more details.

Requesting Historical Bars

EClient.reqHistoricalData(

tickerId: int, A unique identifier which will serve to identify the incoming data.

contract: Contract, The IBApi.Contract object you are working with.

endDateTime: String, The request’s end date and time. This should be formatted as “YYYYMMDD HH:mm:ss TMZ” or an empty string indicates current present moment).
Please be aware that endDateTime must be left as an empty string when requesting continuous futures contracts.

durationString: String, The amount of time (or Valid Duration String units) to go back from the request’s given end date and time.

barSizeSetting: String, The data’s granularity or Valid Bar Sizes

whatToShow: String, The type of data to retrieve. See Historical Data Types

useRTH: bool, Whether (1) or not (0) to retrieve data generated only within Regular Trading Hours (RTH)

formatDate: bool, The format in which the incoming bars’ date should be presented. Note that for day bars, only yyyyMMdd format is available.

keepUpToDate: bool, Whether a subscription is made to return updates of unfinished real time bars as they are available (True), or all data is returned on a one-time basis (False). If True, and endDateTime cannot be specified.
Supported whatToShow values: Trades, Midpoint, Bid, Ask.

mktDataOptions: TagValueList, This is a field used exclusively for internal use.

)

self.reqHistoricalData(4102, contract, queryTime, "1 M", "1 day", "MIDPOINT", 1, 1, False, [])

Expected Sample Output:

HistoricalData. ReqId: 4102 BarData. Date: 20240516, Open: 400, High: 401, Low: 394.6, Close: 397, Volume: 55200800, WAP: 398.21, BarCount: 102391
HistoricalData. ReqId: 4102 BarData. Date: 20240517, Open: 397, High: 400.2, Low: 394.2, Close: 395, Volume: 26304400, WAP: 396.94, BarCount: 57594
HistoricalData. ReqId: 4102 BarData. Date: 20240520, Open: 397, High: 399.8, Low: 392.8, Close: 395, Volume: 21057500, WAP: 395.37, BarCount: 46229
HistoricalData. ReqId: 4102 BarData. Date: 20240521, Open: 393.4, High: 393.4, Low: 379.6, Close: 383.6, Volume: 29822300, WAP: 384.32, BarCount: 77989
HistoricalData. ReqId: 4102 BarData. Date: 20240522, Open: 379.2, High: 386.8, Low: 376.6, Close: 384.4, Volume: 21204400, WAP: 382.81, BarCount: 50530
HistoricalData. ReqId: 4102 BarData. Date: 20240523, Open: 380.6, High: 384, Low: 376.4, Close: 381.8, Volume: 17864300, WAP: 381.04, BarCount: 47497
HistoricalDataEnd. ReqId: 4102 from 20240514 12:10:33 Hongkong to 20240614 12:10:33 Hongkong

 

Code example:

from ibapi.client import *
from ibapi.wrapper import *
from ibapi.contract import Contract
import threading
import time

class TradeApp(EWrapper, EClient): 
    def __init__(self): 
        EClient.__init__(self, self) 
        
    def historicalData(self, reqId, bar):
        print("HistoricalData. ReqId:", reqId, "BarData.", bar)

    def historicalSchedule(self, reqId: int, startDateTime: str, endDateTime: str, timeZone: str, sessions: ListOfHistoricalSessions):
        print("HistoricalSchedule. ReqId:", reqId, "Start:", startDateTime, "End:", endDateTime, "TimeZone:", timeZone)
        for session in sessions:
            print("tSession. Start:", session.startDateTime, "End:", session.endDateTime, "Ref Date:", session.refDate)

    def historicalDataUpdate(self, reqId: int, bar: BarData):
        print("HistoricalDataUpdate. ReqId:", reqId, "BarData.", bar)

    def historicalDataEnd(self, reqId: int, start: str, end: str):
        print("HistoricalDataEnd. ReqId:", reqId, "from", start, "to", end)


def websocket_con():
    app.run()
    
app = TradeApp()      
app.connect("127.0.0.1", 7496, clientId=1)

con_thread = threading.Thread(target=websocket_con, daemon=True)
con_thread.start()

time.sleep(1) 

contract = Contract()
contract.symbol = "AAPL"
contract.secType = "STK"
contract.exchange = "SMART"
contract.currency = "USD"

app.reqHistoricalData(reqId=101, 
                          contract=contract,
                          endDateTime='', 
                          durationStr='1 D',
                          barSizeSetting='1 hour',
                          whatToShow='Trades',
                          useRTH=0,                 #0 = Includes data outside of RTH | 1 = RTH data only 
                          formatDate=1,    
                          keepUpToDate=1,           #0 = False | 1 = True 
                          chartOptions=[])

 

client.reqHistoricalData(4002, contract, formatted, "10 D", "1 min", "TRADES", 1, 1, false, null);

 

m_pClient->reqHistoricalData(4001, contract, queryTime, "1 M", "1 day", "MIDPOINT", 1, 1, false, TagValueListSPtr());

 

client.reqHistoricalData(4001, contract, queryTime, "1 M", "1 day", "MIDPOINT", 1, 1, false, null);

 

client.reqHistoricalData(4001, contract, queryTime, "1 M", "1 day", "MIDPOINT", 1, 1, False, Nothing)

 

Duration

The Interactive Brokers Historical Market Data maintains a duration parameter which specifies the overall length of time that data can be collected. The duration specified will derive the bars of data that can then be collected.

Valid Duration String Units:

Unit Description
S Seconds
D Day
W Week
M Month
Y Year

 

Historical Bar Sizes

Bar sizes dictate the data returned by historical bar requests. The bar size will dictate the scale over which the OHLC/V is returned to the API.

Valid Bar Sizes:

Bar Unit Bar Sizes
secs 1, 5, 10, 15, 30
mins 1, 2, 3, 5, 10, 15, 20, 30
hrs 1, 2, 3, 4, 8
days 1
weeks 1
months 1

 

Step Sizes

The functionality of market data requests are predicated on preset step sizes. As such, not all bar sizes will work with all duration values. The table listed here will discuss the smallest to largest bar size value for each duration string.

Duration Unit Bar units allowed Bar size Interval (Min/Max)
S secs | mins 1 secs -> 1mins
D secs | mins | hrs 5 secs -> 1 hours
W sec | mins | hrs 10 secs -> 4 hrs
M sec | mins | hrs 30 secs -> 8 hrs
Y mins | hrs   | d 1 mins-> 1 day

Max Duration Per Bar Size

The table below displays the maximum duration values allowed for a given bar.

As an example, the maximum duration for Seconds values supported for 5 seconds bars are 86400 S. This means that if I want to retrieve more than 1 day’s worth of 5 second bars, I will then need to request data in increments of D (days).

Bar Size Max Second Duration Max Day Duration Max Week Duration Max Month Duration Max Year Duration
1 secs 2000 S {Not Supported} {Not Supported} {Not Supported} {Not Supported}
5 secs 86400 S 365 D 52 W 12 M 68 Y
10 secs 86400 S 365 D 52 W 12 M 68 Y
15 secs 86400 S 365 D 52 W 12 M 68 Y
30 secs 86400 S 365 D 52 W 12 M 68 Y
1 min 86400 S 365 D 52 W 12 M 68 Y
2 mins 86400 S 365 D 52 W 12 M 68 Y
3 mins 86400 S 365 D 52 W 12 M 68 Y
5 mins 86400 S 365 D 52 W 12 M 68 Y
10 mins 86400 S 365 D 52 W 12 M 68 Y
15 mins 86400 S 365 D 52 W 12 M 68 Y
20 mins 86400 S 365 D 52 W 12 M 68 Y
30 mins 86400 S 365 D 52 W 12 M 68 Y
1 hour 86400 S 365 D 52 W 12 M 68 Y
2 hours 86400 S 365 D 52 W 12 M 68 Y
3 hours 86400 S 365 D 52 W 12 M 68 Y
4 hours 86400 S 365 D 52 W 12 M 68 Y
8 hours 86400 S 365 D 52 W 12 M 68 Y
1 day 86400 S 365 D 52 W 12 M 68 Y
1M 86400 S 365 D 52 W 12 M 68 Y
1W 86400 S 365 D 52 W 12 M 68 Y

Format Date Received

Interactive Brokers will return historical market data based on the format set from the request. The formatDate parameter can be provided an integer value to indicate how data should be returned.

Note: Day bars will only return dates in the yyyyMMdd format. Time data is not available.

Value Description Example
1 String Time Zone Date “20231019 16:11:48 America/New_York”
2 Epoch Date 1697746308
3 Day & Time Date “1019 16:11:48 America/New_York”

Keep Up To Date

When using keepUpToDate=True for historical data requests, you will see several bars returned with the same timestamp. This is because data is updated approximately every 1-2 seconds. These updates compound until the end of the specified bar size.

In our example to the below, 15 second bars are requested, and we can see the 30 second bar built out incrementally until 20231204 13:30:30 is completed. At which point, we move on to the 45th second bars. This same logic extends into minute, hourly, or daily bars.

Note:

keepUpToDate is only available for whatToShow: Trades, Midpoint, Bid, Ask

Date: 20231204 13:30:30 US/Eastern, Open: 188.56, High: 188.56, Low: 188.54, Close: 188.55
Date: 20231204 13:30:30 US/Eastern, Open: 188.56, High: 188.56, Low: 188.54, Close: 188.55
Date: 20231204 13:30:30 US/Eastern, Open: 188.56, High: 188.56, Low: 188.54, Close: 188.55
Date: 20231204 13:30:30 US/Eastern, Open: 188.56, High: 188.56, Low: 188.54, Close: 188.55
Date: 20231204 13:30:30 US/Eastern, Open: 188.56, High: 188.56, Low: 188.54, Close: 188.55
Date: 20231204 13:30:30 US/Eastern, Open: 188.56, High: 188.56, Low: 188.54, Close: 188.56
Date: 20231204 13:30:30 US/Eastern, Open: 188.56, High: 188.56, Low: 188.54, Close: 188.56
Date: 20231204 13:30:30 US/Eastern, Open: 188.56, High: 188.57, Low: 188.54, Close: 188.55
Date: 20231204 13:30:45 US/Eastern, Open: 188.54, High: 188.54, Low: 188.54, Close: 188.54

 

Receiving Historical Bars

EWrapper.historicalData (

reqId: int. Request identifier used to track data.

bar: Bar. The OHLC historical data Bar. The time zone of the bar is the time zone chosen on the TWS login screen. Smallest bar size is 1 second.
)

The historical data will be delivered via the EWrapper.historicalData method in the form of candlesticks. The time zone of returned bars is the time zone chosen in TWS on the login screen.

def historicalData(self, reqId:int, bar: BarData):
	print("HistoricalData. ReqId:", reqId, "BarData.", bar)

 

@Override
public void historicalData(int reqId, Bar bar) {
	System.out.println("HistoricalData:  " + EWrapperMsgGenerator.historicalData(reqId, bar.time(), bar.open(), bar.high(), bar.low(), bar.close(), bar.volume(), bar.count(), bar.wap()));
}

 

void TestCppClient::historicalData(TickerId reqId, const Bar& bar) {
    printf( "HistoricalData. ReqId: %ld - Date: %s, Open: %s, High: %s, Low: %s, Close: %s, Volume: %s, Count: %s, WAP: %sn", reqId, bar.time.c_str(), 
        Utils::doubleMaxString(bar.open).c_str(), Utils::doubleMaxString(bar.high).c_str(), Utils::doubleMaxString(bar.low).c_str(), Utils::doubleMaxString(bar.close).c_str(), 
        decimalStringToDisplay(bar.volume).c_str(), Utils::intMaxString(bar.count).c_str(), decimalStringToDisplay(bar.wap).c_str());
}

 

public virtual void historicalData(int reqId, Bar bar)
{
	Console.WriteLine("HistoricalData. " + reqId + " - Time: " + bar.Time + ", Open: " + Util.DoubleMaxString(bar.Open) + ", High: " + Util.DoubleMaxString(bar.High) + ", Low: " + Util.DoubleMaxString(bar.Low) + ", Close: " + Util.DoubleMaxString(bar.Close) + ", Volume: " + Util.DecimalMaxString(bar.Volume) + ", Count: " + Util.IntMaxString(bar.Count) + ", WAP: " + Util.DecimalMaxString(bar.WAP));
}

 

public virtual void historicalData(int reqId, Bar bar)
{
	Console.WriteLine("HistoricalData. " + reqId + " - Time: " + bar.Time + ", Open: " + Util.DoubleMaxString(bar.Open) + ", High: " + Util.DoubleMaxString(bar.High) + ", Low: " + Util.DoubleMaxString(bar.Low) + ", Close: " + Util.DoubleMaxString(bar.Close) + ", Volume: " + Util.DecimalMaxString(bar.Volume) + ", Count: " + Util.IntMaxString(bar.Count) + ", WAP: " + Util.DecimalMaxString(bar.WAP));
}

 

EWrapper.historicalSchedule (

reqId: int. Request identifier used to track data.

startDateTime: String. Returns the start date and time of the historical schedule range.

endDateTime: String. Returns the end date and time of the historical schedule range.

timeZone: String. Returns the time zone referenced by the schedule.

sessions: HistoricalSession[]. Returns the full block of historical schedule data for the duration.
)

In the case of whatToShow=”schedule”, you will need to also define the EWrapper.historicalSchedule value. This is a unique method that will only be called in the case of the unique whatToShow value to display calendar information.

def historicalSchedule(self, reqId: int, startDateTime: str, endDateTime: str, timeZone: str, sessions: ListOfHistoricalSessions):
	print("HistoricalSchedule. ReqId:", reqId, "Start:", startDateTime, "End:", endDateTime, "TimeZone:", timeZone)
	for session in sessions:
		print("tSession. Start:", session.startDateTime, "End:", session.endDateTime, "Ref Date:", session.refDate)

 

@Override
public void historicalSchedule(int reqId, String startDateTime, String endDateTime, String timeZone, List sessions) {
	System.out.println(EWrapperMsgGenerator.historicalSchedule(reqId, startDateTime, endDateTime, timeZone, sessions));
}

 

void TestCppClient::historicalSchedule(int reqId, const std::string& startDateTime, const std::string& endDateTime, const std::string& timeZone, const std::vector& sessions) {
    printf("Historical Schedule. ReqId: %d, Start: %s, End: %s, TimeZone: %sn", reqId, startDateTime.c_str(), endDateTime.c_str(), timeZone.c_str());
    for (unsigned int i = 0; i < sessions.size(); i++) {
        printf("tSession. Start: %s, End: %s, RefDate: %sn", sessions[i].startDateTime.c_str(), sessions[i].endDateTime.c_str(), sessions[i].refDate.c_str());
    }
}

 

public void historicalSchedule(int reqId, string startDateTime, string endDateTime, string timeZone, HistoricalSession[] sessions)
{
	Console.WriteLine($"Historical Schedule. ReqId: {reqId}, Start: {startDateTime}, End: {endDateTime}, Time Zone: {timeZone}");
	foreach (var session in sessions)
	{
		Console.WriteLine($"tSession. Start: {session.StartDateTime}, End: {session.EndDateTime}, Ref Date: {session.RefDate}");
	}
}

 

public void historicalSchedule(int reqId, string startDateTime, string endDateTime, string timeZone, HistoricalSession[] sessions)
{
	Console.WriteLine($"Historical Schedule. ReqId: {reqId}, Start: {startDateTime}, End: {endDateTime}, Time Zone: {timeZone}");
	foreach (var session in sessions)
	{
		Console.WriteLine($"tSession. Start: {session.StartDateTime}, End: {session.EndDateTime}, Ref Date: {session.RefDate}");
	}
}

 

EWrapper.historicalDataUpdate (

reqId: int. Request identifier used to track data.

bar: Bar. The OHLC historical data Bar. The time zone of the bar is the time zone chosen on the TWS login screen. Smallest bar size is 1 second.
)

Receives bars in real time if keepUpToDate is set as True in reqHistoricalData. Similar to realTimeBars function, except returned data is a composite of historical data and real time data that is equivalent to TWS chart functionality to keep charts up to date. Returned bars are successfully updated using real time data.

def historicalDataUpdate(self, reqId: int, bar: BarData):
	print("HistoricalDataUpdate. ReqId:", reqId, "BarData.", bar)

 

@Override
public void historicalDataUpdate(int reqId, Bar bar) {
	System.out.println("HistoricalDataUpdate. " + EWrapperMsgGenerator.historicalData(reqId, bar.time(), bar.open(), bar.high(), bar.low(), bar.close(), bar.volume(), bar.count(), bar.wap()));
}

 

void TestCppClient::historicalDataUpdate(TickerId reqId, const Bar& bar) {
    printf( "HistoricalDataUpdate. ReqId: %ld - Date: %s, Open: %s, High: %s, Low: %s, Close: %s, Volume: %s, Count: %s, WAP: %sn", reqId, bar.time.c_str(), 
        Utils::doubleMaxString(bar.open).c_str(), Utils::doubleMaxString(bar.high).c_str(), Utils::doubleMaxString(bar.low).c_str(), Utils::doubleMaxString(bar.close).c_str(), 
        decimalStringToDisplay(bar.volume).c_str(), Utils::intMaxString(bar.count).c_str(), decimalStringToDisplay(bar.wap).c_str());
}

 

public void historicalDataUpdate(int reqId, Bar bar)
{
	Console.WriteLine("HistoricalDataUpdate. " + reqId + " - Time: " + bar.Time + ", Open: " + Util.DoubleMaxString(bar.Open) + ", High: " + Util.DoubleMaxString(bar.High) + 
		", Low: " + Util.DoubleMaxString(bar.Low) + ", Close: " + Util.DoubleMaxString(bar.Close) + ", Volume: " + Util.DecimalMaxString(bar.Volume) + 
		", Count: " + Util.IntMaxString(bar.Count) + ", WAP: " + Util.DecimalMaxString(bar.WAP));
}

 

public void historicalDataUpdate(int reqId, Bar bar)
{
	Console.WriteLine("HistoricalDataUpdate. " + reqId + " - Time: " + bar.Time + ", Open: " + Util.DoubleMaxString(bar.Open) + ", High: " + Util.DoubleMaxString(bar.High) + ", Low: " + Util.DoubleMaxString(bar.Low) + ", Close: " + Util.DoubleMaxString(bar.Close) + ", Volume: " + Util.DecimalMaxString(bar.Volume) + ", Count: " + Util.IntMaxString(bar.Count) + ", WAP: " + Util.DecimalMaxString(bar.WAP));
}

 

EWrapper.historicalDataEnd (

reqId: int. Request identifier used to track data.

start: String. Returns the starting time of the first historical data bar.

end: String. Returns the end time of the last historical data bar.
)

Marks the ending of the historical bars reception.

def historicalDataEnd(self, reqId: int, start: str, end: str):
	print("HistoricalDataEnd. ReqId:", reqId, "from", start, "to", end)

 

@Override
public void historicalDataEnd(int reqId, String startDateStr, String endDateStr) {
	System.out.println("HistoricalDataEnd. " + EWrapperMsgGenerator.historicalDataEnd(reqId, startDateStr, endDateStr));
}

 

void TestCppClient::historicalDataEnd(int reqId, const std::string& startDateStr, const std::string& endDateStr) {
    std::cout << "HistoricalDataEnd. ReqId: " << reqId << " - Start Date: " << startDateStr << ", End Date: " << endDateStr << std::endl;   
}

 

public virtual void historicalDataEnd(int reqId, string startDate, string endDate)
{
	Console.WriteLine("HistoricalDataEnd - "+reqId+" from "+startDate+" to "+endDate);
}

 

public virtual void historicalDataEnd(int reqId, string startDate, string endDate)
        {
            Console.WriteLine("HistoricalDataEnd - "+reqId+" from "+startDate+" to "+endDate);
        }

 

Historical Bar whatToShow

The historical bar types listed below can be used as the whatToShow value for historical bars. These values are used to request different data such as Trades, Midpoint, Bid_Ask data and more. Some bar types support more products than others. Please note the Supported Products section for each bar type below.

AGGTRADES

Bar Values:

Open High Low Close Volume
First traded price Highest traded price Lowest traded price Last traded price Total traded volume

Supported Products: Cryptocurrency

ASK

Bar Values:

Open High Low Close Volume
Starting ask price Highest ask price Lowest ask price Last ask price N/A

Supported Products: Bonds, CFDs, Commodities, Cryptocurrencies, ETFs, FOPs, Forex, Funds, Futures,  Metals, Options, SSFs, Stocks, Structured Products, Warrants

BID

Bar Values:

Open High Low Close Volume
Starting bid price Highest bid price Lowest bid price Last bid price N/A

Supported Products: Bonds, CFDs, Commodities, Cryptocurrencies, ETFs, FOPs, Forex, Funds, Futures,  Metals, Options, SSFs, Stocks, Structured Products, Warrants

BID_ASK

Bar Values:

Open High Low Close Volume
Time average bid Max Ask Min Bid Time average ask N/A

Supported Products: Bonds, CFDs, Commodities, Cryptocurrencies, ETFs, FOPs, Forex, Funds, Futures, Metals, Options, SSFs, Stocks, Structured Products, Warrants

FEE_RATE

Bar Values:

Open High Low Close Volume
Starting Fee Rate Highest fee rate Lowest fee rate Last fee rate N/A

Supported Products: Stocks, ETFs,

HISTORICAL_VOLATILITY

Bar Values:

Open High Low Close Volume
Starting volatility Highest volatility Lowest volatility Last volatility N/A

Supported Products: ETFs, Indices, Stocks

MIDPOINT

Bar Values:

Open High Low Close Volume
Starting midpoint price Highest midpoint price Lowest midpoint price Last midpoint price N/A

Supported Products: Bonds, CFDs, Commodities, Cryptocurrencies, ETFs, FOPs, Forex, Funds, Futures,  Metals, Options, SSFs, Stocks, Structured Products, Warrants

OPTION_IMPLIED_VOLATILITY

Bar Values:

Open High Low Close Volume
Starting implied volatility Highest implied volatility Lowest implied volatility Last implied volatility N/A

Supported Products: ETFs, Indices, Stocks

SCHEDULE

Bar Values:

Open High Low Close Volume
Starting ask price Highest ask price Lowest ask price Last ask price N/A

Supported Products: Bonds, CFDs, Commodities, Cryptocurrencies, ETFs, Forex, Funds, Futures, Indices, Metals,  SSFs, Stocks, Structured Products, Warrants

NOTE: SCHEDULE data returns only on 1 day bars but returns historical trading schedule only with no information about OHLCV.

TRADES

Bar Values:

Open High Low Close Volume
First traded price Highest traded price Lowest traded price Last traded price Total traded volume

Supported Products: Bonds, ETFs, FOPs, Futures, Indices, Metals, Options, SSFs, Stocks, Structured Products, Warrants

NOTES: TRADES data is adjusted for splits, but not dividends.

YIELD_ASK

Bar Values:

Open High Low Close Volume
Starting ask yield Highest ask yield Lowest ask yield Last ask yield N/A

Supported Products: Indices

Note: Yield historical data only available for corporate bonds.

YIELD_BID

Bar Values:

Open High Low Close Volume
Starting bid yield Highest bid yield Lowest bid yield Last bid yield N/A

Supported Products: Indices

Note: Yield historical data only available for corporate bonds.

YIELD_BID_ASK

Bar Values:

Open High Low Close Volume
Time average bid yield Highest ask yield Lowest bid yield Time average ask yield N/A

Supported Products: Indices

Note: Yield historical data only available for corporate bonds.

YIELD_LAST

Bar Values:

Open High Low Close Volume
Starting last yield Highest last yield Lowest last yield Last last yield N/A

Supported Products: Indices

Note: Yield historical data only available for corporate bonds.

Histogram Data

Instead of returned data points as a function of time as with the function IBApi::EClient::reqHistoricalData, histograms return data as a function of price level with function IBApi::EClient::reqHistogramData

Requesting Histogram Data

EClient.reqHistogramData (

requestId: int, id of the request

contract: Contract, Contract object that is subject of query.

useRth: bool, Data from regular trading hours (1), or all available hours (0).

period: String, string value of requested date range. This will be tied to the same bar size strings as the historical bar sizes
)

Returns data histogram of specified contract.

self.reqHistogramData(4004, contract, false, "3 days")

 

client.reqHistogramData(4004, contract, false, "3 days");

 

m_pClient->reqHistogramData(15001, contract, false, "1 weeks");

 

client.reqHistogramData(15001, contract, false, "1 week");

 

client.reqHistogramData(15001, contract, False, "1 week")

 

Receiving Histogram Data

EWrapper.histogramData (

requestId: int. Request identifier used to track data.

data: HistogramEntry[]. Returned Tuple of histogram data, number of trades at specified price level.
)

Returns relevant histogram data.

def histogramData(self, reqId:int, items:HistogramDataList):
	print("HistogramData. reqid, items)

 

@Override
public void histogramData(int reqId, List items) {
	System.out.println(EWrapperMsgGenerator.histogramData(reqId, items));
}

 

void TestCppClient::histogramData(int reqId, const HistogramDataVector& data) {
    printf("Histogram. ReqId: %d, data length: %lun", reqId, data.size());
    for (const HistogramEntry& entry : data) {
        printf("t price: %s, size: %sn", Utils::doubleMaxString(entry.price).c_str(), decimalStringToDisplay(entry.size).c_str());
    }
}

 

public void histogramData(int reqId, HistogramEntry[] data)
{
	Console.WriteLine("Histogram data. Request Id: {0}, data size: {1}", reqId, data.Length);
	data.ToList().ForEach(i => Console.WriteLine("tPrice: {0}, Size: {1}", Util.DoubleMaxString(i.Price), Util.DecimalMaxString(i.Size)));
}

 

Public Sub histogramData(reqId As Integer, data As HistogramEntry()) Implements EWrapper.histogramData
	Console.WriteLine("Histogram data. Request Id: {0}, data size: {1}", reqId, data.Length) 
	data.ToList().ForEach(Sub(i) Console.WriteLine(vbTab & "Price: {0}, Size: {1}", Util.DoubleMaxString(i.Price), Util.DecimalMaxString(i.Size)))
End Sub

 

Cancelling Histogram Data

EClient.cancelHistogramData (

tickerId: int. Request identifier used to track data.
)

An active histogram request which has not returned data can be cancelled with EClient.cancelHistogramData

self.reqHistogramData(4004)

 

client.cancelHistogramData(4004);

 

m_pClient->cancelHistogramData(15001);

 

client.cancelHistogramData(15001);

 

client.cancelHistogramData(15001)

 

Historical Time & Sales

The highest granularity of historical data from IB’s database can be retrieved using the API function EClient.reqHistoricalTicks for historical time and sales values. Historical Time & Sales will return the same data as what is available in Trader Workstation under the Time and Sales window. This is a series of ticks indicating each trade based on the requested values.

  • Historical Tick-By-Tick data is not available for combos.
  • Data will not be returned from multiple trading sessions in a single request; Multiple requests must be used.
  • To complete a full second, more ticks may be returned than requested.
  • Time & Sales data requires a Level 1, Top Of Book market data subscription. This would be the same subscription as EClient.reqMktData() or EClient.reqHistoricalData().

Requesting Time and Sales data

EClient.reqHistoricalTicks (

requestId: int, id of the request

contract: Contract, Contract object that is subject of query.

startDateTime: String, i.e. “20170701 12:01:00”. Uses TWS timezone specified at login.

endDateTime: String, i.e. “20170701 13:01:00”. In TWS timezone. Exactly one of startDateTime or endDateTime must be defined.

numberOfTicks: int, Number of distinct data points. Max is 1000 per request.

whatToShow: String, (Bid_Ask, Midpoint, or Trades) Type of data requested.

useRth: bool, Data from regular trading hours (1), or all available hours (0).

ignoreSize: bool, Omit updates that reflect only changes in size, and not price. Applicable to Bid_Ask data requests.
Note: Options and Future Options will only display a value of 1, unless to indicate a removed bid/ask, which will instead return a price and size value of 0.

miscOptions: list, Should be defined as null; reserved for internal use.
)

Requests historical Time & Sales data for an instrument.

self.reqHistoricalTicks(18001, contract, "20170712 21:39:33 US/Eastern", "", 10, "TRADES", 1, True, [])

 

client.reqHistoricalTicks(18001, contract, "20220808 10:00:00 US/Eastern", null, 10, "TRADES", 1, true, null);

 

m_pClient->reqHistoricalTicks(19001, contract, "20170621 09:38:33 US/Eastern", "", 10, "BID_ASK", 1, true, TagValueListSPtr());

 

client.reqHistoricalTicks(18001, contract, "20170712 21:39:33 US/Eastern", null, 10, "TRADES", 1, true, null);

 

client.reqHistoricalTicks(18001, contact, "20170712 21:39:33 US/Eastern", Nothing, 10, "TRADES", 1, True, Nothing)

 

Receiving Time and Sales data

Data is returned to unique functions based on what is requested in the whatToShow field.

  • IBApi.EWrapper.historicalTicks for whatToShow=MIDPOINT
  • IBApi.EWrapper.historicalTicksBidAsk for whatToShow=BID_ASK
  • IBApi.EWrapper.historicalTicksLast for for whatToShow=TRADES

EWrapper.historicalTicks (

reqId: int, id of the request

ticks: ListOfHistoricalTick, object containing a list of tick values for the requested timeframe.

done: bool, return whether or not this is the end of the historical ticks requested.
)

For whatToShow=MIDPOINT

def historicalTicks(self, reqId: int, ticks: ListOfHistoricalTickLast, done: bool):
	for tick in ticks:
		print("historicalTicks. ReqId:", reqId, tick)

 

@Override
public void historicalTicks(int reqId, List ticks, boolean done) {
	for (HistoricalTick tick : ticks) {
		System.out.println(EWrapperMsgGenerator.historicalTick(reqId, tick.time(), tick.price(), tick.size()));
	}
}

 

void TestCppClient::historicalTicks(int reqId, const std::vector& ticks, bool done) {
    for (const HistoricalTick& tick : ticks) {
    std::time_t t = tick.time;
        std::cout << "Historical tick. ReqId: " << reqId << ", time: " << ctime(&t) << ", price: "<< Utils::doubleMaxString(tick.price).c_str() << ", size: " << decimalStringToDisplay(tick.size).c_str() << std::endl;
    }
}

 

public void historicalTicks(int reqId, HistoricalTick[] ticks, bool done)
{
	foreach (var tick in ticks)
	{
		Console.WriteLine("Historical Tick. Request Id: {0}, Time: {1}, Price: {2}, Size: {3}", reqId, Util.UnixSecondsToString(tick.Time, "yyyyMMdd-HH:mm:ss"), Util.DoubleMaxString(tick.Price), Util.DecimalMaxString(tick.Size));
	}
}

 

Public Sub historicalTick(reqId As Integer, ticks As HistoricalTick(), done As Boolean) Implements EWrapper.historicalTicks
	For Each tick In ticks
		Console.WriteLine("Historical Tick. Request Id: {0}, Time: {1}, Price: {2}, Size: {3}", reqId, Util.UnixSecondsToString(tick.Time, "yyyyMMdd-HH:mm:ss"), Util.DoubleMaxString(tick.Price), Util.DecimalMaxString(tick.Size))
	Next
End Sub

 

EWrapper.historicalTicksBidAsk (

reqId: int, id of the request

ticks: ListOfHistoricalTick, object containing a list of tick values for the requested timeframe.

done: bool, return whether or not this is the end of the historical ticks requested.
)

For whatToShow=BidAsk

def historicalTicksBidAsk(self, reqId: int, ticks: ListOfHistoricalTickLast, done: bool):
	for tick in ticks:
		print("historicalTicksBidAsk. ReqId:", reqId, tick)

 

@Override
public void historicalTicksBidAsk(int reqId, List ticks, boolean done) {
	for (HistoricalTickBidAsk tick : ticks) {
		System.out.println(EWrapperMsgGenerator.historicalTickBidAsk(reqId, tick.time(), tick.tickAttribBidAsk(), tick.priceBid(), tick.priceAsk(), tick.sizeBid(),
				tick.sizeAsk()));
	}
}   

 

void TestCppClient::historicalTicksBidAsk(int reqId, const std::vector& ticks, bool done) {
    for (const HistoricalTickBidAsk& tick : ticks) {
		std::time_t t = tick.time;
        std::cout << "Historical tick bid/ask. ReqId: " << reqId << ", time: " << ctime(&t) << ", price bid: "<< Utils::doubleMaxString(tick.priceBid).c_str()  << ", price ask: "<< Utils::doubleMaxString(tick.priceAsk).c_str() << ", size bid: " << decimalStringToDisplay(tick.sizeBid).c_str() << ", size ask: " << decimalStringToDisplay(tick.sizeAsk).c_str() << ", bidPastLow: " << tick.tickAttribBidAsk.bidPastLow << ", askPastHigh: " << tick.tickAttribBidAsk.askPastHigh << std::endl;
    }
}

 

public void historicalTicksBidAsk(int reqId, HistoricalTickBidAsk[] ticks, bool done)
{
	foreach (var tick in ticks)
	{
		Console.WriteLine("Historical Tick Bid/Ask. Request Id: {0}, Time: {1}, Price Bid: {2}, Price Ask: {3}, Size Bid: {4}, Size Ask: {5}, Bid/Ask Tick Attribs: {6} ", reqId, Util.UnixSecondsToString(tick.Time, "yyyyMMdd-HH:mm:ss"), Util.DoubleMaxString(tick.PriceBid), Util.DoubleMaxString(tick.PriceAsk), Util.DecimalMaxString(tick.SizeBid), Util.DecimalMaxString(tick.SizeAsk), tick.TickAttribBidAsk);
	}
}

 

Public Sub historicalTickBidAsk(reqId As Integer, ticks As HistoricalTickBidAsk(), done As Boolean) Implements EWrapper.historicalTicksBidAsk
	For Each tick In ticks
		Console.WriteLine("Historical Tick Bid/Ask. Request Id: {0}, Time: {1}, Price Bid: {2}, Price Ask: {3}, Size Bid: {4}, Size Ask: {5}, Bid/Ask Tick Attribs: {6}", reqId, Util.UnixSecondsToString(tick.Time, "yyyyMMdd-HH:mm:ss"), Util.DoubleMaxString(tick.PriceBid), Util.DoubleMaxString(tick.PriceAsk), Util.DecimalMaxString(tick.SizeBid), Util.DecimalMaxString(tick.SizeAsk), tick.TickAttribBidAsk.ToString())
	Next
End Sub

 

EWrapper.historicalTicksLast (

reqId: int, id of the request

ticks: ListOfHistoricalTick, object containing a list of tick values for the requested timeframe.

done: bool, return whether or not this is the end of the historical ticks requested.
)

For whatToShow=Last & AllLast

def historicalTicksLast(self, reqId: int, ticks: ListOfHistoricalTickLast, done: bool):
	for tick in ticks:
		print("HistoricalTickLast. ReqId:", reqId, tick)

 

public void historicalTicksLast(int reqId, List ticks, boolean done) {
	for (HistoricalTickLast tick : ticks) {
		System.out.println(EWrapperMsgGenerator.historicalTickLast(reqId, tick.time(), tick.tickAttribLast(), tick.price(), tick.size(), tick.exchange(), 
			tick.specialConditions()));
	}
}

 

void TestCppClient::historicalTicksLast(int reqId, const std::vector& ticks, bool done) {
    for (HistoricalTickLast tick : ticks) {
		std::time_t t = tick.time;
        std::cout << "Historical tick last. ReqId: " << reqId << ", time: " << ctime(&t) << ", price: "<< Utils::doubleMaxString(tick.price).c_str() << ", size: " << decimalStringToDisplay(tick.size).c_str() << ", exchange: " << tick.exchange << ", special conditions: " << tick.specialConditions << ", unreported: " << tick.tickAttribLast.unreported << ", pastLimit: " << tick.tickAttribLast.pastLimit << std::endl;
    }
}

 

public void historicalTicksLast(int reqId, HistoricalTickLast[] ticks, bool done)
{
	foreach (var tick in ticks)
	{
		Console.WriteLine("Historical Tick Last. Request Id: {0}, Time: {1}, Price: {2}, Size: {3}, Exchange: {4}, Special Conditions: {5}, Last Tick Attribs: {6} ", reqId, Util.UnixSecondsToString(tick.Time, "yyyyMMdd-HH:mm:ss"), Util.DoubleMaxString(tick.Price), Util.DecimalMaxString(tick.Size), tick.Exchange, tick.SpecialConditions, tick.TickAttribLast);
	}
}

 

Public Sub historicalTickLast(reqId As Integer, ticks As HistoricalTickLast(), done As Boolean) Implements EWrapper.historicalTicksLast
	For Each tick In ticks
		Console.WriteLine("Historical Tick Last. Request Id: {0}, Time: {1}, Price: {2}, Size: {3}, Exchange: {4}, Special Conditions: {5}, Last Tick Attribs: {6}", reqId, Util.UnixSecondsToString(tick.Time, "yyyyMMdd-HH:mm:ss"), Util.DoubleMaxString(tick.Price), Util.DecimalMaxString(tick.Size), tick.Exchange, tick.SpecialConditions, tick.TickAttribLast.ToString())
	Next
End Sub

 

Historical Halted and Unhalted ticks

The tick attribute pastLimit is also returned with streaming Tick-By-Tick responses. Check Halted and Unhalted ticks section.

  • If tick has zero price, zero size and pastLimit flag is set – this is “Halted” tick.
  • If tick has zero price, zero size and followed immediately after “Halted” tick – this is “Unhalted” tick.

Historical Date Formatting

When creating dates in the TWS API, Interactive Brokers typically supports three methods:

  1. Operator Time Zone
  2. Exchange Time Zone
  3. Coordinated Universal Time (UTC)

Operator Time Zone

Operator Time Zone is the local time set by the user in Trader Workstation. The Operator Time Zone typically maintains a unique formatting structure separate from Exchange Time Zones; however, they can match.

A user can confirm their Operator Time Zone by launching Trader Workstation then, before logging in, click “More Options >”.

tws login screen highlighting More Options button.

Users can then confirm their active Operator Time Zone by referencing the “Time Zone” field.

For US residents, this will typically appear as “America/New_York”, “America/Chicago”, or “America/Los_Angeles”. It is essential to note the Time Zone formatting here, as “America/Chicago” is treated differently than “US/Central” as a time zone.

All requests made can now be sent as “YYYYMMDD hh:mm:ss America/Chicago” to always send dates in Central time. This same rule goes for any alternative Time Zones, such as “America/Los_Angeles” or “America/New_York”.

Exchange Time Zone

The exchange Time Zone is the value the exchange itself uses to calculate time. This value is typically unique to the Operator Time Zone, but these values can overlap.

As an example, the New York Stock Exchange operates on “US/Eastern”. However, the CME operates on “US/Central”. This values can be programmatically requested using the EClient.reqContractDetails method, and then received from EWrapper.contractDetails in contractDetails.Time ZoneId.

Note that this will be interpreted differently from “America/Chicago”.

code Time Zone Display

Coordinated Universal Time (UTC)

UTC is a time standard centered around Greenwich Mean Time (GMT). UTC historical data can be formatted as “YYYYMMDD-hh:mm:ss”. Please keep in mind this is based on UTC+0, and as a reference, US/Eastern time is approximately UTC-4 or UTC-5 depending on U.S. Daylight savings.

Please note GMT is unaffected by Daylight savings, and so 09:00:00 will be the same time of day year round regardless of the exchange’s or your local daylight savings observation.

Modifying Returned Date

You may also log in to the Trader Workstation and modify this in the Global Configuration under API and then Settings. Here, you will find a modifiable setting labeled “Send instrument-specific attributes for dual-mode API client in” Here you can select one of the following:

  • operator timezone: refers to the local timezone you have set in the Trader Workstation or IB Gateway
  • instrument timezone: refers to the timezone of the requested exchange. If “SMART” is used, this will use the instrument’s primary exchange.
  • UTC format: refers to a standardized return using UTC as the timezone. This will be returned in the format YYYYMMDD-hh:mm:ss

Market Data: Live

Live Data Limitations

For all data, besides Delayed Watchlist Data, a paid data subscription is required to receive market data through the API. See the Market Data Subscriptions page for more information.

  • Live market data and historical bars are currently not available from the API for the exchange OSE. Only 15 minute delayed streaming data will be available for this exchange.

  • Some Available Tick Types may not be provided due to the contract details, the time that you run the code…… ,etc. To verify whether the specific Available Tick Type is provided, it is suggested to manually check the data in TWS.
  • Different Available Tick Types have different updating frequency.

The bid, ask, and last size quotes are displayed in shares instead of lots.

API users have the option to configure the TWS API to work in compatibility mode for older programs, but we recommend migrating to “quotes in shares” at your earliest convenience.

To display quotes as lots, from the Global Configuration > API > Settings page, check “Bypass US Stocks market data in shares warning for API orders.”

5 Second Bars

Real time and historical data functionality is combined through the EClient.reqRealTimeBars request. reqRealTimeBars will create an active subscription that will return a single bar in real time every five seconds that has the OHLC values over that period. reqRealTimeBars can only be used with a bar size of 5 seconds.

Important: real time bars subscriptions combine the limitations of both, top and historical market data. Make sure you observe Market Data Lines and Pacing Violations for Small Bars (30 secs or less). For example, no more than 60 *new* requests for real time bars can be made in 10 minutes, and the total number of active active subscriptions of all types cannot exceed the maximum allowed market data lines for the user.

Request Real Time Bars

EClient.reqRealTimeBars (

tickerId: int. Request identifier used to track data.

contract: Contract. The Contract object for which the depth is being requested

barSize: int. Currently being ignored

whatToShow: String. The nature of the data being retrieved:
Available Values: TRADES, MIDPOINT, BID, ASK

useRTH: int. Set to 0 to obtain the data which was also generated outside of the Regular Trading Hours, set to 1 to obtain only the RTH data
)

realTimeBarOptions: List<TagValue>. Internal use only.

 

Requests real time bars.

Only 5 seconds bars are provided. This request is subject to the same pacing as any historical data request: no more than 60 API queries in more than 600 seconds.

Real time bars subscriptions are also included in the calculation of the number of Level 1 market data subscriptions allowed in an account.

self.reqRealTimeBars(3001, contract, 5, "MIDPOINT", 0, [])

 

Code example:

from ibapi.client import *
from ibapi.wrapper import *
from ibapi.contract import Contract
import time

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

    def realtimeBar(self, reqId: TickerId, time:int, open_: float, high: float, low: float, close: float, volume: Decimal, wap: Decimal, count: int):
        print("RealTimeBar. TickerId:", reqId, RealTimeBar(time, -1, open_, high, low, close, volume, wap, count))
    
app = TradeApp()      
app.connect("127.0.0.1", 7496, clientId=1)

contract = Contract() 
contract.symbol = "AAPL" 
contract.secType = "STK" 
contract.currency = "USD" 
contract.exchange = "SMART" 

app.reqRealTimeBars(3001, contract, 5, "TRADES", 0, [])

app.run()

 

client.reqRealTimeBars(3001, contract, 5, "MIDPOINT", true, null);

 

m_pClient->reqRealTimeBars(3001, contract, 5, "MIDPOINT", true, TagValueListSPtr());

 

client.reqRealTimeBars(3001, contract, 5, "MIDPOINT", true, null);

 

client.reqRealTimeBars(3001, contract, 5, "MIDPOINT", True, Nothing)

 

Receive Real Time Bars

EWrapper.realtimeBar (

reqId: int. Request identifier used to track data.

time: long. The bar’s start date and time (Epoch/Unix time)

open: double. The bar’s open point

high: double. The bar’s high point

low: double. The bar’s low point

close: double. The bar’s closing point

volume: decimal. The bar’s traded volume (only returned for TRADES data)

WAP: decimal. The bar’s Weighted Average Price rounded to minimum increment (only available for TRADES).

count: int. The number of trades during the bar’s timespan (only available for TRADES).
)

Receives the real time 5 second bars.

def realtimeBar(self, reqId: TickerId, time:int, open_: float, high: float, low: float, close: float, volume: Decimal, wap: Decimal, count: int):
	print("RealTimeBar. TickerId:", reqId, RealTimeBar(time, -1, open_, high, low, close, volume, wap, count))

 

@Override
public void realtimeBar(int reqId, long time, double open, double high, double low, double close, Decimal volume, Decimal wap, int count) {
	System.out.println("RealTimeBar: " + EWrapperMsgGenerator.realtimeBar(reqId, time, open, high, low, close, volume, wap, count));
}

 

void TestCppClient::realtimeBar(TickerId reqId, long time, double open, double high, double low, double close, Decimal volume, Decimal wap, int count) {
    printf( "RealTimeBars. %ld - Time: %s, Open: %s, High: %s, Low: %s, Close: %s, Volume: %s, Count: %s, WAP: %sn", reqId, Utils::longMaxString(time).c_str(), Utils::doubleMaxString(open).c_str(), Utils::doubleMaxString(high).c_str(), Utils::doubleMaxString(low).c_str(), Utils::doubleMaxString(close).c_str(), decimalStringToDisplay(volume).c_str(), Utils::intMaxString(count).c_str(), decimalStringToDisplay(wap).c_str());
}

 

public virtual void realtimeBar(int reqId, long time, double open, double high, double low, double close, decimal volume, decimal WAP, int count)
{
	Console.WriteLine("RealTimeBars. " + reqId + " - Time: " + Util.LongMaxString(time) + ", Open: " + Util.DoubleMaxString(open) + ", High: " + Util.DoubleMaxString(high) +  ", Low: " + Util.DoubleMaxString(low) + ", Close: " + Util.DoubleMaxString(close) + ", Volume: " + Util.DecimalMaxString(volume) + ", Count: " + Util.IntMaxString(count) + ", WAP: " + Util.DecimalMaxString(WAP));
}

 

Public Sub realtimeBar(reqId As Integer, time As Long, open As Double, high As Double, low As Double, close As Double, volume As Decimal, WAP As Decimal, count As Integer) Implements IBApi.EWrapper.realtimeBar
	Console.WriteLine("RealTimeBars. " & reqId & " - Time: " & Util.LongMaxString(time) & ", Open: " & Util.DoubleMaxString(open) & ", High: " & Util.DoubleMaxString(high) & ", Low: " & Util.DoubleMaxString(low) & ", Close: " & Util.DoubleMaxString(close) & ", Volume: " & Util.DecimalMaxString(volume) & ", Count: " & Util.IntMaxString(count) & ", WAP: " & Util.DecimalMaxString(WAP))
End Sub

 

Cancel Real Time Bars

EClient.cancelRealTimeBars (

tickerId: int. Request identifier used to track data.
)

Cancels Real Time Bars’ subscription.

self.cancelRealTimeBars(3001)

 

client.cancelRealTimeBars(3001);

 

m_pClient->cancelRealTimeBars(3001);

 

client.cancelRealTimeBars(3001);

 

client.cancelRealTimeBars(3001)

 

Component Exchanges

A single data request from the API can receive aggregate quotes from multiple exchanges. The tick types ‘bidExch’ (tick type 32), ‘askExch’ (tick type 33), ‘lastExch’ (tick type 84) are used to identify the source of a quote. To preserve bandwidth, the data returned to these tick types consists of a sequence of capital letters rather than a long list of exchange names for every returned exchange name field. To find the full exchange name corresponding to a single letter code returned in tick types 32, 33, or 84, and API function IBApi::EClient::reqSmartComponents is available. Note: This function can only be used when the exchange is open.

Different IB contracts have a different exchange map containing the set of exchanges on which they trade. Each exchange map has a different code, such as “a6” or “a9”. This exchange mapping code is returned to EWrapper.tickReqParams immediately after a market data request is made by a user with market data subscriptions. To find a particular map of single letter codes to full exchange names, the function reqSmartComponents is invoked with the exchange mapping code returned to tickReqParams.

For instance, a market data request for the IBKR US contract may return the exchange mapping identifier “a6” to EWrapper.tickReqParams . Invoking the function EClient.reqSmartComponents with the symbol “a9” will reveal the list of exchanges offering market data for the IBKR US contract, and their single letter codes. The code for “ARCA” may be “P”. In that case if “P” is returned to the exchange tick types, that would indicate the quote was provided by ARCA.

Request Component Exchanges

EClient.reqSmartComponents (

reqId: int. Request identifier used to track data.

bboExchange: String. Mapping identifier received from EWrapper.tickReqParams
)

Returns the mapping of single letter codes to exchange names given the mapping identifier.

self.reqSmartComponents(1018, "a6")

 

client.reqSmartComponents(1013, "a6");

 

m_pClient->reqSmartComponents(13002, m_bboExchange);

 

client.reqSmartComponents(13002, testImpl.BboExchange);

 

client.reqSmartComponents(13002, wrapperImpl.BboExchange)

 

Receive Component Exchanges

EWrapper.smartComponents (

reqId: int. Request identifier used to track data.

smartComponentMap: SmartComponentMap. Unique object containing a map of all key-value pairs
)

Containing a bit number to exchange + exchange abbreviation dictionary. All IDs can be initially retrieved using reqTickParams.

def smartComponents(self, reqId:int, smartComponentMap:SmartComponentMap):
	print("SmartComponents:")
	for smartComponent in smartComponentMap:
		print("SmartComponent.", smartComponent)

 

@Override
public void smartComponents(int reqId, Map<Integer, Entry> theMap) {
	System.out.println(EWrapperMsgGenerator.smartComponents(reqId, theMap));
}

 

void TestCppClient::smartComponents(int reqId, const SmartComponentsMap& theMap) {
    printf("Smart components: (%lu):n", theMap.size());
    for (SmartComponentsMap::const_iterator i = theMap.begin(); i != theMap.end(); i++) {
        printf(" bit number: %d exchange: %s exchange letter: %cn", i->first, std::get(i->second).c_str(), std::get(i->second));
    }
}

 

public void smartComponents(int reqId, Dictionary<int, KeyValuePair> theMap)
{
	StringBuilder sb = new StringBuilder();
	sb.AppendFormat("==== Smart Components Begin (total={0}) reqId = {1} ====n", theMap.Count, reqId);
	foreach (var item in theMap)
	{
		sb.AppendFormat("bit number: {0}, exchange: {1}, exchange letter: {2}n", item.Key, item.Value.Key, item.Value.Value);
	}
	sb.AppendFormat("==== Smart Components Begin (total={0}) reqId = {1} ====n", theMap.Count, reqId);
	Console.WriteLine(sb);
}

 

Public Sub smartComponents(reqId As Integer, theMap As Dictionary(Of Integer, KeyValuePair(Of String, Char))) Implements EWrapper.smartComponents
	Dim sb As New StringBuilder
	sb.AppendFormat("==== Smart Components Begin (total={0}) reqId = {1} ===={2}", theMap.Count, reqId, Environment.NewLine)
	For Each item In theMap
		sb.AppendFormat("bit number: {0}, exchange: {1}, exchange letter: {2}{3}", item.Key, item.Value.Key, item.Value.Value, Environment.NewLine)
	Next
	sb.AppendFormat("==== Smart Components Begin (total={0}) reqId = {1} ===={2}", theMap.Count, reqId, Environment.NewLine)
	Console.WriteLine(sb)
End Sub

 

Market Depth Exchanges

To check which exchanges offer deep book data, the function EClient.reqMktDepthExchanges can be invoked. It will return a list of exchanges from where market depth is available if the user has the appropriate market data subscription.

API ‘Exchange’ fields for which a market depth request would return market maker information and result in a callback to EWrapper.updateMktDepthL2 will be indicated in the results from the EWrapper.mktDepthExchanges field by a ‘True’ value in the ‘isL2’ field:

Requesting Market Depth Exchanges

EClient.reqMktDepthExchanges ()

Requests venues for which market data is returned to updateMktDepthL2 (those with market makers).

self.reqMktDepthExchanges()

 

client.reqMktDepthExchanges();

 

m_pClient->reqMktDepthExchanges();

 

client.reqMktDepthExchanges();

 

client.reqMktDepthExchanges()

 

Receive Market Depth Exchanges

EWrapper.mktDepthExchanges (

depthMktDataDescriptions: DepthMktDataDescription[]. A list containing all available exchanges offering market depth.
)

Called when receives Depth Market Data Descriptions.

def mktDepthExchanges(self, depthMktDataDescriptions:ListOfDepthExchanges):
	print("MktDepthExchanges:")
	for desc in depthMktDataDescriptions:
		print("DepthMktDataDescription.", desc)

 

@Override
public void mktDepthExchanges(DepthMktDataDescription[] depthMktDataDescriptions) {
	System.out.println(EWrapperMsgGenerator.mktDepthExchanges(depthMktDataDescriptions));
}

 

void TestCppClient::mktDepthExchanges(const std::vector &depthMktDataDescriptions) {
	printf("Mkt Depth Exchanges (%lu):n", depthMktDataDescriptions.size());
	for (unsigned int i = 0; i < depthMktDataDescriptions.size(); i++) {
		printf("Depth Mkt Data Description [%d] - exchange: %s secType: %s listingExch: %s serviceDataType: %s aggGroup: %sn", i, depthMktDataDescriptions[i].exchange.c_str(), depthMktDataDescriptions[i].secType.c_str(), depthMktDataDescriptions[i].listingExch.c_str(), depthMktDataDescriptions[i].serviceDataType.c_str(), Utils::intMaxString(depthMktDataDescriptions[i].aggGroup).c_str());
	}
}

 

public void mktDepthExchanges(DepthMktDataDescription[] depthMktDataDescriptions)
{
	Console.WriteLine("Market Depth Exchanges:");
	foreach (var depthMktDataDescription in depthMktDataDescriptions)
	{
		Console.WriteLine("Depth Market Data Description: Exchange: {0}, Security Type: {1}, Listing Exch: {2}, Service Data Type: {3}, Agg Group: {4}", depthMktDataDescription.Exchange, depthMktDataDescription.SecType, depthMktDataDescription.ListingExch, depthMktDataDescription.ServiceDataType, Util.IntMaxString(depthMktDataDescription.AggGroup));
	}
}

 

Public Sub mktDepthExchanges(depthMktDataDescriptions As DepthMktDataDescription()) Implements EWrapper.mktDepthExchanges
	Console.WriteLine("Market Depth Exchanges:")
	For Each depthMktDataDescription In depthMktDataDescriptions
		Console.WriteLine("Depth Market Data Descriprion. Exchange: " & depthMktDataDescription.Exchange & " Security Type: " & depthMktDataDescription.SecType & " Listing Exch: " & depthMktDataDescription.ListingExch & " Service Data Type: " & depthMktDataDescription.ServiceDataType & "  Agg Group: " & Util.IntMaxString(depthMktDataDescription.AggGroup))
	Next
End Sub

 

Market Depth (L2)

Market depth data, also known as level II, represents an instrument’s order book. Via the TWS API it is possible to obtain this information with the EClient.reqMarketDepth function. Unlike Top Market Data (Level I), market depth data is sent without sampling nor filtering, however we cannot guarantee that every price quoted for a particular security will be displayed when you invoke EClient.reqMarketDepth.

In particular, odd lot orders are not included.

It is possible to Smart-route a EClient.reqMarketDepth request to receive aggregated data from all available exchanges, similar to the TWS BookTrader display.

An integral part of processing the incoming data is monitoring EWrapper::error for message 317 “Market depth data has been RESET. Please empty deep book contents before applying any new entries.” and handling it appropriately, otherwise the update process would be corrupted.

Market Depth is not support for Calendar Spreads or Combos.

Request Market Depth

Important: Please note that the languages use different method names for requesting market depth.

The C# and Visual Basic APIs use reqMarketDepth().

The Python, Java, and C++ APIs use reqMktDepth().

EClient.reqMarketDepth (

tickerId: int. Request identifier used to track data.

contract: Contract. The Contract for which the depth is being requested.

numRows: int. The number of rows on each side of the order book.

isSmartDepth: bool. Flag indicates that this is smart depth request.

mktDepthOptions: List. Internal use only. Leave an empty array.
)

Requests the contract’s market depth (order book).

self.reqMktDepth(2001, contract, 5, False, [])

 

client.reqMktDepth(2001, contract, 5, false, null);

 

m_pClient->reqMktDepth(2001, contract, 5, false, TagValueListSPtr());

 

client.reqMarketDepth(2001, contract, 5, false, null);

 

client.reqMarketDepth(2001, contract, 5, False, Nothing)

 

Receive Market Depth

EWrapper.updateMktDepth (

tickerId: int. Request identifier used to track data.

position: int. The order book’s row being updated

operation: int. Indicates a change in the row’s value.:

  • 0 = insert (insert this new order into the row
    identified by ‘position’)·
  • 1 = update (update the existing order in the row identified by
    ‘position’)·
  • 2 = delete (delete the existing order at the row identified by ‘position’).

side: int. 0 for ask, 1 for bid

price: double. The order’s price

size: decimal. The order’s size
)

Returns the order book. Used for direct routed requests only.

def updateMktDepth(self, reqId: TickerId, position: int, operation: int, side: int, price: float, size: Decimal):
		print("UpdateMarketDepth. ReqId:", reqId, "Position:", position, "Operation:", operation, "Side:", side, "Price:", floatMaxString(price), "Size:", decimalMaxString(size))

 

@Override
public void updateMktDepth(int tickerId, int position, int operation, int side, double price, Decimal size) {
	System.out.println(EWrapperMsgGenerator.updateMktDepth(tickerId, position, operation, side, price, size));
}

 

void TestCppClient::updateMktDepth(TickerId id, int position, int operation, int side, double price, Decimal size) {
    printf( "UpdateMarketDepth. %ld - Position: %s, Operation: %d, Side: %d, Price: %s, Size: %sn", id, Utils::intMaxString(position).c_str(), operation, side, Utils::doubleMaxString(price).c_str(), decimalStringToDisplay(size).c_str());
}

 

public virtual void updateMktDepth(int tickerId, int position, int operation, int side, double price, decimal size)
{
	Console.WriteLine("UpdateMarketDepth. " + tickerId + " - Position: " + position + ", Operation: " + operation + ", Side: " + side + ", Price: " + Util.DoubleMaxString(price) + ", Size: " + Util.DecimalMaxString(size));
}

 

Public Sub updateMktDepth(tickerId As Integer, position As Integer, operation As Integer, side As Integer, price As Double, size As Decimal) Implements IBApi.EWrapper.updateMktDepth
	Console.WriteLine("UpdateMarketDepth. " & CStr(tickerId) & " - Position: " & CStr(position) & ", Operation: " & CStr(operation) & ", Side: " & CStr(side) & ", Price: " & Util.DoubleMaxString(price) & ", Size: " & Util.DecimalMaxString(size))
End Sub

 

EWrapper.updateMktDepthL2 (

tickerId: int. Request identifier used to track data.

position: int. The order book’s row being updated.

marketMaker: String. The exchange holding the order if isSmartDepth is True, otherwise the MPID of the market maker.

operation: int. Indicates a change in the row’s value.:

  • 0 = insert (insert this new order into the row
    identified by ‘position’)·
  • 1 = update (update the existing order in the row identified by
    ‘position’)·
  • 2 = delete (delete the existing order at the row identified by ‘position’).

side: int. 0 for ask, 1 for bid

price: double. The order’s price

size: decimal. The order’s size

isSmartDepth: bool. Flag indicating if this is smart depth response
)

Returns the order book. Used for direct routed requests only.

def updateMktDepthL2(self, reqId: TickerId, position: int, marketMaker: str, operation: int, side: int, price: float, size: Decimal, isSmartDepth: bool):
	print("UpdateMarketDepthL2. ReqId:", reqId, "Position:", position, "MarketMaker:", marketMaker, "Operation:", operation, "Side:", side, "Price:", floatMaxString(price), "Size:", decimalMaxString(size), "isSmartDepth:", isSmartDepth)

 

@Override
public void updateMktDepthL2(int tickerId, int position, String marketMaker, int operation, int side, double price, Decimal size, boolean isSmartDepth) {
	System.out.println(EWrapperMsgGenerator.updateMktDepthL2( tickerId, position, marketMaker, operation, side, price, size, isSmartDepth));
}

 

void TestCppClient::updateMktDepthL2(TickerId id, int position, const std::string& marketMaker, int operation, int side, double price, Decimal size, bool isSmartDepth) {
    printf( "UpdateMarketDepthL2. %ld - Position: %s, Operation: %d, Side: %d, Price: %s, Size: %s, isSmartDepth: %dn", id, Utils::intMaxString(position).c_str(), operation, side, Utils::doubleMaxString(price).c_str(), decimalStringToDisplay(size).c_str(), isSmartDepth);
}

 

public virtual void updateMktDepthL2(int tickerId, int position, string marketMaker, int operation, int side, double price, decimal size, bool isSmartDepth)
{
	Console.WriteLine("UpdateMarketDepthL2. " + tickerId + " - Position: " + position + ", Operation: " + operation + ", Side: " + side + ", Price: " + Util.DoubleMaxString(price) + ", Size: " + Util.DecimalMaxString(size) + ", isSmartDepth: " + isSmartDepth);
}

 

Public Sub updateMktDepthL2(tickerId As Integer, position As Integer, marketMaker As String, operation As Integer, side As Integer, price As Double, size As Decimal, isSmartDepth As Boolean) Implements IBApi.EWrapper.updateMktDepthL2
	Console.WriteLine("UpdateMarketDepthL2. " & CStr(tickerId) & " MarketMaker: " & marketMaker & ", Position: " & CStr(position) & ", Operation: " & CStr(operation) & ", Side: " & CStr(side) & ", Price: " & Util.DoubleMaxString(price) & ", Size: " & Util.DecimalMaxString(size) & ", isSmartDepth: " & CStr(isSmartDepth))
End Sub

 

Cancel Market Depth

EClient.cancelMarketDepth (

tickerId: int. Request identifier used to track data.

isSmartDepth: bool. Flag indicates that this is smart depth request.

)

Cancel’s market depth’s request.

self.cancelMktDepth(2001, False)

 

client.cancelMktDepth(2001, false);

 

m_pClient->cancelMktDepth(2001, false);

 

client.cancelMktDepth(2001, false);

 

client.cancelMktDepth(2001, False)

 

Options Greeks

The option greek values- delta, gamma, theta, vega- are returned by default following a reqMktData() request for the option. See Available Tick Types

Tick types “Bid Option Computation” (#10), “Ask Option Computation” (#11), “Last Option Computation” (#12), and “Model Option Computation” (#13) return all Greeks (delta, gamma, vega, theta), the underlying price and the stock and option reference price when requested.

MODEL_OPTION_COMPUTATION also returns model implied volatility.

Note that to receive live greek values it is necessary to have market data subscriptions for both the option and the underlying contract.

The implied volatility for an option given its price and the price of the underlying can be calculated with the function EClient.calculateImpliedVolatility.

Alternatively, given the price of the underlying and an implied volatility it is possible to calculate the option price using the function EClient.calculateOptionPrice.

After the request, the option specific information will be delivered via the EWrapper.tickOptionComputation method.

Request Options Greeks

EClient.reqMktData (

reqId: int. Request identifier for tracking data.

contract: Contract. Contract object used for specifying an instrument.

genericTickList: String. Comma separated ids of the available generic ticks.

snapshot: bool. Set to True for snapshot data with a relevant subscription or False for live data.

regulatorySnapshot: bool. Set to True for a paid, regulatory snapshot or False for live data.

mktDataOptions: List<TagValue>. Internal use only.
)

As long as the data is requested on an Option contract, greeks will be requested automatically if underlying market data is already subscribed.

self.reqMktData(reqId, OptionContract, "", False, False, [])

Code example:

from ibapi.client import *
from ibapi.wrapper import *
from ibapi.contract import Contract
import threading
import time

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

    def tickGeneric(self, reqId: TickerId, tickType: TickType, value: float):
        print("TickGeneric. TickerId:", reqId, "TickType:", tickType, "Value:", floatMaxString(value))

    def tickPrice(self, reqId: TickerId, tickType: TickType, price: float, attrib: TickAttrib):
        print(reqId, tickType, price, attrib)

    def tickSize(self, reqId: TickerId, tickType: TickType, size: Decimal):
        print("TickSize. TickerId:", reqId, "TickType:", tickType, "Size: ", decimalMaxString(size))

    def tickString(self, reqId: TickerId, tickType: TickType, value: str):
        print("TickString. TickerId:", reqId, "Type:", tickType, "Value:", value)

    def tickReqParams(self, tickerId:int, minTick:float, bboExchange:str, snapshotPermissions:int):
        print("TickReqParams. TickerId:", tickerId, "MinTick:", floatMaxString(minTick), "BboExchange:", bboExchange, "SnapshotPermissions:", intMaxString(snapshotPermissions))

    def tickOptionComputation(self, reqId: TickerId, tickType: TickType, tickAttrib: int, impliedVol: float, delta: float, optPrice: float, pvDividend: float, gamma: float, vega: float, theta: float, undPrice: float):
        print("TickOptionComputation. TickerId:", reqId, "TickType:", tickType, "TickAttrib:", intMaxString(tickAttrib), "ImpliedVolatility:", floatMaxString(impliedVol), "Delta:", floatMaxString(delta), "OptionPrice:", floatMaxString(optPrice), "pvDividend:", floatMaxString(pvDividend), "Gamma: ", floatMaxString(gamma), "Vega:", floatMaxString(vega), "Theta:", floatMaxString(theta), "UnderlyingPrice:", floatMaxString(undPrice))

def websocket_con():
    app.run()
    
app = TradeApp()      
app.connect("127.0.0.1", 7496, clientId=1)

con_thread = threading.Thread(target=websocket_con, daemon=True)
con_thread.start()

time.sleep(1) 

contract = Contract()
contract.symbol = "AAPL"
contract.secType = "OPT"
contract.exchange = "SMART"
contract.currency = "USD"
contract.lastTradeDateOrContractMonth = 20240621
contract.strike = 200
contract.right = "C"
contract.multiplier = 100

app.reqMarketDataType(1)
app.reqMktData(102, contract, "", False, False, [])
client.reqMktData(reqId, OptionContract, "", false, false, null);

 

m_pClient->reqMktData(reqId, OptionContract, "", false, false, TagValueListSPtr());

 

client.reqMktData(reqId, OptionContract, "", false, false, null);

 

client.reqMktData(reqId, OptionContract, "", False, False, Nothing)

 

Calculating option prices

EClient.calculateOptionPrice (

reqId: int. Request identifier used to track data.

contract: Contract. The Contract object for which the depth is being requested

volatility: double. Hypothetical volatility.

underPrice: double. Hypothetical option’s underlying price.

optionPriceOptions: List<TagValue>. Internal use only. Send an empty tag value list.
)

Calculates an option’s price based on the provided volatility and its underlying’s price.

self.calculateImpliedVolatility(5001, OptionContract, 0.5, 55, [])

 

client.calculateImpliedVolatility(5001, OptionContract, 0.6, 55, null);

 

m_pClient->calculateImpliedVolatility(5001, OptionContract, 0.5, 55, TagValueListSPtr());

 

client.calculateImpliedVolatility(5001, OptionContract, 0.5, 55, null);

 

client.calculateImpliedVolatility(5001, OptionContract, 0.5, 55, Nothing)

 

Calculating historical volatility

EClient.calculateImpliedVolatility (

reqId: int. Request identifier used to track data.

contract: Contract. The Contract object for which the depth is being requested

optionPrice: double. Hypothetical option price.

underPrice: double. Hypothetical option’s underlying price.

impliedVolatilityOptions: List<TagValue>. Internal use only. Send an empty tag value list.
)

Calculate the volatility for an option. Request the calculation of the implied volatility based on hypothetical option and its underlying prices.

self.calculateOptionPrice(5002, OptionContract, 0.6, 55, [])

 

client.calculateOptionPrice(5002, OptionContract, 0.5, 55, null);

 

m_pClient->calculateOptionPrice(5002, OptionContract, 0.6, 55, TagValueListSPtr());

 

client.calculateOptionPrice(5002, OptionContract, 0.6, 55, null);

 

client.calculateOptionPrice(5002, OptionContract, 0.6, 55, Nothing)

 

Receiving Options Data

EWrapper.tickOptionComputation (

tickerId the request’s unique identifier.

field: int. Specifies the type of option computation.
Pass the field value into
TickType.getField(int tickType) to retrieve the field description. For example, a field value of 13 will map to modelOptComp, etc. 10 = Bid 11 = Ask 12 = Last

tickAttrib: int. 0 – return based, 1- price based.

impliedVolatility: double. the implied volatility calculated by the TWS option modeler, using the specified tick type value.

delta: double. The option delta value.

optPrice: double. The option price.

pvDividend: double. The present value of dividends expected on the option’s underlying.

gamma: double. The option gamma value.

vega: double. The option vega value.

theta: double. The option theta value.

undPrice: double. The price of the underlying.
)

Receives option specific market data. This method is called when the market in an option or its underlier moves. TWS’s option model volatilities, prices, and deltas, along with the present value of dividends expected on that options underlier are received.

def tickOptionComputation(self, reqId: TickerId, tickType: TickType, tickAttrib: int, impliedVol: float, delta: float, optPrice: float, pvDividend: float, gamma: float, vega: float, theta: float, undPrice: float):
	print("TickOptionComputation. TickerId:", reqId, "TickType:", tickType, "TickAttrib:", intMaxString(tickAttrib), "ImpliedVolatility:", floatMaxString(impliedVol), "Delta:", floatMaxString(delta), "OptionPrice:", floatMaxString(optPrice), "pvDividend:", floatMaxString(pvDividend), "Gamma: ", floatMaxString(gamma), "Vega:", floatMaxString(vega), "Theta:", floatMaxString(theta), "UnderlyingPrice:", floatMaxString(undPrice))

 

@Override
public void tickOptionComputation(int tickerId, int field, int tickAttrib, double impliedVol, double delta, double optPrice,
		double pvDividend, double gamma, double vega, double theta, double undPrice) {
	System.out.println("TickOptionComputation: " + EWrapperMsgGenerator.tickOptionComputation( tickerId, field, tickAttrib, impliedVol, delta, optPrice, pvDividend, gamma, vega, theta, undPrice));
}

 

void TestCppClient::tickOptionComputation( TickerId tickerId, TickType tickType, int tickAttrib, double impliedVol, double delta, double optPrice, double pvDividend, double gamma, double vega, double theta, double undPrice) {
    printf( "TickOptionComputation. Ticker Id: %ld, Type: %d, TickAttrib: %s, ImpliedVolatility: %s, Delta: %s, OptionPrice: %s, pvDividend: %s, Gamma: %s, Vega: %s, Theta: %s, Underlying Price: %sn", tickerId, (int)tickType, Utils::intMaxString(tickAttrib).c_str(), Utils::doubleMaxString(impliedVol).c_str(), Utils::doubleMaxString(delta).c_str(), Utils::doubleMaxString(optPrice).c_str(), Utils::doubleMaxString(pvDividend).c_str(), Utils::doubleMaxString(gamma).c_str(), Utils::doubleMaxString(vega).c_str(), Utils::doubleMaxString(theta).c_str(), Utils::doubleMaxString(undPrice).c_str());
}

 

public virtual void tickOptionComputation(int tickerId, int field, int tickAttrib, double impliedVolatility, double delta, double optPrice, double pvDividend, double gamma, double vega, double theta, double undPrice)
{
	Console.WriteLine("TickOptionComputation. TickerId: " + tickerId + ", field: " + field + ", TickAttrib: " + Util.IntMaxString(tickAttrib) + ", ImpliedVolatility: " + Util.DoubleMaxString(impliedVolatility) + ", Delta: " + Util.DoubleMaxString(delta) + ", OptionPrice: " + Util.DoubleMaxString(optPrice) +", pvDividend: " + Util.DoubleMaxString(pvDividend) + ", Gamma: " + Util.DoubleMaxString(gamma) + ", Vega: " + Util.DoubleMaxString(vega) + ", Theta: " + Util.DoubleMaxString(theta) + ", UnderlyingPrice: " + Util.DoubleMaxString(undPrice));
}

 

Public Sub tickOptionComputation(tickerId As Integer, field As Integer, tickAttrib As Integer, impliedVolatility As Double, delta As Double, optPrice As Double, pvDividend As Double, gamma As Double, vega As Double, theta As Double, undPrice As Double) Implements IBApi.EWrapper.tickOptionComputation
	Console.WriteLine("TickOptionComputation. TickerId: " & tickerId & ", field: " & field & ", TickAttrib: " & Util.IntMaxString(tickAttrib) & ", ImpliedVolatility: " & Util.DoubleMaxString(impliedVolatility) & ", Delta: " & Util.DoubleMaxString(delta) & ", OptionPrice: " & Util.DoubleMaxString(optPrice) & ", pvDividend: " & Util.DoubleMaxString(pvDividend) & ", Gamma: " & Util.DoubleMaxString(gamma) & ", Vega: " & Util.DoubleMaxString(vega) & ", Theta: " & Util.DoubleMaxString(theta) & ", UnderlyingPrice: " & Util.DoubleMaxString(undPrice))
End Sub

 

Top of Book (L1)

Streaming market data values corresponding to data shown in TWS watchlists is available via the EClient.reqMktData. This data is not tick-by-tick but consists of aggregate snapshots taken several times per second. A set of ‘default’ tick types are returned by default from a call to EClient.reqMktData, and additional tick types are available by specifying the corresponding generic tick type in the market data request. Including the generic tick types many, but not all, types of data are available that can be displayed in TWS watchlists by adding additional columns.

Using the TWS API, you can request real time market data for trading and analysis. From the API, market data returned from the function IBApi.EClient.reqMktData corresponds to market data displayed in TWS watchlists. This data is not tick-by-tick but consists of aggregated snapshots taken at intra-second intervals which differ depending on the type of instrument:

Product Frequency
Stocks, Futures and others 250 ms
US Options 100 ms
FX pairs 5 ms

Request Watchlist Data

EClient.reqMktData (

reqId: int. Request identifier for tracking data.

contract: Contract. Contract object used for specifying an instrument.

genericTickList: String. Comma separated ids of the available generic ticks.

snapshot: bool. Used to retrieve a single snapshot of data for those with an existing market data subscirption.

regulatorySnapshot: bool. Used to retrieve a single snapshot of paid data. Each snapshot costs $0.01.

mktDataOptions: List<TagValue>. Internal use only.
)

Requests real time market data. Returns market data for an instrument either in real time or 10-15 minutes delayed data.

self.reqMktData(reqId, contract, "", False, False, [])

 

client.reqMktData(reqId, contract, "", false, false, null);

 

m_pClient->reqMktData(reqId, contract, "", false, false, TagValueListSPtr());

 

client.reqMktData(reqId, contract, "", false, false, null);

 

client.reqMktData(reqId, contract, "", False, False, Nothing)

 

Generic Tick Types

The most common tick types are delivered automatically after a successful market data request. There are however other tick types available by explicit request: the generic tick types. When invoking IBApi.EClient.reqMktData, specific generic ticks can be requested via the genericTickList parameter of the function:

See the Available Tick Types section for more information on generic ticks.

Streaming Data Snapshots

With an exchange market data subscription, such as Network A (NYSE), Network B(ARCA), or Network C(NASDAQ) for US stocks, it is possible to request a snapshot of the current state of the market once instead of requesting a stream of updates continuously as market values change. By invoking the EClient.reqMktData function passing in true for the snapshot parameter, the client application will receive the currently available market data once before a EWrapper.tickSnapshotEnd event is sent 11 seconds later. Snapshot requests can only be made for the default tick types; no generic ticks can be specified. It is important to note that a snapshot request will only return available data over the 11 second span; in some cases values may not be returned for all tick types.

EWrapper.tickSnapshotEnd (

tickerId: int. Request identifier used to track data.
)

When requesting market data snapshots, this market will indicate the snapshot reception is finished. Expected to occur 11 seconds after beginning of request.