Investing in financial products involves risk to your capital.

Close Navigation
Learn more about IBKR accounts

Trader Workstation (TWS) API

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. 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

Requirements

  • 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.

How To Find The API

It is important to know that the TWS API is only available through the interactivebrokers.github.io MSI or ZIP file. All other resources, 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.

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 is designed to accept up to fifty messages per second coming from the client side. Anything coming from the client application to the TWS 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 were all connected client applications to the same instance of TWS 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.

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.

Intel® Decimal Floating-Point Math Library

This product includes Intel® Decimal Floating-Point Math Library (in binary form) developed by the Intel Corporation under its license which can be found here.

Configure TWS / IBG for API Connectivity

  1. Log in to the Trader Workstation or IB Gateway
  2. Open the Global Configuration by selecting the Cog Wheel icon in the top right corner

  3. On the left, select API and then Settings
  4. At a minimum, you will need to maintain these settings:
    • “Enable ActiveX and Socket Clients” must be checked
    • “Read-only API” should be unchecked
    • Unless you are interested in modifying each request or the base code, we would advise setting your Socket port to 7496
  5. This will let you get started; however, there are some option settings we would encourage you to enable:
    • “Create API message log file” should be checked
    • “Include market data in API log file” should be checked
    • “Logging Level” should be changed from “Error” to “Detail”

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.

Updating The Python IDE

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

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 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.

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 -> Account -> 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 a EWrapper implementation so they can 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.

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)

 

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)

 

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)

 

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()

 

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", "")

 

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)

 

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", "")

 

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.

{TWS API}sourcepythonclientibapicontract.py

{TWS API}sourceJavaClientcomibclientContract.java

{TWS API}sourceCppClientclientContract.h

{TWS API}sourceCSharpClientclientContract.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.

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):
  printinstance(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 reqContractDetails. If an option contract is incompletely defined (for instance with the strike undefined) and used as an argument to IBApi::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 IBApi::EClient::reqSecDefOptParams was introduced that does not have the throttling limitation.

  • It is not recommended to use reqContractDetails to receive complete option chains on an underlying, e.g. all combinations of strikes/rights/expiries.
  • For very large option chains returned from 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.

IBApi::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 IBApi::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 IBApi.EWrapper.error method. The IBApi.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”.

Advanced order rejection

Order advancedErrorOverride and EWrapper.error advancedOrderRejectJson properties.

  • advancedErrorOverride accepts a comma-separated list with parameters containing error tags. This list will override the mentioned errors and proceed with the order placement.
  • advancedOrderRejectJson returns order reject description in JSON format. The JSON responses can be used to add fields to advancedErrorOverride.
    The response your API client will receive from our back end via reject message will contain a FIX Tag 8230. This FIX Tag is for order rejection message.
    For example, the response will contain code 8229=IBDBUYTX which can be passed in 8229 (advancedErrorOverride) field in IBApi::EClient::placeOrder method.
    The tag values of 8229 can contain a comma-separated list of advanced error override codes. For example, 8229=IBDBUYTX,MOBILEPH, will override both of the rejections.
  • Additionally, a new API Setting has been introduced: Show advanced order reject in UI always
    If checked, the order reject will not be sent to API.

Error Message Codes

For a full list of all available error codes from the TWS API, please visit our TWS API Error Messages page.

Receive Error Messages

EWrapper.error(

reqId: int. The request identifier which generated the error. Note: -1 will indicate a notification and not true error condition.

errorCode: int. The code identifying the error.

errorMsg: String. The error’s description.

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

See the TWS Error Codes section for more details on specific error messages.

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

Allocation Methods and Groups

A number of methods and profiles are available with Financial Advisor and IBroker account structures to specify how trades should be distributed across multiple accounts. This functionality allows for trades to be placed across multiple accounts. The API has the same functionality available as TWS.

Group and Profile order allocation methods for Financial Advisor Accounts can be created directly in TWS: Allocations and Transfers. After the initial creation, modifications can be made through the IBApi.EClient.replaceFA() method via the API directly.

As suggested from the method names below, a Group will distribute the order based on inherent properties such as the account’s liquidation value or equity whereas a Profile will offer the possibility to assign the allocated proportion based on explicit ratios or percentages.

Note: There is an API setting which merges groups and profiles, where both allocation methods are considered groups. See Unification of Groups and Profiles

Allocation by Group

EqualQuantity

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.

NetLiq

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.

AvailableEquity

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.

PctChange

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.

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

Allocation by Profile

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

Profile Methods Type Number
Percentages 1
Financial Ratios 2
Shares 3

Percentages

This method will split the total number of shares in the order between listed accounts based on the percentages you indicate. For example, an order for 1000 shares using a profile with four accounts at 25% each would allocate 250 shares to each listed account in the profile.

Financial Ratios

This method calculates the allocation of shares based on the ratios you enter. For example, an order for 1000 shares using a profile with four accounts set to a ratio of 4, 2, 1, 1 would allocate 500, 250, 125 and 125 shares to the listed accounts, respectively.

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.

Managing Groups and Profiles from the API

Customers are able to manage their existing allocation groups from the TWS API.

Important: While the API is able to modify these groups and profiles, the API is unable to create them. See the TWS Allocations and Transfers section of our guides for more information.

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)

 

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. See FA Data Types

xml: String. XML configuration for allocation profiles or group. See ReplaceFA XML Structure 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 XML Structure

The structure on the right is a generic structure for allocations. However, for the most accurate results, we recommend initially calling the EClient.requestFa method in order to confirm existing information before modification.

<?xml version="1.0" encoding="UTF-8"?>
<ListOfGroups>
  <Group>
  <name>Profile_Name</name>
  <defaultMethod>Allocation_Method</defaultMethod>
  
  <ListOfAccts varName="list">
  <Account>
    <acct>Account_n</acct>
    <amount>Amount</amount>
  </Account>
  <Account>
    <acct>Account_n+1</acct>
    <amount>Amount</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, and API clients will see the following changes:

Model Portfolios and the API

Placing Orders to a FA account

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.

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.

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 Violation1 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”.

Step Sizes

A step size is defined as the ratio between the historical data request’s duration period and its granularity (i.e. bar size). Historical Data requests need to be assembled in such a way that only a few thousand bars are returned at a time. The following table exemplifies this concept

Duration Allowed Bar Sizes
60 S 1 sec – 1 mins
120 S 1 sec – 2 mins
1800 S (30 mins) 1 sec – 30 mins
3600 S (1 hr) 5 secs – 1 hr
14400 S (4hr) 10 secs – 3 hrs
28800 S (8 hrs) 30 secs – 8 hrs
1 D 1 min – 1 day
2 D 2 mins – 1 day
1 W 3 mins – 1 week
1 M 30 mins – 1 month
1 Y 1 day – 1 month

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. VWAP is available.

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.

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.reqHistoricalBars (

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” or an empty string indicates current present moment).

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.

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

)

self.reqHistoricalData(4102, contract, queryTime, "1 M", "1 day", "MIDPOINT", 1, 1, False, [])
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

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

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, Cryptocurrencies, 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

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.

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.

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.

  • Important to note: 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.

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. he 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 ourside of the Regular Trading Hours, set to 1 to obtain only the RTH data
)

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", True, [])

 

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.

date: long. The bar’s 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.

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, [])

 

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.

def tickSnapshotEnd(self, reqId: int):
  print("TickSnapshotEnd. TickerId:", reqId)

 

