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..
Visit IBKR U.K. Open an IBKR U.K. Account