Your last question had more information, I upvoted so I could find it but it disappeared. I will just fix up that code so you can see how it works in interaction with the API.
There are at least 2 ways to get option contracts. The first is just ask for them but don't fill out all the parameters, then contractDetails will return all matching contracts. The second is to just ask for all parameters but you won't know if all contracts are traded.
I put numbers in the code comments for an idea of how the program flow works.
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.common import TickerId, SetOfFloat, SetOfString, MarketDataTypeEnum
from ibapi.contract import Contract, ContractDetails
from ibapi.ticktype import TickType
class TestApp(EClient, EWrapper):
def __init__(self):
EClient.__init__(self, self)
self.underlyingContract = None
self.opts = []
self.optParams = ()
self.greeks = []
def error(self, reqId:TickerId, errorCode:int, errorString:str):
print("Error: ", reqId, "", errorCode, "", errorString)
def nextValidId(self, orderId):
self.start() #1
def contractDetails(self, reqId:int, contractDetails:ContractDetails, ):
if contractDetails.contract.secType == "OPT":#2,3 (2 contracts, P+C)
self.opts.append(contractDetails.contract)
if contractDetails.contract.secType == "STK":#4
self.underlyingContract = contractDetails.contract
self.reqSecDefOptParams(3,self.underlyingContract.symbol,"","STK",
self.underlyingContract.conId)#5
def contractDetailsEnd(self, reqId):
print("\ncontractDetails End\n")#3,4
def securityDefinitionOptionParameter(self, reqId:int, exchange:str,
underlyingConId:int, tradingClass:str, multiplier:str,
expirations:SetOfString, strikes:SetOfFloat):
#6
self.optParams = (exchange, underlyingConId, tradingClass, multiplier, expirations, strikes)
def securityDefinitionOptionParameterEnd(self, reqId:int):
print("SecurityDefinitionOptionParameterEnd. ReqId",reqId)
# make a contract out of params or just use contract from earlier
if len(self.opts) > 0:
self.reqMktData(4,self.opts[0],"",False,False,[])#7
def tickOptionComputation(self, reqId:TickerId, tickType:TickType,
impliedVol:float, delta:float, optPrice:float, pvDividend:float,
gamma:float, vega:float, theta:float, undPrice:float):
self.greeks.append([optPrice,delta,impliedVol,undPrice]) #8
# just stop after first callback but you could set a time or something else
# if you don't get data, the program won't end unless you ctrl-c or something
self.stop() #9
def start(self):
# get some option contracts, not all
opts = Contract()
opts.symbol = 'AAPL'
opts.secType = 'OPT'
opts.exchange = 'SMART'
opts.currency = 'USD'
opts.strike="140"
#opts.right="P" # ambiguous so as to get multiple contracts
opts.multiplier="100"
opts.lastTradeDateOrContractMonth = '20211015'
self.reqContractDetails(1, opts) #2
# get just underlying conId
underlying = Contract()
underlying.symbol = 'AAPL'
underlying.secType = 'STK'
underlying.exchange = 'SMART'
underlying.currency = 'USD'
self.reqContractDetails(2, underlying) #4
# in case you don't have data subscription
self.reqMarketDataType(MarketDataTypeEnum.DELAYED)
def stop(self):
self.disconnect() #10
app = TestApp()
app.connect("127.0.0.1", 7497, 123)
app.run() # starts a reader thread that will block until disconnect()
#11 after disconnect, program can continue
# I just do this so I can use spyder variable inspector but you could print
uc = app.underlyingContract
opts = app.opts
params = app.optParams
greeks = app.greeks