Study Notes:
In this lesson, we will be discussing the TWS API Python essential components, and discussing them using the Contract Details request as an example. 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. I have installed the API and then opened the python source directory, IBAPI, as well as the python sample code directory, Testbed.
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 module, which I will discuss more later.
After importing my modules, I will now create a class to combine the two modules. I will simply type “class TestApp(EClient, EWrapper):”. Next, I will instantiate the class, as we will be using object-oriented programming going forward.
Now, I will create the EWrapper object for Contract Details, to receive my financial instrument data. I will type “def contractDetails” and include self, request ID, and contract Details as my arguments. And just for this sample, I will only be printing the contract details object, so I will type “print(f’contract details: {contractDetails}’)”. While it is not necessary, I will also include the contractDetailsEnd method, so that I have a safe place to disconnect my socket and acknowledge when I have received all of my data.
With our TestApp class created, I will start working on my Main method. After defining the method, I will add a variable to reference the TestApp class. Next, I will make a call to TestApp’s connect method. Here, I will title this as app.connect. Then I will reference our localhost as the host, then the port we set in TWS, 7497, and then a client ID – I have chosen to use 1000.
We can now begin building our contract. I want to request details for AAPL stock. To do so, I will first create my Contract object, or mycontract. Next, I will assign the symbol, AAPL, and set the security type, to STK. I am choosing to use Interactive Broker’s Smart Routing option as my exchange, and so I will set this to “Smart”. Because I am trading this on a U.S. exchange, I will use the United States Dollar as my currency. In the case of some contracts, they may be ambiguous from the symbol alone. And so, I will specify my primary exchange as NASDAQ, this is also sometimes known as ISLAND.
Now that I have my contract, I’m going to request my financial instrument details. However, I have found in my experience that my computer can typically run my request faster than a socket connection can be built. And so, I will be referencing Python’s “Time” module from earlier, to have my code sleep for 3 seconds. Now I am ready to request my contract details. The only arguments we need to provide are the request ID and our contract.
With everything set, I will create the EWrapper Run loop to receive all of my requested data. To do so, I only need to type “app.run()”. And then, outside of the main loop, I will make a call to the NAME-MAIN idiom.
Once I run my code, we can see our full contract details were returned, such as the contract object, as well as the long name, Apple Inc. Now the full contract details for an AAPL stock are rather verbose, so maybe I will want to request just the long name for some reason. To do so, I can edit my contractDetails object, to specifically return contractDetails.longName. And as you can see, we are now only returning the contract’s full name. There are many other attributes which you may uniquely request, which can be found in the contract.py file.
If I move over to my ibapi folder, and open the contract.py file, I can scroll down and see a variety of different attributes. For example, I may want to know the liquid trading hours for my contract, or if I traded options, I may want to see the expiration date.
There are a variety of other attributes that are useful, and I would advise reviewing this list to explore what else might be beneficial for you.
Option Contract
With that in mind, lets go ahead and create an options contract for Apple. I’ll start by removing the long name so we can receive the full contract. Then, I’ll change my security type to OPT for Option, and I’ll remove the primary exchange. I’ll also include a “Right”, which I will set to ‘C’ for a Call. If we were to make the options request now, we would receive all Call options for Apple. So it would be best to trim this list down. I would like to get a bit more granular by adding a lastTradeDateorContractMonth. Here, I will add a contract month for November 2022.
Now if I run this code, you will see a huge list of options. That is because I am not specifying a strike, nor am I specifying the exact expiration day. Because of this, we will want to get even more granular. And so, I will add a strike price of 125. And even with this specificity, I will still get 4 contracts returned. That means I would need to get even more granular than using the month of November and specify an exact expiration date.
Futures Contract
Now that we have an options contract, let’s now try to create a Futures contract. To do so, I’ll start by removing my Right, as well as my strike price. I’m also going to use DAX for my symbol, and set my security type to FUT. I’ll change my exchange to EUREX, and my currency to EUR. We will also want to edit our contract so that our expiration is set for December.
If we run this request, we will still receive 3 different contracts, and that’s because of their multiplier. We have essentially received DAX, DAX Mini, and DAX Micro futures. So to get more granular, I will add a multiplier to my contract. And so I will set mycontract.multipler equal to ‘1’. If we run this request again, we will only receive 1 contract for our DAX future.
You may be thinking that this is a lot of information you need to specify any time you would like to place a trade, particularly for Options or Futures. However, this information can be bundled into a single field, known as the Contract ID, or conId. We can see this as a series of numbers inside of our contract object. If instead of my other fields, I simple specify ‘mycontract.conId’ to this value, we can see that is the only field I need. Because of this, after you know your full contract details, Interactive Brokers strongly advises that you use this field for your other requests, like requesting market data or placing orders.
However, that concludes our video on the TWS API Essentials and the ContractDetails Requests. Thank you for watching, and we look forward to having you join us for mor TWS Python API lessons.
Financial Instruments (Contracts)
Code Snippets
Stock Contract
from ibapi.client import * from ibapi.wrapper import * import time class TestApp(EClient, EWrapper): def __init__(self): EClient.__init__(self, self) def contractDetails(self, reqId, contractDetails): print(f"contract details: {contractDetails}") def contractDetailsEnd(self, reqId): print("End of contractDetails") self.disconnect() def main(): app = TestApp() app.connect("127.0.0.1", 7497, 1000) mycontract = Contract() mycontract.symbol = "AAPL" mycontract.secType = "STK" mycontract.exchange = "SMART" mycontract.currency = "USD" mycontract.primaryExchange = "ISLAND" time.sleep(3) app.reqContractDetails(1, mycontract) app.run() if __name__ == "__main__": main()
Futures Contract
from ibapi.client import * from ibapi.wrapper import * import time class TestApp(EClient, EWrapper): def __init__(self): EClient.__init__(self, self) def contractDetails(self, reqId, contractDetails): print(f"contract details: {contractDetails}") def contractDetailsEnd(self, reqId): print("End of contractDetails") self.disconnect() def main(): app = TestApp() app.connect("127.0.0.1", 7497, 1000) mycontract = Contract() mycontract.symbol = "DAX" mycontract.secType = "FUT" mycontract.exchange = "EUREX" mycontract.currency = "EUR" mycontract.lastTradeDateOrContractMonth = "202212" mycontract.multiplier = 1 # Or you can use just the Contract ID # mycontract.conId = 552142063 time.sleep(3) app.reqContractDetails(1, mycontract) app.run() if __name__ == "__main__": main()
Option Contract
from ibapi.client import * from ibapi.wrapper import * import time class TestApp(EClient, EWrapper): def __init__(self): EClient.__init__(self, self) def contractDetails(self, reqId, contractDetails): print(f"contract details: {contractDetails}") def contractDetailsEnd(self, reqId): print("End of contractDetails") self.disconnect() def main(): app = TestApp() app.connect("127.0.0.1", 7497, 1000) mycontract = Contract() mycontract.symbol = "AAPL" mycontract.secType = "OPT" mycontract.exchange = "SMART" mycontract.currency = "USD" mycontract.right = "C" mycontract.lastTradeDateOrContractMonth = "202211" mycontract.strike = 125 time.sleep(3) app.reqContractDetails(1, mycontract) app.run() if __name__ == "__main__": main()
there are errors in output –should we ignore it ?
akotak@Ankitkumars-MacBook-Pro IBJts % /usr/bin/python3 /Users/akotak/Downloads/AlgoTrading/IBJ
ts/source/pythonclient/tests/lesson_3.py
ERROR -1 2104 Market data farm connection is OK:usfarm.nj
ERROR -1 2104 Market data farm connection is OK:cashfarm
ERROR -1 2104 Market data farm connection is OK:usfarm
ERROR -1 2106 HMDS data farm connection is OK:ushmds
ERROR -1 2158 Sec-def data farm connection is OK:secdefil
contract details: 265598,AAPL,STK,,0,,,SMART,NASDAQ,USD,AAPL,NMS,False,,,,combo:,NMS,0.01,ACTIVETIM,AD,ADJUST,ALERT,ALGO,ALLOC,AON,AVGCOST,BASKET,BENCHPX,CASHQTY,COND,CONDORDER,DARKONLY,DARKPOLL,DAY,DEACT,DEACTDIS,DEACTEOD,DIS,DUR,GAT,GTC,GTD,GTT,HID,IBKRATS,ICE,IMB,IOC,LIT,LMT,LOC,MIDPX,MIT,MKT,MOC,MTL,NGCOMB,NODARK,NONALGO,OCA,OPG,OPGREROUT,PEGBENCH,PEGMID,POSTATS,POSTONLY,PREOPGRTH,PRICECHK,REL,REL2MID,RELPCTOFS,RPI,RTH,SCALE,SCALEODD,SCALERST,SIZECHK,SMARTSTG,SNAPMID,SNAPMKT,SNAPREL,STP,STPLMT,SWEEP,TRAIL,TRAILLIT,TRAILLMT,TRAILMIT,WHATIF,SMART,AMEX,NYSE,CBOE,PHLX,ISE,CHX,ARCA,ISLAND,DRCTEDGE,BEX,BATS,EDGEA,CSFBALGO,JEFFALGO,BYX,IEX,EDGX,FOXRIVER,PEARL,NYSENAT,LTSE,MEMX,IBEOS,OVERNIGHT,PSX,1,0,APPLE INC,,Technology,Computers,Computers,US/Eastern,20230819:CLOSED;20230820:CLOSED;20230821:0400-20230821:2000;20230822:0400-20230822:2000;20230823:0400-20230823:2000;20230824:0400-20230824:2000,20230819:CLOSED;20230820:CLOSED;20230821:0930-20230821:1600;20230822:0930-20230822:1600;20230823:0930-20230823:1600;20230824:0930-20230824:1600,,0,,,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,1,[4311536688: ISIN=US0378331005;],,COMMON,,,,,,False,False,0,False,,,,,False,,0.0001,0.0001,100
End of contractDetails
akotak@Ankitkumars-MacBook-Pro IBJts %
Hello Ankit, thank you for reaching out. All supported API programming languages offer call back functions to receive error messages sent from the TWS for troubleshooting purposes. Socket-based APIs (e.g., C#, Java, VB.Net, C++, Python and ActiveX) handle error messages within the error() call back function in the EWrapper interface. For additional information, including a list of message codes, please review our API documentation. We hope this helps!
If your query is still not answered after reviewing the documentation, please create a web ticket in Client Portal with the category “API.” Our experts will be glad to help you out!
I directly copied the futures contract and received the error:
ERROR 1 200 No security definition has been found for the request
Im not sure where this is coming from or what it means
Hello Paul, thank you for reaching out. This error message is triggered to indicate the contract definition provided in your RTD formula cannot be found by TWS. Please view this User Guide for more information: https://interactivebrokers.github.io/tws-api/rtd_fqa_errors.html
Please reach back out if you have any more questions. We are here to help!
how to restrict the option contract for a particular date, not the all valid dates in the whole month? E.g. if on 1/Jan/2024, I only want to request data from the IB server for the SPY option contract expiry on that date?
Hello Nathan, thank you for reaching out. The contract specifications can be as precise or vague as needed in the TWS API. Our example assumed you have no knowledge of the expiration, so we look at the whole month of November. If you know an expiration is taking place on January 1st, 2024, you could set mycontract.lastTradeDateOrContractMonth = “20240101” to include the year, month, and day of the expiration. Please reach back out if you have more questions. We are here to help!
I have the same issue as Paul, which I understand, however one I get the “ERROR 1 200 No security definition has been found for the request”, the code continues to run in this infinite loop and I have to restart the kernel to stop it. I am using a Jupyter Notebook. Is there a way to stop it if this error occurs? Thanks
Hello, thank you for reaching out. For this situation, we recommend creating a web ticket to contact our API experts. They would be happy to help.
https://www.interactivebrokers.com/sso/resolver?action=NEW_TICKET
Hello, how can the forex contract be viewed?
Hello, thank you for reaching out. Forex contracts are constructed by setting the symbol to the target currency, while the ‘currency’ value is equal to the base. In an example of EUR.USD pairs, we would set the symbol, or target currency, to ‘EUR’ while our base currency value would be ‘USD’. You can find more details on contracts in our documentation here: https://ibkrcampus.com/ibkr-api-page/contracts/#forex. We hope this helps!
Fyi if you directly copy paste the futures example and run it, you will get an error. This is because you are trying to pull contract details for the DAX future with expiry 2022 which is too far in the past. Try updating the year to the current or next year and it should work.