I need help retrieving the option chain for EMINI contracts using the latest IBKR API in Python. My setup:
Environment: Spyder on Windows
Requirements: Retrieve contract ID, Greeks, and price based on expiry, strike, and option type (Call/Put). Store data in a pandas DataFrame for future use.
Could you provide guidance or sample code for this?
I have tried using ChatGPT and other forums but could not find a solution.
<code>from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.contract import Contract
from ibapi.ticktype import TickTypeEnum
import threading
import time
class IBApiWrapper(EWrapper):
def __init__(self):
super().__init__()
self.expiry_dates = []
def error(self, reqId, errorCode, errorString):
print(f"Error. Id: {reqId}, Code: {errorCode}, Msg: {errorString}")
def contractDetails(self, reqId, contractDetails):
expiry = contractDetails.contract.lastTradeDateOrContractMonth
self.expiry_dates.append(expiry)
print(f"Contract Details. ReqId: {reqId}, Expiry: {expiry}")
def tickPrice(self, reqId, tickType, price, attrib):
print(f"Tick Price. Ticker Id: {reqId}, Type: {TickTypeEnum.to_str(tickType)}, Price: {price}")
def tickSize(self, reqId, tickType, size):
print(f"Tick Size. Ticker Id: {reqId}, Type: {TickTypeEnum.to_str(tickType)}, Size: {size}")
class IBApiClient(EClient):
def __init__(self, wrapper):
super().__init__(wrapper)
class IBApiApp(IBApiWrapper, IBApiClient):
def __init__(self):
IBApiWrapper.__init__(self)
IBApiClient.__init__(self, wrapper=self)
def start(self):
self.connect("127.0.0.1", 7496, clientId=1)
thread = threading.Thread(target=self.run)
thread.start()
setattr(self, "_thread", thread)
time.sleep(1)
if not self.isConnected():
print("Failed to connect")
return
# Create contract for GOOGL option to retrieve expiry dates
contract = Contract()
contract.symbol = "ES"
contract.secType = "OPT"
contract.exchange = "GLOBEX"
contract.currency = "USD"
contract.right = "C" # Call option
# Request contract details to get expiry dates
self.reqContractDetails(1, contract)
def stop(self):
self.disconnect()
self._thread.join()
def request_option_data(self, expiry):
# Create contract for specific expiry
contract = Contract()
contract.symbol = "ES"
contract.secType = "OPT"
contract.exchange = "GLOBEX"
contract.currency = "USD"
contract.lastTradeDateOrContractMonth = expiry
contract.strike = 5500
contract.right = "C"
contract.multiplier = "50"
# Request Market Data
self.reqMarketDataType(1) # Switch to live (1) frozen (2) delayed (3) delayed frozen (4)
self.reqMktData(1, contract, "", False, False, [])
def main():
app = IBApiApp()
app.start()
# Give time to receive contract details and determine the next two expiry dates
time.sleep(10)
if len(app.expiry_dates) >= 2:
next_two_expiries = app.expiry_dates[:2]
for expiry in next_two_expiries:
app.request_option_data(expiry)
else:
print("Could not retrieve enough expiry dates")
# Keep the script running to receive data
time.sleep(20)
app.stop()
if __name__ == "__main__":
main()
</code>
<code>from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.contract import Contract
from ibapi.ticktype import TickTypeEnum
import threading
import time
class IBApiWrapper(EWrapper):
def __init__(self):
super().__init__()
self.expiry_dates = []
def error(self, reqId, errorCode, errorString):
print(f"Error. Id: {reqId}, Code: {errorCode}, Msg: {errorString}")
def contractDetails(self, reqId, contractDetails):
expiry = contractDetails.contract.lastTradeDateOrContractMonth
self.expiry_dates.append(expiry)
print(f"Contract Details. ReqId: {reqId}, Expiry: {expiry}")
def tickPrice(self, reqId, tickType, price, attrib):
print(f"Tick Price. Ticker Id: {reqId}, Type: {TickTypeEnum.to_str(tickType)}, Price: {price}")
def tickSize(self, reqId, tickType, size):
print(f"Tick Size. Ticker Id: {reqId}, Type: {TickTypeEnum.to_str(tickType)}, Size: {size}")
class IBApiClient(EClient):
def __init__(self, wrapper):
super().__init__(wrapper)
class IBApiApp(IBApiWrapper, IBApiClient):
def __init__(self):
IBApiWrapper.__init__(self)
IBApiClient.__init__(self, wrapper=self)
def start(self):
self.connect("127.0.0.1", 7496, clientId=1)
thread = threading.Thread(target=self.run)
thread.start()
setattr(self, "_thread", thread)
time.sleep(1)
if not self.isConnected():
print("Failed to connect")
return
# Create contract for GOOGL option to retrieve expiry dates
contract = Contract()
contract.symbol = "ES"
contract.secType = "OPT"
contract.exchange = "GLOBEX"
contract.currency = "USD"
contract.right = "C" # Call option
# Request contract details to get expiry dates
self.reqContractDetails(1, contract)
def stop(self):
self.disconnect()
self._thread.join()
def request_option_data(self, expiry):
# Create contract for specific expiry
contract = Contract()
contract.symbol = "ES"
contract.secType = "OPT"
contract.exchange = "GLOBEX"
contract.currency = "USD"
contract.lastTradeDateOrContractMonth = expiry
contract.strike = 5500
contract.right = "C"
contract.multiplier = "50"
# Request Market Data
self.reqMarketDataType(1) # Switch to live (1) frozen (2) delayed (3) delayed frozen (4)
self.reqMktData(1, contract, "", False, False, [])
def main():
app = IBApiApp()
app.start()
# Give time to receive contract details and determine the next two expiry dates
time.sleep(10)
if len(app.expiry_dates) >= 2:
next_two_expiries = app.expiry_dates[:2]
for expiry in next_two_expiries:
app.request_option_data(expiry)
else:
print("Could not retrieve enough expiry dates")
# Keep the script running to receive data
time.sleep(20)
app.stop()
if __name__ == "__main__":
main()
</code>
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.contract import Contract
from ibapi.ticktype import TickTypeEnum
import threading
import time
class IBApiWrapper(EWrapper):
def __init__(self):
super().__init__()
self.expiry_dates = []
def error(self, reqId, errorCode, errorString):
print(f"Error. Id: {reqId}, Code: {errorCode}, Msg: {errorString}")
def contractDetails(self, reqId, contractDetails):
expiry = contractDetails.contract.lastTradeDateOrContractMonth
self.expiry_dates.append(expiry)
print(f"Contract Details. ReqId: {reqId}, Expiry: {expiry}")
def tickPrice(self, reqId, tickType, price, attrib):
print(f"Tick Price. Ticker Id: {reqId}, Type: {TickTypeEnum.to_str(tickType)}, Price: {price}")
def tickSize(self, reqId, tickType, size):
print(f"Tick Size. Ticker Id: {reqId}, Type: {TickTypeEnum.to_str(tickType)}, Size: {size}")
class IBApiClient(EClient):
def __init__(self, wrapper):
super().__init__(wrapper)
class IBApiApp(IBApiWrapper, IBApiClient):
def __init__(self):
IBApiWrapper.__init__(self)
IBApiClient.__init__(self, wrapper=self)
def start(self):
self.connect("127.0.0.1", 7496, clientId=1)
thread = threading.Thread(target=self.run)
thread.start()
setattr(self, "_thread", thread)
time.sleep(1)
if not self.isConnected():
print("Failed to connect")
return
# Create contract for GOOGL option to retrieve expiry dates
contract = Contract()
contract.symbol = "ES"
contract.secType = "OPT"
contract.exchange = "GLOBEX"
contract.currency = "USD"
contract.right = "C" # Call option
# Request contract details to get expiry dates
self.reqContractDetails(1, contract)
def stop(self):
self.disconnect()
self._thread.join()
def request_option_data(self, expiry):
# Create contract for specific expiry
contract = Contract()
contract.symbol = "ES"
contract.secType = "OPT"
contract.exchange = "GLOBEX"
contract.currency = "USD"
contract.lastTradeDateOrContractMonth = expiry
contract.strike = 5500
contract.right = "C"
contract.multiplier = "50"
# Request Market Data
self.reqMarketDataType(1) # Switch to live (1) frozen (2) delayed (3) delayed frozen (4)
self.reqMktData(1, contract, "", False, False, [])
def main():
app = IBApiApp()
app.start()
# Give time to receive contract details and determine the next two expiry dates
time.sleep(10)
if len(app.expiry_dates) >= 2:
next_two_expiries = app.expiry_dates[:2]
for expiry in next_two_expiries:
app.request_option_data(expiry)
else:
print("Could not retrieve enough expiry dates")
# Keep the script running to receive data
time.sleep(20)
app.stop()
if __name__ == "__main__":
main()
New contributor
Praveen Kumar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.