@Override
public void tickSnapshotEnd(int reqId) {
  System.out.println("TickSnapshotEnd: " + EWrapperMsgGenerator.tickSnapshotEnd(reqId));
}

 

void TestCppClient::tickSnapshotEnd(int reqId) {
    printf( "TickSnapshotEnd: %dn", reqId);
}

 

public virtual void tickSnapshotEnd(int tickerId)
{
  Console.WriteLine("TickSnapshotEnd: "+tickerId);
}

 

Public Sub tickSnapshotEnd(tickerId As Integer) Implements IBApi.EWrapper.tickSnapshotEnd
  Console.WriteLine("TickSnapshotEnd: " & CStr(tickerId))
End Sub

 

Regulatory Snapshots

The fifth argument to reqMktData specifies a regulatory snapshot request to US stocks and options.

For stocks, there are individual exchange-specific market data subscriptions necessary to receive streaming quotes. For instance, for NYSE stocks this subscription is known as “Network A”, for ARCA/AMEX stocks it is called “Network B” and for NASDAQ stocks it is “Network C”. Each subscription is added a la carte and has a separate market data fee.

Alternatively, there is also a “US Securities Snapshot Bundle” subscription which does not provide streaming data but which allows for real time calculated snapshots of US market NBBO prices. By setting the 5th parameter in the function EClient::reqMktData to True, a regulatory snapshot request can be made from the API. The returned value is a calculation of the current market state based on data from all available exchanges.

Important: Each regulatory snapshot made will incur a fee of 0.01 USD to the account. This applies to both live and paper accounts.. If the monthly fee for regulatory snapshots reaches the price of a particular ‘Network’ subscription, the user will automatically be subscribed to that Network subscription for continuous streaming quotes and charged the associated fee for that month. At the end of the month the subscription will be terminated. Each listing exchange will be capped independently and will not be combined across listing exchanges.

Requesting regulatory snapshots is subject to pacing limitations:

  • No more than one request per second.

The following table lists the cost and maximum allocation for regulatory snapshot quotes:

Listed Network Feed Price per reqSnapshot request Pro or non-Pro Max reqSnapshot request
NYSE (Network A/CTA) 0.01 USD Pro 4500
NYSE (Network A/CTA) 0.01 USD Non-Pro 150
AMEX (Network B/CTA) 0.01 USD Pro 2300
AMEX (Network B/CTA) 0.01 USD Non-Pro 150
NASDAQ (Network C/UTP) 0.01 USD Pro 2300
NASDAQ (Network C/UTP) 0.01 USD Non-Pro 150

Receive Live Data

EWrapper.tickGeneric (

tickerId: int. Request identifier used to track data.

field: int. The type of tick being received.

value: double. Return value corresponding to value. See Available Tick Types for more details.
)

Returns generic data back to requester. Used for an array of tick types and is used to represent general evaluations.

def tickGeneric(self, reqId: TickerId, tickType: TickType, value: float):
	print("TickGeneric. TickerId:", reqId, "TickType:", tickType, "Value:", floatMaxString(value))

 

@Override
public void tickGeneric(int tickerId, int tickType, double value) {
	System.out.println("Tick Generic: " + EWrapperMsgGenerator.tickGeneric(tickerId, tickType, value));
}

 

void TestCppClient::tickGeneric(TickerId tickerId, TickType tickType, double value) {
    printf( "Tick Generic. Ticker Id: %ld, Type: %d, Value: %sn", tickerId, (int)tickType, Utils::doubleMaxString(value).c_str());
}

 

public virtual void tickGeneric(int tickerId, int field, double value)
{
	Console.WriteLine("Tick Generic. Ticker Id:" + tickerId + ", Field: " + field + ", Value: " + Util.DoubleMaxString(value));
}

 

Public Sub tickGeneric(tickerId As Integer, field As Integer, value As Double) Implements IBApi.EWrapper.tickGeneric
	Console.WriteLine("Tick Generic. Ticker Id:" & tickerId & ", Field: " & field & ", Value: " & Util.DoubleMaxString(value))
End Sub

 

EWrapper.tickPrice (

tickerId: int. Request identifier used to track data.

field: int. The type of the price being received (i.e. ask price).

price: double. The actual price.

attribs: TickAttrib. A TickAttrib object that contains price attributes such as TickAttrib::CanAutoExecute, TickAttrib::PastLimit and TickAttrib::PreOpen.
)

Market data tick price callback. Handles all price related ticks. Every tickPrice callback is followed by a tickSize. A tickPrice value of -1 or 0 followed by a tickSize of 0 indicates there is no data for this field currently available, whereas a tickPrice with a positive tickSize indicates an active quote of 0 (typically for a combo contract).

def tickPrice(self, reqId: TickerId, tickType: TickType, price: float, attrib: TickAttrib):
	print(reqId, tickType, price, attrib)

 

@Override
public void tickPrice(int tickerId, int field, double price, TickAttrib attribs) {
	System.out.println("Tick Price: " + EWrapperMsgGenerator.tickPrice( tickerId, field, price, attribs));
}

 

void TestCppClient::tickPrice( TickerId tickerId, TickType field, double price, const TickAttrib& attribs) {
    printf( "Tick Price. Ticker Id: %ld, Field: %d, Price: %s, CanAutoExecute: %d, PastLimit: %d, PreOpen: %dn", tickerId, (int)field, Utils::doubleMaxString(price).c_str(), attribs.canAutoExecute, attribs.pastLimit, attribs.preOpen);
}

 

public virtual void tickPrice(int tickerId, int field, double price, TickAttrib attribs) 
{
	Console.WriteLine("Tick Price. Ticker Id:" + tickerId + ", Field: " + field + ", Price: " + Util.DoubleMaxString(price) + ", CanAutoExecute: " + attribs.CanAutoExecute + ", PastLimit: " + attribs.PastLimit + ", PreOpen: " + attribs.PreOpen);
}

 

Public Sub tickPrice(tickerId As Integer, field As Integer, price As Double, attribs As TickAttrib) Implements IBApi.EWrapper.tickPrice
	Console.WriteLine("TickPrice - TickerId [" & CStr(tickerId) & "] Field [" & TickType.getField(field) & "] Price [" & Util.DoubleMaxString(price) & "] PreOpen [" & attribs.PreOpen & "]")
End Sub

 

EWrapper.tickSize (

tickerId: int. Request identifier used to track data.

field: int. the type of size being received (i.e. bid size)

size: int. the actual size. US stocks have a multiplier of 100.
)

Market data tick size callback. Handles all size-related ticks.

def tickSize(self, reqId: TickerId, tickType: TickType, size: Decimal):
	print("TickSize. TickerId:", reqId, "TickType:", tickType, "Size: ", decimalMaxString(size))

 

@Override
public void tickSize(int tickerId, int field, Decimal size) {
    System.out.println("Tick Size: " + EWrapperMsgGenerator.tickSize( tickerId, field, size));
}

 

void TestCppClient::tickSize( TickerId tickerId, TickType field, Decimal size) {
    printf( "Tick Size. Ticker Id: %ld, Field: %d, Size: %sn", tickerId, (int)field, decimalStringToDisplay(size).c_str());
}

 

public virtual void tickSize(int tickerId, int field, decimal size)
{
	Console.WriteLine("Tick Size. Ticker Id:" + tickerId + ", Field: " + field + ", Size: " + Util.DecimalMaxString(size));
}

 

