Options valuation seems more an art than a discipline.
I am trying at the moment to understand the differences in implied volatility among different strikes and expiry dates.
As a first step, I’ve decided to download the options chain from IB in order to analyze it.
Here it is the code I am going to use for this task.
""" This script will access the IB API and download to excel the option chain for the underlying entered in the excel file """ #=============================================================================== # LIBRARIES #=============================================================================== from ib.opt import ibConnection, message from ib.ext.Contract import Contract import quantacademy.excel_management as excel import pandas as pd from time import sleep from collections import defaultdict #=============================================================================== # Class IB_API #=============================================================================== class IB_API: """ This class will establish a connection to IB and group the different operations """ # Variables d_ticker_reqId = {} reqId = 1 d_opt_contracts = defaultdict(dict) d_contracts = {} # Functions def __init__(self): """ Connection to the IB API """ print "Calling connection" # Creation of Connection class self.connection = ibConnection() # Register data handlers self.connection.registerAll(self.process_messages) # Connect self.connection.connect() def process_messages(self, msg): """ Function that indicates how to process each different message """ if msg.typeName == "contractDetails": print msg opt_contract = msg.values()[1] self.save_option_contracts_to_dict(opt_contract) elif msg.typeName == "tickPrice": field = msg.values()[1] price = msg.values()[2] localSymbol = self.d_ticker_reqId[msg.values()[0]].m_localSymbol if field == 1: self.d_opt_contracts[localSymbol]['bid'] = str(price) elif field == 2: self.d_opt_contracts[localSymbol]['ask'] = str(price) elif field == 9: self.d_opt_contracts[localSymbol]['close'] = str(price) elif msg.typeName == "tickOptionComputation": localSymbol = self.d_ticker_reqId[msg.values()[0]].m_localSymbol field = msg.values()[1] price = msg.values()[2] delta = msg.values()[3] impliedVolatility = msg.values()[4] optPrice = msg.values()[5] pvDividend = msg.values()[6] gamma = msg.values()[7] vega = msg.values()[8] theta = msg.values()[9] undPrice = None if field == 10: self.d_opt_contracts[localSymbol]['bid_delta'] = str(delta) self.d_opt_contracts[localSymbol]['bid_impliedVolatility'] = str(impliedVolatility) self.d_opt_contracts[localSymbol]['bid_optPrice'] = str(optPrice) self.d_opt_contracts[localSymbol]['bid_pvDividend'] = str(pvDividend) self.d_opt_contracts[localSymbol]['bid_gamma'] = str(gamma) self.d_opt_contracts[localSymbol]['bid_vega'] = str(vega) self.d_opt_contracts[localSymbol]['bid_theta'] = str(theta) self.d_opt_contracts[localSymbol]['bid_undPrice'] = str(undPrice) elif field == 11: self.d_opt_contracts[localSymbol]['ask_delta'] = str(delta) self.d_opt_contracts[localSymbol]['ask_impliedVolatility'] = str(impliedVolatility) self.d_opt_contracts[localSymbol]['ask_optPrice'] = str(optPrice) self.d_opt_contracts[localSymbol]['ask_pvDividend'] = str(pvDividend) self.d_opt_contracts[localSymbol]['ask_gamma'] = str(gamma) self.d_opt_contracts[localSymbol]['ask_vega'] = str(vega) self.d_opt_contracts[localSymbol]['ask_theta'] = str(theta) self.d_opt_contracts[localSymbol]['ask_undPrice'] = str(undPrice) elif field == 24: self.d_opt_contracts[localSymbol]['iv'] = str(price) else: print msg def get_contract_details(self, reqId, contract_values): """ Call for all the options contract for the underlying """ print "Calling Contract Details" # Contract creation contract = Contract() contract.m_symbol = contract_values['m_symbol'] contract.m_exchange = contract_values['m_exchange'] contract.m_secType = contract_values['m_secType'] # If expiry is empty it will download all available expiries if contract_values['m_expiry'] <> "": contract.m_expiry = contract_values['m_expiry'] self.connection.reqContractDetails(reqId, contract) sleep(20) def get_market_data(self): """ Call for all the options prices and greeks """ print "Calling Market Data" self.reqId = 1 # Loop through all options contracts for option in self.d_contracts.values(): self.d_ticker_reqId[self.reqId] = option self.connection.reqMktData(self.reqId, option, None, True) self.reqId += 1 sleep(1) sleep(10) def save_option_contracts_to_dict(self, opt_contract): """ It saves the options contracts downloaded as ContractDetails object to a dictionary of dictionaries """ self.d_opt_contracts[opt_contract.m_summary.m_localSymbol]['m_conId']=opt_contract.m_summary.m_conId self.d_opt_contracts[opt_contract.m_summary.m_localSymbol]['m_symbol']=opt_contract.m_summary.m_symbol self.d_opt_contracts[opt_contract.m_summary.m_localSymbol]['m_secType']=opt_contract.m_summary.m_secType self.d_opt_contracts[opt_contract.m_summary.m_localSymbol]['m_expiry']=opt_contract.m_summary.m_expiry self.d_opt_contracts[opt_contract.m_summary.m_localSymbol]['m_strike']=opt_contract.m_summary.m_strike self.d_opt_contracts[opt_contract.m_summary.m_localSymbol]['m_right']=opt_contract.m_summary.m_right self.d_opt_contracts[opt_contract.m_summary.m_localSymbol]['m_multiplier']=opt_contract.m_summary.m_multiplier self.d_opt_contracts[opt_contract.m_summary.m_localSymbol]['m_exchange']=opt_contract.m_summary.m_exchange self.d_opt_contracts[opt_contract.m_summary.m_localSymbol]['m_currency']=opt_contract.m_summary.m_currency self.d_opt_contracts[opt_contract.m_summary.m_localSymbol]['m_localSymbol']=opt_contract.m_summary.m_localSymbol """ It saves the options contracts downloaded as ContractDetails object to a dictionary of contracts """ self.d_contracts[opt_contract.m_summary.m_localSymbol] = Contract() self.d_contracts[opt_contract.m_summary.m_localSymbol].m_conId=opt_contract.m_summary.m_conId self.d_contracts[opt_contract.m_summary.m_localSymbol].m_symbol=opt_contract.m_summary.m_symbol self.d_contracts[opt_contract.m_summary.m_localSymbol].m_secType=opt_contract.m_summary.m_secType self.d_contracts[opt_contract.m_summary.m_localSymbol].m_expiry=opt_contract.m_summary.m_expiry self.d_contracts[opt_contract.m_summary.m_localSymbol].m_strike=opt_contract.m_summary.m_strike self.d_contracts[opt_contract.m_summary.m_localSymbol].m_right=opt_contract.m_summary.m_right self.d_contracts[opt_contract.m_summary.m_localSymbol].m_multiplier=opt_contract.m_summary.m_multiplier self.d_contracts[opt_contract.m_summary.m_localSymbol].m_exchange=opt_contract.m_summary.m_exchange self.d_contracts[opt_contract.m_summary.m_localSymbol].m_currency=opt_contract.m_summary.m_currency self.d_contracts[opt_contract.m_summary.m_localSymbol].m_localSymbol=opt_contract.m_summary.m_localSymbol if __name__ == '__main__': # Connection ib = IB_API() # Get contract details filename = excel.select_excel_file() xl = pd.ExcelFile(filename) df_input = xl.parse('input') #contract_values = {'m_symbol': 'TLT', 'm_exchange': 'SMART', 'm_secType': 'OPT', # 'm_expiry': '20140905'} contract_values = { 'm_symbol': str(df_input['m_symbol'][0]), 'm_exchange': str(df_input['m_exchange'][0]), 'm_secType': str(df_input['m_secType'][0]), 'm_expiry': str(df_input['m_expiry'][0]) } ib.get_contract_details(1, contract_values) # Get Market values ib.get_market_data() print ib.d_opt_contracts # Output columns_after_hours = [ 'm_conId', 'm_localSymbol', 'm_symbol', 'm_currency', 'm_exchange', 'm_secType', 'm_multiplier', 'm_right', 'm_strike', 'm_expiry', 'close', 'bid', 'ask' ] columns_open_market = [ 'bid_impliedVolatility', 'ask_impliedVolatility', 'bid_delta', 'ask_delta', 'bid_theta', 'ask_theta', 'bid_gamma', 'ask_gamma', 'bid_pvDividend', 'ask_pvDividend', 'bid_vega', 'ask_vega', 'bid_optPrice', 'ask_optPrice', 'bid_undPrice', 'ask_undPrice' ] df_option_chain = pd.DataFrame(ib.d_opt_contracts) df_option_chain = df_option_chain.T # Check if market is open if 'bid_impliedVolatility' in df_option_chain.columns: df_option_chain = df_option_chain[columns_after_hours + columns_open_market] else: df_option_chain = df_option_chain[columns_after_hours] # Save in a new excel tab excel.save_in_new_tab_of_excel(filename, df_option_chain, "option_chain") |
hello,
thanks for posting the code. I am using C# but perhaps you can help me anyway. I am inside the contractDetails callback for getting an options chain. At this point I want to get the market data such as underlying price, implied volatility etc…
BUT this opens up a ton of realtime connections … how can I fill out all of the data and manage these connections properly.
Do you have to write some code to chunk it? I looked at your python code, but I’m not seeing how you are doing that there.. that is managing the connections.
-Nick
Hi Nick,
sorry for replying so late. I was very busy working in a project and I left this blog during it. I come back now.
Hopefully you have already solved this issue. But just in case, I tell you how I managed it (if I have understood well the question).
I first call the ContractDetails function, for getting the information of all options contracts. Then I wait for 20 seconds. You can see it in my get_contract_details function. After this time I must have received all contract data, so then it is when I require Market Data.
The connection is always one, but I am making many requirements. Each one I send it with a different Id (reqId) and I store to which contract it belongs, so afterwards, when I receive the data I can link them.
I don’t know if there is a better way, but this one works. Tell me if I can help you further or if you have found a better way of managing it.
Thanks for writing,
Ricardo
You can use this tool to download historical options data from Interactive Brokers. It lets you choose which options expiration and strikes you want to download and downloads them all in parallel.
http://www.tradinggeeks.net/downloads/ib-data-downloader/
Hi,
When I try to call:
ib.get_contract_details(1, contract_values)
I get the error:
AttributeError: IB_API instance has no attribute ‘get_contract_details’
Any ideas?
Thanks,
Matt
Hi Matt,
thanks for commenting. I am not using at this moment this code, IB might have change its API. It worked when I used it. I will check it again and tell you.
Regards
Hi,
I am also getting an error at:
import quantacademy.excel_management as excel
Thanks,
Matt
Hi,
which error are you getting?
Have you downloaded the code in http://www.quantacademy.com/2014/07/excel-management-with-python-pandas/ and store it in a folder called “quantacademy”?
Regards
Are you aware that posted code has no identation at all? In most cases is easy to add when reading the code, but there could be some ambiguities
Nice effort BTW, I will test this IB connection this evening to see if I can use this code at my option analyzer code
Thank you Roman, you are right. I hadn’t realized.
Interactive Brokers posted a recorded webiniar at youtube on Dec 13 2016 about IBridgePy, a flexiable and easy-to-use Python tool to trade at IB. It can handle option chains easily.
https://www.youtube.com/watch?v=hogXB07OJ_I
Thank you
I am using this. It works great for me.
https://marketxls.com/utilities-and-apps/
Thanks a lot Harrison. I will test it.
My pleasure. Hope it helps. 🙂
I had use MarketXLS. It works great for me.
https://marketxls.com/utilities-and-apps/