Capital you invest is at risk. | Capital you invest is at risk.

Close Navigation
Learn more about IBKR accounts

Essential components of TWS API programs

Lesson of

Duration 8:58
Level Intermediate

Capital you invest is at risk. | Capital you invest is at risk.

To watch this video you must accept functional cookies.

Welcome to this lesson on the essential components of a TWS API Python program. This includes the API classes EClient and EWrapper, a function call to create a connection to TWS, and a run loop for processing returned messages in the queue. This lesson will also include a brief discussion of the nextValidId method, and we can implement threading. Finally, we’ll walk through our reqCurrentTime method to create a basic “Hello World” style script.

To begin, in any TWS API program you’ll always see two main classes, which would be EClient and EWrapper.  EClient is used for outgoing messages which are sent from the API program to TWS or the IB Gateway.  EWrapper is used to handle incoming messages from the Interactive Brokers server through TWS or IB Gateway.

For this lesson, I will be using Visual Studio Code. However, you can use any development environment of your choice, or even just the command lines and a text editor. To begin, I will start by importing the necessary modules. I will start by importing EClient, using “from ibapi.client import *” and EWrapper, using “from ibapi.wrapper import *”.  I will also be importing the time and threading modules, which we will touch on later.

After importing my modules, I will create a class to combine the EClient and EWrapper modules. I will type “class TestApp(EClient, EWrapper):”. Next, we instantiate the class by defining our init method with def __init__(self): followed by a newline EClient init request using EClient.__init__(self,self).

After our init, let’s create the EWrapper object for NextValidId(self, orderId): to receive order Ids. This will receive the EWrapper return of next valid order id, and retain valid session throughout the trading day to prevent duplicate values. Here, I can create an object for the order id, self.orderId = orderId. Now it may be confusing, but we can now make a new function, nextId, only retaining the object. Within the function, I will increment our newly made self.orderId value by 1, and then return the self.order variable. This way we can maintain the order Id throughout future requests and return the order id to our request.

We will circle back to some of the more elaborate EWrapper functionality in a moment. However, for now, we can just print out this id by creating our TestApp reference. All this takes is setting a variable, let’s use “app”, equal to the TestApp() class. Now, we’ll connect our app to Trader Workstation, by calling app.connect(“127.0.0.1”, 7497, 0). The values in this method are the host, port, and clientId.

Assuming your TWS is on the same machine where your API code is running, this will always be “127.0.0.1” or “localhost”. We have included a description of the standard port values in the transcript of this video. You can also review your TWS socket port setting in our prior video on setting up the Trader Workstation for API use. And then our client ID can be any value, as long as another client ID connection is not using the same value.

Platform

Port

TWS Live

7496

TWS Paper

7497

IBG Live

4001

IBG Paper

4002

With our connect methodology in place, we can implement a little bit of threading to get started. The simple implementation would be to call threading.Thread(target=app.run).start().

Please be aware that we reference the object of app.run, without including the parenthesis. Next, we’ll add a quick time.sleep(1) reference, to allow our object to instantiate before we start sending requests. This value will largely depend on your internal machine speed, so you increase or decrease this value as you see fit.

Then, as a quick test to show off our nextId method, we can use a for loop as the example.  I will write the loop as for I in range(0,5): and then printing the app.nextId() method each time. If we run this script as is, we should see some notifications indicating our connection is OK, followed by our printed ids. These request IDs are used throughout our programming and need to be uniquely assigned on each request. As a result, creating this reliable incrementation tool will be essential. 

We will explore this further through future videos.

But as a simple implementation of the EClient – EWrapper duality, we can move on to a call for the current time in Trader Workstation. Within our for loop, after our call for the nextId value, I will add a new request for app.reqCurrentTime(). This begins the initial request through EWrapper, but to capture the response, we should define the currentTime function within our class.

Calling def currentTime(self,time): we can receive our time value. Within the function, we can print our time value. This function will return the current epoch time observed in Trader Workstation. Epoch time is a single integer time representing the current timestamp in milliseconds. The connection between EClient.reqCurrentTime and EWrapper.currentTime will be an ongoing theme observed through nearly all endpoints used within the API. One external request will be met with one or more asynchronous responses.

One final method to create that will be used throughout the TWS API programming will be our EWrapper.error function. Error will automatically return any error generated by the Trader Workstation while processing your request. This will include values like invalid order formats, market data issues, and more. This will not reflect code issues or similar programming logic failures.

To define this, add the new definition for error within our TestApp class, containing the arguments for self, reqId, errorCode, errorString, and advancedOrderReject. While you are welcome to simply print all of these values directly, I will be adding context to each message through an f-string so we can quickly distinguish which value refers to which argument. If we run our script now, you’ll see various “error” messages. If we read the errorString value of these messages, we’ll realize these are just notifications mentioning that various market data connections are OK. While this method will largely capture error messages, we will receive system notifications such as the market data connectivity through EWrapper.error as well.

That concludes our lesson on the Essential Components of the TWS API. Thank you for watching. If you have any questions, please be sure to review our documentation or leave a comment below this video. We look forward to having you in the next lesson of our TWS API series.

Code Snippet – essentials.py

from ibapi.wrapper import *
import time
import threading

class TestApp(EClient, EWrapper):
  def __init__(self):
    EClient.__init__(self, self)
  
  def nextValidId(self, orderId):
    self.orderId = orderId
  
  def nextId(self):
    self.orderId += 1
    return self.orderId
  
  def currentTime(self, time):
    print(time)

  def error(self, reqId, errorCode, errorString, advancedOrderReject):
    print(f"reqId: {reqId}, errorCode: {errorCode}, errorString: {errorString}, orderReject: {advancedOrderReject}")

app = TestApp()
app.connect("127.0.0.1", 7497, 0)
threading.Thread(target=app.run).start()
time.sleep(1)

# for i in range(0,5):
#   print(app.nextId())
app.reqCurrentTime()

Join The Conversation

If you have a general question, it may already be covered in our FAQs page. go to: IBKR Ireland FAQs or IBKR U.K. FAQs. If you have an account-specific question or concern, please reach out to Client Services: IBKR Ireland or IBKR U.K..

Leave a Reply

Disclosure: Interactive Brokers

The analysis in this material is provided for information only and is not and should not be construed as an offer to sell or the solicitation of an offer to buy any security. To the extent that this material discusses general market activity, industry or sector trends or other broad-based economic or political conditions, it should not be construed as research or investment advice. To the extent that it includes references to specific securities, commodities, currencies, or other instruments, those references do not constitute a recommendation by IBKR to buy, sell or hold such investments. This material does not and is not intended to take into account the particular financial conditions, investment objectives or requirements of individual customers. Before acting on this material, you should consider whether it is suitable for your particular circumstances and, as necessary, seek professional advice.

The views and opinions expressed herein are those of the author and do not necessarily reflect the views of Interactive Brokers, its affiliates, or its employees.

Disclosure: API Examples Discussed

Throughout the lesson, please keep in mind that the examples discussed are purely for technical demonstration purposes, and do not constitute investment advice, an investment recommendation or investment research. Also, it is important to remember that placing trades in a paper account is recommended before any live trading.

This website uses cookies to collect usage information in order to offer a better browsing experience. By browsing this site or by clicking on the "ACCEPT COOKIES" button you accept our Cookie Policy.