Public Sub tickSize(tickerId As Integer, field As Integer, size As Decimal) Implements IBApi.EWrapper.tickSize
	Console.WriteLine("Tick Size. Ticker Id:" & CStr(tickerId) & ", Field: " & TickType.getField(field) & ", Size: " & Util.DecimalMaxString(size))
End Sub

 

EWrapper.tickString (

tickerId: int. Request identifier used to track data.

field: int. The type of the tick being received

value: String. Variable containining message response.
)

Market data callback. Every tickPrice is followed by a tickSize. There are also independent tickSize callbacks anytime the tickSize changes, and so there will be duplicate tickSize messages following a tickPrice.

def tickString(self, reqId: TickerId, tickType: TickType, value: str):
	print("TickString. TickerId:", reqId, "Type:", tickType, "Value:", value)

 

@Override
    public void tickString(int tickerId, int tickType, String value) {
        System.out.println("Tick String: " + EWrapperMsgGenerator.tickString(tickerId, tickType, value));
    }

 

void TestCppClient::tickString(TickerId tickerId, TickType tickType, const std::string& value) {
    printf( "Tick String. Ticker Id: %ld, Type: %d, Value: %sn", tickerId, (int)tickType, value.c_str());
}

 

public virtual void tickString(int tickerId, int tickType, string value)
{
	Console.WriteLine("Tick string. Ticker Id:" + tickerId + ", Type: " + tickType + ", Value: " + value);
}

 

Public Sub tickString(tickerId As Integer, field As Integer, value As String) Implements IBApi.EWrapper.tickString
	Console.WriteLine("Tick string. Ticker Id:" & CStr(tickerId) & ", Type: " & TickType.getField(field) & ", Value: " & value)
End Sub

 

Exchange Component Mapping

A market data request is able to return data from multiple exchanges. After a market data request is made for an instrument covered by market data subscriptions, a message will be sent to function IBApi::EWrapper::tickReqParams with information about ‘minTick’, BBO exchange mapping, and available snapshot permissions.

The exchange mapping identifier bboExchange will be a symbol such as “a6” which can be used to decode the single letter exchange abbreviations returned to the bidExch, askExch, and lastExch fields by invoking the function IBApi::EClient::reqSmartComponents. More information about Component Exchanges.

The minTick returned to tickReqParams indicates the minimum increment in market data values returned to the API. It can differ from the minTick value in the ContractDetails class. For instance, combos will often have a minimum increment of 0.01 for market data and a minTick of 0.05 for order placement.

EWrapper.tickReqParams (

tickerId: int. Request identifier used to track data.

minTick: Minimum tick for the contract on the exchange.

bboExchange: String. Exchange offering the best bid offer.

snapshotPermissions: Based on the snapshot parameter in EClient.reqMktData.
)

Displays the ticker with BBO exchange.

def tickReqParams(self, tickerId:int, minTick:float, bboExchange:str, snapshotPermissions:int):
	print("TickReqParams. TickerId:", tickerId, "MinTick:", floatMaxString(minTick), "BboExchange:", bboExchange, "SnapshotPermissions:", intMaxString(snapshotPermissions))

 

@Override
public void tickReqParams(int tickerId, double minTick, String bboExchange, int snapshotPermissions) {
	System.out.println("Tick req params: " + EWrapperMsgGenerator.tickReqParams(tickerId, minTick, bboExchange, snapshotPermissions));
}

 

void TestCppClient::tickReqParams(int tickerId, double minTick, const std::string& bboExchange, int snapshotPermissions) {
    printf("tickerId: %d, minTick: %s, bboExchange: %s, snapshotPermissions: %un", tickerId, Utils::doubleMaxString(minTick).c_str(), bboExchange.c_str(), snapshotPermissions);
    m_bboExchange = bboExchange;
}

 

public void tickReqParams(int tickerId, double minTick, string bboExchange, int snapshotPermissions)
{
	Console.WriteLine("id={0} minTick = {1} bboExchange = {2} snapshotPermissions = {3}", tickerId, Util.DoubleMaxString(minTick), bboExchange, Util.IntMaxString(snapshotPermissions)); BboExchange = bboExchange;
}

 

Public Sub tickReqParams(tickerId As Integer, minTick As Double, bboExchange As String, snapshotPermissions As Integer) Implements EWrapper.tickReqParams
	Console.WriteLine("id={0} minTick = {1} bboExchange = {2} snapshotPermissions = {3}", tickerId, Util.DoubleMaxString(minTick), bboExchange, Util.IntMaxString(snapshotPermissions))
	Me.BboExchange = bboExchange
End Sub

 

Re-Routing CFDs

IB does not provide market data for certain types of instruments, such as stock CFDs and forex CFDs. If a stock CFD or forex CFD is entered into a TWS watchlist, TWS will automatically display market data for the underlying ticker and show a ‘U’ icon next to the instrument name to indicate that the data is for the underlying instrument.

From the API, when level 1 or level 2 market data is requested for a stock CFD or a forex CFD, a callback is made to the functions EWrapper.rerouteMktDataReq or EWrapper.rerouteMktDepthReq respectively with details about the underlying instrument in IB’s database which does have market data.

EWrapper.rerouteMktDataReq (

reqId: int. Request identifier used to track data.

conId: int. Contract identifier of the underlying instrument which has market data.

exchange: int. Primary exchange of the underlying.
)

Returns ocnid and exchange for CFD market data request re-route.

def rerouteMktDataReq(self, reqId: int, conId: int, exchange: str):
	print("Re-route market data request. ReqId:", reqId, "ConId:", conId, "Exchange:", exchange)

 

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

 

void TestCppClient::rerouteMktDataReq(int reqId, int conid, const std::string& exchange) {
    printf( "Re-route market data request. ReqId: %d, ConId: %d, Exchange: %sn", reqId, conid, exchange.c_str());
}

 

public void rerouteMktDataReq(int reqId, int conId, string exchange)
{
	Console.WriteLine("Re-route market data request. Req Id: {0}, ConId: {1}, Exchange: {2}", reqId, conId, exchange);
}

 

Public Sub rerouteMktDataReq(reqId As Integer, conId As Integer, exchange As String) Implements IBApi.EWrapper.rerouteMktDataReq
	Console.WriteLine("Re-route market data request. Req Id: {0}, Con Id: {1}, Exchange: {2}", reqId, conId, exchange)
End Sub

 

EWrapper.rerouteMktDepthReq (

reqId: int. Request identifier used to track data.

conId: int. Contract identifier of the underlying instrument which has market data.

exchange: int. Primary exchange of the underlying.
)

Returns the conId and exchange for an underlying contract when a request is made for level 2 data for an instrument which does not have data in IB’s database. For example stock CFDs and index CFDs.

def rerouteMktDepthReq(self, reqId: int, conId: int, exchange: str):
	print("Re-route market depth request. ReqId:", reqId, "ConId:", conId, "Exchange:", exchange)

 

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

 

void TestCppClient::rerouteMktDepthReq(int reqId, int conid, const std::string& exchange) {
    printf( "Re-route market depth request. ReqId: %d, ConId: %d, Exchange: %sn", reqId, conid, exchange.c_str());
}

 

public void rerouteMktDepthReq(int reqId, int conId, string exchange)
{
	Console.WriteLine("Re-route market depth request. Req Id: {0}, ConId: {1}, Exchange: {2}", reqId, conId, exchange);
}

 

Public Sub rerouteMktDepthReq(reqId As Integer, conId As Integer, exchange As String) Implements IBApi.EWrapper.rerouteMktDepthReq
            Console.WriteLine("Re-route market depth request. Req Id: {0}, Con Id: {1}, Exchange: {2}", reqId, conId, exchange)
        End Sub

 

Available Tick Types

EClient.reqMktData will return data to various methods such as EWrapper.tickPrice, EWrapper.tickSize, EWrapper.tickString, etc. The values returned are dependent upon the generic tick requested and the type of data returned. The table below references what generic tick should be requested, what tick id should be returned, and to which method it will return to.

Tick Name Description Generic tick required Delivery Method Tick Id
Bid Size Number of contracts or lots offered at the bid price. IBApi.EWrapper.tickSize 0
Bid Price Highest priced bid for the contract. IBApi.EWrapper.tickPrice 1
Ask Price Lowest price offer on the contract. IBApi.EWrapper.tickPrice 2
Ask Size Number of contracts or lots offered at the ask price. IBApi.EWrapper.tickSize 3
Last Price Last price at which the contract traded (does not include some trades in RTVolume). IBApi.EWrapper.tickPrice 4
Last Size Number of contracts or lots traded at the last price. IBApi.EWrapper.tickSize 5
High High price for the day. IBApi.EWrapper.tickPrice 6
Low Low price for the day. IBApi.EWrapper.tickPrice 7
Volume Trading volume for the day for the selected contract (US Stocks: multiplier 100). IBApi.EWrapper.tickSize 8
Close Price “The last available closing price for the previous day. For US Equities we use corporate action processing to get the closing price so the close price is adjusted to reflect forward and reverse splits and cash and stock dividends.” IBApi.EWrapper.tickPrice 9
Bid Option Computation Computed Greeks and implied volatility based on the underlying stock price and the option bid price. See Option Greeks IBApi.EWrapper.tickOptionComputation 10
Ask Option Computation Computed Greeks and implied volatility based on the underlying stock price and the option ask price. See Option Greeks IBApi.EWrapper.tickOptionComputation 11
Last Option Computation Computed Greeks and implied volatility based on the underlying stock price and the option last traded price. See Option Greeks IBApi.EWrapper.tickOptionComputation 12
Model Option Computation Computed Greeks and implied volatility based on the underlying stock price and the option model price. Correspond to greeks shown in TWS. See Option Greeks IBApi.EWrapper.tickOptionComputation 13
Open Tick Current session’s opening price. Before open will refer to previous day. The official opening price requires a market data subscription to the native exchange of the instrument. IBApi.EWrapper.tickPrice 14
Low 13 Weeks Lowest price for the last 13 weeks. For stocks only. 165 IBApi.EWrapper.tickPrice 15
High 13 Weeks Highest price for the last 13 weeks. For stocks only. 165 IBApi.EWrapper.tickPrice 16
Low 26 Weeks Lowest price for the last 26 weeks. For stocks only. 165 IBApi.EWrapper.tickPrice 17
High 26 Weeks Highest price for the last 26 weeks. For stocks only. 165 IBApi.EWrapper.tickPrice 18
Low 52 Weeks Lowest price for the last 52 weeks. For stocks only. 165 IBApi.EWrapper.tickPrice 19
High 52 Weeks Highest price for the last 52 weeks. For stocks only. 165 IBApi.EWrapper.tickPrice 20
Average Volume The average daily trading volume over 90 days. Multiplier of 100. For stocks only. 165 IBApi.EWrapper.tickSize 21
Open Interest “(Deprecated not currently in use) Total number of options that are not closed.” IBApi.EWrapper.tickSize 22
Option Historical Volatility The 30-day historical volatility (currently for stocks). 104 IBApi.EWrapper.tickGeneric 23
Option Implied Volatility “A prediction of how volatile an underlying will be in the future. The IB 30-day volatility is the at-market volatility estimated for a maturity thirty calendar days forward of the current trading day and is based on option prices from two consecutive expiration months.” 106 IBApi.EWrapper.tickGeneric 24
Option Bid Exchange Not Used. IBApi.EWrapper.tickString 25
Option Ask Exchange Not Used. IBApi.EWrapper.tickString 26
Option Call Open Interest Call option open interest. 101 IBApi.EWrapper.tickSize 27
Option Put Open Interest Put option open interest. 101 IBApi.EWrapper.tickSize 28
Option Call Volume Call option volume for the trading day. 100 IBApi.EWrapper.tickSize 29
Option Put Volume Put option volume for the trading day. 100 IBApi.EWrapper.tickSize 30
Index Future Premium The number of points that the index is over the cash index. 162 IBApi.EWrapper.tickGeneric 31
Bid Exchange “For stock and options identifies the exchange(s) posting the bid price. See Component Exchanges” IBApi.EWrapper.tickString 32
Ask Exchange “For stock and options identifies the exchange(s) posting the ask price. See Component Exchanges” IBApi.EWrapper.tickString 33
Auction Volume The number of shares that would trade if no new orders were received and the auction were held now. 225 IBApi.EWrapper.tickSize 34
Auction Price The price at which the auction would occur if no new orders were received and the auction were held now- the indicative price for the auction. Typically received after Auction imbalance (tick type 36) 225 IBApi.EWrapper.tickPrice 35
Auction Imbalance The number of unmatched shares for the next auction; returns how many more shares are on one side of the auction than the other. Typically received after Auction Volume (tick type 34) 225 IBApi.EWrapper.tickSize 36
Mark Price “The mark price is the current theoretical calculated value of an instrument. Since it is a calculated value it will typically have many digits of precision.” 232 IBApi.EWrapper.tickPrice 37
Bid EFP Computation Computed EFP bid price IBApi.EWrapper.tickEFP 38
Ask EFP Computation Computed EFP ask price IBApi.EWrapper.tickEFP 39
Last EFP Computation Computed EFP last price IBApi.EWrapper.tickEFP 40
Open EFP Computation Computed EFP open price IBApi.EWrapper.tickEFP 41
High EFP Computation Computed high EFP traded price for the day IBApi.EWrapper.tickEFP 42
Low EFP Computation Computed low EFP traded price for the day IBApi.EWrapper.tickEFP 43
Close EFP Computation Computed closing EFP price for previous day IBApi.EWrapper.tickEFP 44
Last Timestamp Time of the last trade (in UNIX time). IBApi.EWrapper.tickString 45
Shortable Describes the level of difficulty with which the contract can be sold short. See Shortable 236 IBApi.EWrapper.tickGeneric 46
RT Volume (Time & Sales) “Last trade details (Including both “”Last”” and “”Unreportable Last”” trades). See RT Volume” 233 IBApi.EWrapper.tickString 48
Halted Indicates if a contract is halted. See Halted IBApi.EWrapper.tickGeneric 49
Bid Yield Implied yield of the bond if it is purchased at the current bid. IBApi.EWrapper.tickPrice 50
Ask Yield Implied yield of the bond if it is purchased at the current ask. IBApi.EWrapper.tickPrice 51
Last Yield Implied yield of the bond if it is purchased at the last price. IBApi.EWrapper.tickPrice 52
Custom Option Computation Greek values are based off a user customized price. IBApi.EWrapper.tickOptionComputation 53
Trade Count Trade count for the day. 293 IBApi.EWrapper.tickGeneric 54
Trade Rate Trade count per minute. 294 IBApi.EWrapper.tickGeneric 55
Volume Rate Volume per minute. 295 IBApi.EWrapper.tickGeneric 56
Last RTH Trade Last Regular Trading Hours traded price. 318 IBApi.EWrapper.tickPrice 57
RT Historical Volatility 30-day real time historical volatility. 411 IBApi.EWrapper.tickGeneric 58
IB Dividends Contract’s dividends. See IB Dividends. 456 IBApi.EWrapper.tickString 59
Bond Factor Multiplier The bond factor is a number that indicates the ratio of the current bond principal to the original principal 460 IBApi.EWrapper.tickGeneric 60
Regulatory Imbalance The imbalance that is used to determine which at-the-open or at-the-close orders can be entered following the publishing of the regulatory imbalance. 225 IBApi.EWrapper.tickSize 61
News Contract’s news feed. 292 IBApi.EWrapper.tickString 62
Short-Term Volume 3 Minutes The past three minutes volume. Interpolation may be applied. For stocks only. 595 IBApi.EWrapper.tickSize 63
Short-Term Volume 5 Minutes The past five minutes volume. Interpolation may be applied. For stocks only. 595 IBApi.EWrapper.tickSize 64
Short-Term Volume 10 Minutes The past ten minutes volume. Interpolation may be applied. For stocks only. 595 IBApi.EWrapper.tickSize 65
Delayed Bid Delayed bid price. See Market Data Types. IBApi.EWrapper.tickPrice 66
Delayed Ask Delayed ask price. See Market Data Types. IBApi.EWrapper.tickPrice 67
Delayed Last Delayed last traded price. See Market Data Types. IBApi.EWrapper.tickPrice 68
Delayed Bid Size Delayed bid size. See Market Data Types. IBApi.EWrapper.tickSize 69
Delayed Ask Size Delayed ask size. See Market Data Types. IBApi.EWrapper.tickSize 70
Delayed Last Size Delayed last size. See Market Data Types. IBApi.EWrapper.tickSize 71
Delayed High Price Delayed highest price of the day. See Market Data Types. IBApi.EWrapper.tickPrice 72
Delayed Low Price Delayed lowest price of the day. See Market Data Types IBApi.EWrapper.tickPrice 73
Delayed Volume Delayed traded volume of the day. See Market Data Types IBApi.EWrapper.tickSize 74
Delayed Close The prior day’s closing price. IBApi.EWrapper.tickPrice 75
Delayed Open Not currently available IBApi.EWrapper.tickPrice 76
RT Trade Volume “Last trade details that excludes “”Unreportable Trades””. See RT Trade Volume” 375 IBApi.EWrapper.tickString 77
Creditman mark price Not currently available IBApi.EWrapper.tickPrice 78
Creditman slow mark price Slower mark price update used in system calculations 619 IBApi.EWrapper.tickPrice 79
Delayed Bid Option Computed greeks based on delayed bid price. See Market Data Types and Option Greeks. IBApi.EWrapper.tickPrice 80
Delayed Ask Option Computed greeks based on delayed ask price. See Market Data Types and Option Greeks. IBApi.EWrapper.tickPrice 81
Delayed Last Option Computed greeks based on delayed last price. See Market Data Types and Option Greeks. IBApi.EWrapper.tickPrice 82
Delayed Model Option Computed Greeks and model’s implied volatility based on delayed stock and option prices. IBApi.EWrapper.tickPrice 83
Last Exchange Exchange of last traded price IBApi.EWrapper.tickString 84
Last Regulatory Time Timestamp (in Unix ms time) of last trade returned with regulatory snapshot IBApi.EWrapper.tickString 85
Futures Open Interest Total number of outstanding futures contracts. *HSI open interest requested with generic tick 101 588 IBApi.EWrapper.tickSize 86
Average Option Volume Average volume of the corresponding option contracts(TWS Build 970+ is required) 105 IBApi.EWrapper.tickSize 87
Delayed Last Timestamp Delayed time of the last trade (in UNIX time) (TWS Build 970+ is required) IBApi.EWrapper.tickString 88
Shortable Shares Number of shares available to short (TWS Build 974+ is required) 236 IBApi.EWrapper.tickSize 89
ETF Nav Close Today’s closing price of ETF’s Net Asset Value (NAV). Calculation is based on prices of ETF’s underlying securities. 578 IBApi.EWrapper.tickPrice 92
ETF Nav Prior Close Yesterday’s closing price of ETF’s Net Asset Value (NAV). Calculation is based on prices of ETF’s underlying securities. 578 IBApi.EWrapper.tickPrice 93
ETF Nav Bid The bid price of ETF’s Net Asset Value (NAV). Calculation is based on prices of ETF’s underlying securities. 576 IBApi.EWrapper.tickPrice 94
ETF Nav Ask The ask price of ETF’s Net Asset Value (NAV). Calculation is based on prices of ETF’s underlying securities. 576 IBApi.EWrapper.tickPrice 95
ETF Nav Last The last price of Net Asset Value (NAV). For ETFs: Calculation is based on prices of ETF’s underlying securities. For NextShares: Value is provided by NASDAQ 577 IBApi.EWrapper.tickPrice 96
ETF Nav Frozen Last ETF Nav Last for Frozen data 623 IBApi.EWrapper.tickPrice 97
ETF Nav High The high price of ETF’s Net Asset Value (NAV) 614 IBApi.EWrapper.tickPrice 98
ETF Nav Low The low price of ETF’s Net Asset Value (NAV) 614 IBApi.EWrapper.tickPrice 99
Estimated IPO – Midpoint Midpoint is calculated based on IPO price range 586 IBApi.EWrapper.tickGeneric 101
Final IPO Price Final price for IPO 586 IBApi.EWrapper.tickGeneric 102

Halted

The Halted tick type indicates if a contract has been halted for trading. It can have the following values:

Value Description
-1 Halted status not available. Usually returned with frozen data.
0 Not halted. This value will only be returned if the contract is in a TWS watchlist.
1 General halt. Trading halt is imposed for purely regulatory reasons with/without volatility halt.
2 Volatility halt. Trading halt is imposed by the exchange to protect against extreme volatility.

Shortable

The shortable tick is an indicative on the amount of shares which can be sold short for the contract:

Receiving the actual number of shares available to short requires TWS 974+. For detailed information about shortability data (shortable shares, fee rate) available outside of TWS, IB also provides an FTP site. For more information on the FTP site, see knowledge base article 2024

Range Description
Value higher than 2.5 There are at least 1000 shares available for short selling.
Value higher than 1.5 This contract will be available for short selling if shares can be located.
1.5 or less Contract is not available for short selling.

Volume Data

The API reports the current day’s volume in several ways. They are summarized as follows:

  • Volume tick type 8: The ‘native volume’. This includes delayed transactions, busted trades, and combos, but will not update with every tick.
  • RTVolume: highest number, includes non-reportable trades such as odd lots, average price and derivative trades.
  • RTTradeVolume: only includes ‘last’ ticks, similar to number also used in charts/historical data.

RT Volume

The RT Volume tick type corresponds to the TWS’ Time & Sales window and contains the last trade’s price, size and time along with current day’s total traded volume, Volume Weighted Average Price (VWAP) and whether or not the trade was filled by a single market maker.

There is a setting in TWS which displays tick-by-tick data in the TWS Time & Sales Window. If this setting is checked, it will provide a higher granularity of data than RTVolume.

Example: 701.28;1;1348075471534;67854;701.46918464;true

As volume for US stocks is reported in lots, a volume of 0 reported in RTVolume will typically indicate an odd lot data point (less than 100 shares).

It is important to note that while the TWS Time & Sales Window also has information about trade conditions available with data points, this data is not available through the API. So for instance, the ‘unreportable’ trade status displayed with points in the Time & Sales Window is not available through the API, and that trade data will appear in the API just as any other data point. As always, an API application needs to exercise caution in responding to single data points.

RT Trade Volume

The RT Trade Volume is similar to RT Volume, but designed to avoid relaying back “Unreportable Trades” shown in TWS Time&Sales via the API. RT Trade Volume will not contain average price or derivative trades which are included in RTVolume.

IB Dividends

This tick type provides four different comma-separated elements:

  • The sum of dividends for the past 12 months (0.83 in the example below).
  • The sum of dividends for the next 12 months (0.92 from the example below).
  • The next dividend date (20130219 in the example below).
  • The next single dividend amount (0.23 from the example below).

Example: 0.83,0.92,20130219,0.23

To receive dividend information it is sometimes necessary to direct-route rather than smart-route market data requests.

Tick By Tick Data

Tick-by-tick data has been available since TWS v969 and API v973.04.

In TWS, tick-by-tick data is available in the Time & Sales Window.

From the API, this corresponds to the function IBApi.EClient.reqTickByTickData. The maximum number of simultaneous tick-by-tick subscriptions allowed for a user is determined by the same formula used to calculate maximum number of market depth subscriptions Limitations.

  • Real time tick-by-tick data is currently not available for options. Historical tick-by-tick data is available.

Request Tick By Tick Data

EClient.reqTickByTick (

reqId: int. unique identifier of the request.

contract: Contract. the contract for which tick-by-tick data is requested.

tickType: String. tick-by-tick data type: “Last”, “AllLast”, “BidAsk” or “MidPoint”.

numberOfTicks: int. number of ticks.

ignoreSize: bool. ignore size flag.
)

Requests tick by tick or Time & Sales data.

self.reqTickByTickData(19001, contract, "Last", 0, True)

 

client.reqTickByTickData(19001, contract, "Last", 0, false);

 

m_pClient->reqTickByTickData(20005, contract, "Last", 10, false);

 

client.reqTickByTickData(19001, contract, "Last", 0, false);

 

client.reqTickByTickData(19001, contract, "Last", 0, False)

 

Receive Tick By Tick Data

EWrapper.tickByTickAllLast (

reqId: int. unique identifier of the request.

tickType: int. 0: “Last” or 1: “AllLast”.

time: long. tick-by-tick real-time tick timestamp.

price: double. tick-by-tick real-time tick last price.

size: decimal. tick-by-tick real-time tick last size.

tickAttribLast: TickAttribLast. tick-by-tick real-time last tick attribs (bit 0 – past limit, bit 1 – unreported).

exchange: String. tick-by-tick real-time tick exchange.

specialConditions: String. tick-by-tick real-time tick special conditions.
)

Returns “Last” or “AllLast” tick-by-tick real-time tick.

def tickByTickAllLast(self, reqId: int, tickType: int, time: int, price: float, size: Decimal, tickAtrribLast: TickAttribLast, exchange: str,specialConditions: str):
	print(" ReqId:", reqId, "Time:", time, "Price:", floatMaxString(price), "Size:", size, "Exch:" , exchange, "Spec Cond:", specialConditions, "PastLimit:", tickAtrribLast.pastLimit, "Unreported:", tickAtrribLast.unreported)

 

@Override
public void tickByTickAllLast(int reqId, int tickType, long time, double price, Decimal size, TickAttribLast tickAttribLast, String exchange, String specialConditions) {
	System.out.println(EWrapperMsgGenerator.tickByTickAllLast(reqId, tickType, time, price, size, tickAttribLast, exchange, specialConditions));
}

 

void TestCppClient::tickByTickAllLast(int reqId, int tickType, time_t time, double price, Decimal size, const TickAttribLast& tickAttribLast, const std::string& exchange, const std::string& specialConditions) {
    printf("Tick-By-Tick. ReqId: %d, TickType: %s, Time: %s, Price: %s, Size: %s, PastLimit: %d, Unreported: %d, Exchange: %s, SpecialConditions:%sn", reqId, (tickType == 1 ? "Last" : "AllLast"), ctime(&time), Utils::doubleMaxString(price).c_str(), decimalStringToDisplay(size).c_str(), tickAttribLast.pastLimit, tickAttribLast.unreported, exchange.c_str(), specialConditions.c_str());
}

 

public void tickByTickAllLast(int reqId, int tickType, long time, double price, decimal size, TickAttribLast tickAttribLast, string exchange, string specialConditions)
        {
            Console.WriteLine("Tick-By-Tick. Request Id: {0}, TickType: {1}, Time: {2}, Price: {3}, Size: {4}, Exchange: {5}, Special Conditions: {6}, PastLimit: {7}, Unreported: {8}",
                reqId, tickType == 1 ? "Last" : "AllLast", Util.UnixSecondsToString(time, "yyyyMMdd-HH:mm:ss"), Util.DoubleMaxString(price), Util.DecimalMaxString(size), exchange, specialConditions, tickAttribLast.PastLimit, tickAttribLast.Unreported);
        }

 

Public Sub tickByTickAllLast(reqId As Integer, tickType As Integer, time As Long, price As Double, size As Decimal, tickAttribLast As TickAttribLast, exchange As String, specialConditions As String) Implements EWrapper.tickByTickAllLast
	Dim tickTypeStr As String
	If tickType = 1 Then
		tickTypeStr = "Last"
	Else
		tickTypeStr = "AllLast"
	End If
	Console.WriteLine("Tick-By-Tick. Request Id: {0}, TickType: {1}, Time: {2}, Price: {3}, Size: {4}, Exchange: {5}, Special Conditions: {6}, PastLimit: {7}, Unreported: {8}",
		reqId, tickTypeStr, Util.UnixSecondsToString(time, "yyyyMMdd-HH:mm:ss"), Util.DoubleMaxString(price), Util.DecimalMaxString(size), exchange, specialConditions,
		tickAttribLast.PastLimit, tickAttribLast.Unreported)
End Sub

 

EWrapper.tickByTickBidAsk (

reqId: int. unique identifier of the request.

time: long. timestamp of the tick.

bidPrice: double. bid price of the tick.

askPrice: double. ask price of the tick.

bidSize: decimal. bid size of the tick.

askSize: decimal. ask size of the tick.

tickAttribBidAsk: TickAttribBidAsk. tick-by-tick real-time bid/ask tick attribs (bit 0 – bid past low, bit 1 – ask past high).
)

Returns “BidAsk” tick-by-tick real-time tick.

 def tickByTickBidAsk(self, reqId: int, time: int, bidPrice: float, askPrice: float, bidSize: Decimal, askSize: Decimal, tickAttribBidAsk: TickAttribBidAsk):
	print("BidAsk. ReqId:", reqId, "Time:", time, "BidPrice:", floatMaxString(bidPrice), "AskPrice:", floatMaxString(askPrice), "BidSize:", decimalMaxString(bidSize), "AskSize:", decimalMaxString(askSize), "BidPastLow:", tickAttribBidAsk.bidPastLow, "AskPastHigh:", tickAttribBidAsk.askPastHigh)

 

@Override
public void tickByTickBidAsk(int reqId, long time, double bidPrice, double askPrice, Decimal bidSize, Decimal askSize, TickAttribBidAsk tickAttribBidAsk) {
	System.out.println(EWrapperMsgGenerator.tickByTickBidAsk(reqId, time, bidPrice, askPrice, bidSize, askSize, tickAttribBidAsk));
}

 

void TestCppClient::tickByTickBidAsk(int reqId, time_t time, double bidPrice, double askPrice, Decimal bidSize, Decimal askSize, const TickAttribBidAsk& tickAttribBidAsk) {
    printf("Tick-By-Tick. ReqId: %d, TickType: BidAsk, Time: %s, BidPrice: %s, AskPrice: %s, BidSize: %s, AskSize: %s, BidPastLow: %d, AskPastHigh: %dn", reqId, ctime(&time), Utils::doubleMaxString(bidPrice).c_str(), Utils::doubleMaxString(askPrice).c_str(), decimalStringToDisplay(bidSize).c_str(), decimalStringToDisplay(askSize).c_str(), tickAttribBidAsk.bidPastLow, tickAttribBidAsk.askPastHigh);
}

 

public void tickByTickBidAsk(int reqId, long time, double bidPrice, double askPrice, decimal bidSize, decimal askSize, TickAttribBidAsk tickAttribBidAsk)
{
	Console.WriteLine("Tick-By-Tick. Request Id: {0}, TickType: BidAsk, Time: {1}, BidPrice: {2}, AskPrice: {3}, BidSize: {4}, AskSize: {5}, BidPastLow: {6}, AskPastHigh: {7}", reqId, Util.UnixSecondsToString(time, "yyyyMMdd-HH:mm:ss"), Util.DoubleMaxString(bidPrice), Util.DoubleMaxString(askPrice), Util.DecimalMaxString(bidSize), Util.DecimalMaxString(askSize), tickAttribBidAsk.BidPastLow, tickAttribBidAsk.AskPastHigh);
}

 

Public Sub tickByTickBidAsk(reqId As Integer, time As Long, bidPrice As Double, askPrice As Double, bidSize As Decimal, askSize As Decimal, tickAttribBidAsk As TickAttribBidAsk) Implements EWrapper.tickByTickBidAsk
            Console.WriteLine("Tick-By-Tick. Request Id: {0}, TickType: BidAsk, Time: {1}, BidPrice: {2}, AskPrice: {3}, BidSize: {4}, AskSize: {5}, BidPastLow: {6}, AskPastHigh: {7}",
                reqId, Util.UnixSecondsToString(time, "yyyyMMdd-HH:mm:ss"), Util.DoubleMaxString(bidPrice), Util.DoubleMaxString(askPrice), Util.DecimalMaxString(bidSize), Util.DecimalMaxString(askSize),
                tickAttribBidAsk.BidPastLow, tickAttribBidAsk.AskPastHigh)
        End Sub

 

EWrapper.tickByTickMidPoint (

reqId: int. Request identifier used to track data.

time: long. Timestamp of the tick.

midPoint: double. Mid point value of the tick.
)

Returns “MidPoint” tick-by-tick real-time tick.

def tickByTickMidPoint(self, reqId: int, time: int, midPoint: float):
	print("Midpoint. ReqId:", reqId, "Time:", time, "MidPoint:", floatMaxString(midPoint))

 

@Override
public void tickByTickMidPoint(int reqId, long time, double midPoint) {
	System.out.println(EWrapperMsgGenerator.tickByTickMidPoint(reqId, time, midPoint));
}

 

void TestCppClient::tickByTickMidPoint(int reqId, time_t time, double midPoint) {
    printf("Tick-By-Tick. ReqId: %d, TickType: MidPoint, Time: %s, MidPoint: %sn", reqId, ctime(&time), Utils::doubleMaxString(midPoint).c_str());
}

 

public void tickByTickMidPoint(int reqId, long time, double midPoint)
{
	Console.WriteLine("Tick-By-Tick. Request Id: {0}, TickType: MidPoint, Time: {1}, MidPoint: {2}", reqId, Util.UnixSecondsToString(time, "yyyyMMdd-HH:mm:ss"), Util.DoubleMaxString(midPoint));
}

 

Public Sub tickByTickMidPoint(reqId As Integer, time As Long, midPoint As Double) Implements EWrapper.tickByTickMidPoint
	Console.WriteLine("Tick-By-Tick. Request Id: {0}, TickType: MidPoint, Time: {1}, MidPoint: {2}", reqId, Util.UnixSecondsToString(time, "yyyyMMdd-HH:mm:ss"), Util.DoubleMaxString(midPoint))
End Sub

 

Cancel Tick By Tick Data

EClient.cancelTickByTickData (

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

Cancels specified tick-by-tick data.

self.cancelTickByTickData(19001)

 

client.cancelTickByTickData(19001);

 

m_pClient->cancelTickByTickData(20001);

 

client.cancelTickByTickData(19001);

 

client.cancelTickByTickData(19001)

 

Halted and Unhalted ticks

The Tick-By-Tick attribute has been introduced. The tick attribute pastLimit is also returned with historical Tick-By-Tick responses.

  • 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.

Market Scanner

Some scans in the TWS Advanced Market Scanner can be accessed via the TWS API through the EClient.reqScannerSubscription.

Results are delivered via EWrapper.scannerData and the EWrapper.scannerDataEnd marker will indicate when all results have been delivered. The returned results to scannerData simply consist of a list of contracts. There are no market data fields (bid, ask, last, volume, …) returned from the scanner, and so if these are desired they have to be requested separately with the reqMktData function. Since the scanner results do not include any market data fields, it is not necessary to have market data subscriptions to use the API scanner. However to use filters, market data subscriptions are generally required.

Since the EClient.reqScannerSubscription request keeps a subscription open you will keep receiving periodic updates until the request is cancelled via EClient.cancelScannerSubscription :

Scans are limited to a maximum result of 50 results per scan code, and only 10 API scans can be active at a time.

scannerSubscriptionFilterOptions has been added to the API to allow for generic filters. This field is entered as a list of TagValues which have a tag followed by its value, e.g. TagValue(“usdMarketCapAbove”, “10000”) indicates a market cap above 10000 USD. Available filters can be found using the EClient.reqScannerParameters function.

A string containing all available XML-formatted parameters will then be returned via EWrapper.scannerParameters.

Important: remember the TWS API is just an interface to the TWS. If you are having problems defining a scanner, always make sure you can create a similar scanner using the TWS’ Advanced Market Scanner.

Market Scanner Parameters

A string containing all available XML-formatted parameters will then be returned via EWrapper.scannerParameters.

Request Market Scanner Parameters

EClient.reqScannerParameters ()

Requests an XML list of scanner parameters valid in TWS.

self.reqScannerParameters()

 

client.reqScannerParameters();

 

m_pClient->reqScannerParameters();

 

client.reqScannerParameters();

 

client.reqScannerParameters()

 

Receive Market Scanner Parameters

EWrapper.scannerParameters (

xml: String. The xml-formatted string with the available parameters.
)

Provides the xml-formatted parameters available from TWS market scanners (not all available in API).

def scannerParameters(self, xml: str):
	open('log/scanner.xml', 'w').write(xml)
	print("ScannerParameters received.")

 

@Override
public void scannerParameters(String xml) {
	System.out.println("ScannerParameters. " + xml + "n");
}

 

void TestCppClient::scannerParameters(const std::string& xml) {
    printf( "ScannerParameters. %sn", xml.c_str());
}

 

public virtual void scannerParameters(string xml)
{
	Console.WriteLine("ScannerParameters. "+xml+"n");
}

 

Public Sub scannerParameters(xml As String) Implements IBApi.EWrapper.scannerParameters
	Console.WriteLine("ScannerParameters. " & xml & "n")
End Sub

 

Market Scanner Subscription

All values used for the ScannerSubscription object are pulled from EClient.scannerParams response. The XML tree will relay a tree containing a corresponding code to each ScannerSubscription field as documented below.

instrument: <ScanParameterResponse> <InstrumentList> <Instrument> <type>

Location Code: <ScanParameterResponse> <LocationTree> <Location> <LocationTree> <Location> <locationCode>

Scan Code: <ScanParameterResponse> <ScanTypeList> <ScanType> <scanCode>

Subscription Options should be an empty array of TagValues.

Filter Options: <ScanParameterResponse> <FilterList> <RangeFilter> <AbstractField> <code>

 

ScannerSubscription()

 

Instrument: String. Instrument Type to use.

Location Code: String. Country or region for scanner to search.

Scan Code: String. Value for scanner to sort by.

Subscription Options: Array of TagValues. For internal use only.

Filter Options: Array of TagValues. Contains an array of TagValue objects which filters the scanner subscription.

Request Market Scanner Subscription

EClient.reqScannerSubscription (

reqId: int. Request identifier used for tracking data.

subscription: ScannerSubscription. Object containing details on what values should be used to construct and sort the list.

scannerSubscriptionOptions: List. Internal use only.

scannerSubscriptionFilterOptions: List. List of values used to filter the results of the scanner subscription. May result in an empty scanner response from over-filtering.
)

Starts a subscription to market scan results based on the provided parameters.

self.reqScannerSubscription(7002, scannerSubscription, [], filterTagvalues)

 

client.reqScannerSubscription(7002, scannerSubscription, null, FilterTagValues);

 

m_pClient->reqScannerSubscription(7002, scannerSubscription, TagValueListSPtr(), filterTagValues);

 

client.reqScannerSubscription(7002, scannerSubscription, null, filterTagValues);

 

client.reqScannerSubscription(7002, scannerSubscription, Nothing, filterTagValues)

 

Receive Market Scanner Subscription

EWrapper.scannerData (

reqid: int. Request identifier used to track data.

rank: int. The ranking position of the contract in the scanner sort.

contractDetails: ContractDetails. Contract object of the resulting object.

distance: String. Internal use only.

benchmark: String. Internal use only.

projection: String. Internal use only.

legStr: String. Describes the combo legs when the scanner is returning EFP
)

Provides the data resulting from the market scanner request.

def scannerData(self, reqId: int, rank: int, contractDetails: ContractDetails, distance: str, benchmark: str, projection: str, legsStr: str):
	print("ScannerData. ReqId:", reqId, ScanData(contractDetails.contract, rank, distance, benchmark, projection, legsStr))

 

@Override
public void scannerData(int reqId, int rank, ContractDetails contractDetails, String distance, String benchmark, String projection, String legsStr) {
	System.out.println("ScannerData: " + EWrapperMsgGenerator.scannerData(reqId, rank, contractDetails, distance, benchmark, projection, legsStr));
}

 

void TestCppClient::scannerData(int reqId, int rank, const ContractDetails& contractDetails, const std::string& distance, const std::string& benchmark, const std::string& projection, const std::string& legsStr) {
    printf( "ScannerData. %d - Rank: %d, Symbol: %s, SecType: %s, Currency: %s, Distance: %s, Benchmark: %s, Projection: %s, Legs String: %sn", reqId, rank, contractDetails.contract.symbol.c_str(), contractDetails.contract.secType.c_str(), contractDetails.contract.currency.c_str(), distance.c_str(), benchmark.c_str(), projection.c_str(), legsStr.c_str());
}

 

public virtual void scannerData(int reqId, int rank, ContractDetails contractDetails, string distance, string benchmark, string projection, string legsStr)
{
	Console.WriteLine("ScannerData. "+reqId+" - Rank: "+rank+", Symbol: "+contractDetails.Contract.Symbol+", SecType: "+contractDetails.Contract.SecType+", Currency: "+contractDetails.Contract.Currency +", Distance: "+distance+", Benchmark: "+benchmark+", Projection: "+projection+", Legs String: "+legsStr);
}

 

Public Sub scannerData(reqId As Integer, rank As Integer, contractDetails As IBApi.ContractDetails, distance As String, benchmark As String, projection As String, legsStr As String) Implements IBApi.EWrapper.scannerData
	Console.WriteLine("ScannerData. " & reqId & " - Rank: " & rank & ", : " & contractDetails.Contract.Symbol & ", SecType: " &contractDetails.Contract.SecType & ", Currency: " & contractDetails.Contract.Currency & ", Distance: " & distance & ", Benchmark: " & benchmark & ", Projection: " & projection & ", Legs String: " & legsStr)
End Sub

 

Cancel Market Scanner Subscription

EClient.cancelScannerSubscription (

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

Cancels the specified scanner subscription using the tickerId.

self.cancelScannerSubscription(7003)

 

client.cancelScannerSubscription(7003);

 

m_pClient->cancelScannerSubscription(7002);

 

client.cancelScannerSubscription(7003);

 

client.cancelScannerSubscription(7003)

 

Order Management

Commission Report

When an order is filled either fully or partially, the IBApi.EWrapper.execDetails and IBApi.EWrapper.commissionReport events will deliver IBApi.Execution and IBApi.CommissionReport objects. This allows to obtain the full picture of the order’s execution and the resulting commissions.

  • Advisors executing allocation orders will receive execution details and commissions for the allocation order itself. To receive allocation details and commissions for a specific subaccount IBApi.EClient.reqExecutions can be used.

EWrapper.commissionReport (

commissionReport: CommissionReport. Returns a commissions report object containing the fields execId, commission, currency, realizedPnl, yield, and yieldRedemptionDate.
)

Provides the CommissionReport of an Execution

def commissionReport(self, commissionReport: CommissionReport):
    print("CommissionReport.", commissionReport)

 

@Override
public void commissionReport(CommissionReport commissionReport) {
     System.out.println(EWrapperMsgGenerator.commissionReport(commissionReport));
}

 

void TestCppClient::commissionReport( const CommissionReport& commissionReport) {
    printf( "CommissionReport. %s - %s %s RPNL %sn", commissionReport.execId.c_str(), Utils::doubleMaxString(commissionReport.commission).c_str(), commissionReport.currency.c_str(), Utils::doubleMaxString(commissionReport.realizedPNL).c_str());
}

 

public virtual void commissionReport(CommissionReport commissionReport)
{
  Console.WriteLine("CommissionReport. " + commissionReport.ExecId + " - " + Util.DoubleMaxString(commissionReport.Commission) + " " + commissionReport.Currency + " RPNL " + Util.DoubleMaxString(commissionReport.RealizedPNL));
}

 

Public Sub commissionReport(commissionReport As IBApi.CommissionReport) Implements IBApi.EWrapper.commissionReport
  Console.WriteLine("CommissionReport -