emp has contributed to 32 posts out of 21251 total posts
(0.15%) in 4,778 days (0.01 posts per day).
20 Most recent posts:
thanks. Exporting from the options chains app worked fine for me. Gave the same result when I used the more time consuming method. But I have lost interest in option chains for the moment. At least this "Maximum Pain" method appears to be useless. It does not give accurate longer term predictions.
hi, thanks. Yes that is what I did. I exported the data to a CSV file and then processed that file with Python code. But I lost interest in the chains because I used them to do Max Pain calculations and I watched it for a while but it is basically pretty useless. It does not give predictions that are anywhere near accurate.
I opened a new thread for 1 question because my previous thread got cluttered with too many questions.
When I open the "IQFeed option chain" App, select "Futures Options" then type in the Futures symbols @ES and in the "Chains criteria" chose the month June and the year 2023 I almost instantly get a table with Open Interest numbers for all the options in the chain, see attached PDF.
When I however use my code below to access the Open Interest for all the option symbols in the chain it takes forever.
My question: is there a better way to access the open interest numbers. Maybe some automated way to save the data from the "IQFeed Option Chain" App to CSV files? How does IQFeed do this internally? I guess IQFeed stores these numbers somewhere where they can be accessed instantly in a table form?
thank you
# filesname: charpHistoricalDataTest.py # To run code IQFeed should be launched already # To run code type in the CMD window (path to python should be known) # python charpHistoricalDataTest.py
# Dynamically add IQFeed.CSharpApiClient DLL # for instructions see: https://github.com/mathpaquette/IQFeed.CSharpApiClient/blob/master/docs/USING-WITH-PYTHON.md import sys import clr assembly_path = r'C:/Program Files/AmiBroker/IQFeedCSharpApiClient' sys.path.append(assembly_path) clr.AddReference("IQFeed.CSharpApiClient") from System import DateTime from datetime import datetime, timedelta from IQFeed.CSharpApiClient.Lookup import LookupClientFactory from IQFeed.CSharpApiClient.Lookup.Chains import OptionSideFilterType import pandas as pd import matplotlib.pyplot as plt
lookupClient = LookupClientFactory.CreateNew() lookupClient.Connect()
def total_loss_at_strike(chainC, chainP, expiry_price): """Calculate loss at strike price""" # All call options with strike price below the expiry price will result in loss for option writers in_money_calls = chainC[chainC['Strike'] < expiry_price][["OpenInterest", "Strike"]] in_money_calls["CE loss"] = (expiry_price - in_money_calls['Strike'])*in_money_calls["OpenInterest"]
# All put options with strike price above the expiry price will result in loss for option writers in_money_puts = chainP[chainP['Strike'] > expiry_price][["OpenInterest", "Strike"]] in_money_puts["PE loss"] = (in_money_puts['Strike'] - expiry_price)*in_money_puts["OpenInterest"] total_loss = in_money_calls["CE loss"].sum() + in_money_puts["PE loss"].sum()
return total_loss
def createListofSymbolPlusStrikePrice(f_symbol, o_month, o_year, o_side): f_symbol = str(f_symbol) o_month = str(o_month) o_year = str(o_year)
if( o_side == 1): side = OptionSideFilterType.C if( o_side == 2): side = OptionSideFilterType.P
try: ticks = lookupClient.Chains.GetChainFutureOption( f_symbol, side, o_month, o_year ) symbollist = ' strikepricelist = ' for tt in ticks: symbollist += str(tt.Symbol) symbollist += ',' strikepricelist += str(tt.StrikePrice) #print(tt.StrikePrice) strikepricelist += ','
# remove last comma symbollist = symbollist[:len(symbollist)-1] except Exception as err: print(f"Unexpected {err=}, {type(err)=}")
return symbollist,strikepricelist
def getOpenInterestdata( sym, d1, d2 ): sym = str(sym) #ticks = lookupClient.Historical.GetHistoryDailyDatapoints(sym, 1) ticks = lookupClient.Historical.GetHistoryDailyTimeframe(sym, d1, d2) for tick in ticks: s = str(tick) datalist = s.split(',') #print(int(str(datalist[6]).replace(' OpenInterest: ','))) oi = int(str(datalist[6]).replace(' OpenInterest: ','))
return oi
def main(): ################## # input parameters '' Month codes: January: F February: G March: H April: J May: K June: M July: N August: Q September: U October: V November: X December: Z '' f_symbol = '@ES' o_month = 'M' o_year = '23' ##################
yesterday = datetime.now() - timedelta(1) d1 = DateTime(yesterday.year,yesterday.month,yesterday.day) d2 = DateTime(yesterday.year,yesterday.month,yesterday.day)
# Calls symbollist,strikepricelist = createListofSymbolPlusStrikePrice(f_symbol, o_month, o_year, 1) list1 = symbollist.split(',') list2 = strikepricelist.split(',') df_calls = pd.DataFrame(list(zip(list1, list2)), columns =['Symbols', 'Strike']) df_calls = df_calls.astype({'Strike':'float'}) df_calls = df_calls.sort_values(by=['Strike']) df_calls['OpenInterest'] = 0 idx = 0 for index, row in df_calls.iterrows(): sym = row['Symbols'] oi = getOpenInterestdata( sym, d1, d2 ) df_calls.iloc[idx, 2] = oi print(idx,row['Strike'],row['Symbols'],oi) idx += 1
print(df_calls)
# Puts symbollist,strikepricelist = createListofSymbolPlusStrikePrice(f_symbol, o_month, o_year, 2) list1 = symbollist.split(',') list2 = strikepricelist.split(',') df_puts = pd.DataFrame(list(zip(list1, list2)), columns =['Symbols', 'Strike']) df_puts = df_puts.astype({'Strike':'float'}) df_puts = df_puts.sort_values(by=['Strike']) df_puts['OpenInterest'] = 0
idx = 0 for index, row in df_puts.iterrows(): sym = row['Symbols'] oi = getOpenInterestdata( sym, d1, d2 ) df_puts.iloc[idx, 2] = oi print(idx,row['Strike'],row['Symbols'],oi) idx += 1
print(df_puts)
strikes = list(df_calls['Strike']) losses = [total_loss_at_strike(df_calls, df_puts, strike)/1000000 for strike in strikes]
m = losses.index(min(losses)) print("Max pain > {}".format(strikes[m]))
plt.plot(strikes, losses) plt.ylabel('Total loss in (Millon)') plt.show()
if __name__ == "__main__": main()
this is the final "max pain" code. Kind of slowwwwww. Maybe IQFeed can add max pain so we do not have to calculate it.
Getting max pain for NQ June expiration 12800 and ES June expiration 4050
# filesname: charpHistoricalDataTest.py # to run code IQFeed should be launched already # to run code type in the CMD window (path to python should be known) # python charpHistoricalDataTest.py
# Dynamically add IQFeed.CSharpApiClient DLL import sys import clr assembly_path = r'C:/Program Files/AmiBroker/IQFeedCSharpApiClient' sys.path.append(assembly_path) clr.AddReference("IQFeed.CSharpApiClient") from System import DateTime from datetime import datetime, timedelta from IQFeed.CSharpApiClient.Lookup import LookupClientFactory from IQFeed.CSharpApiClient.Lookup.Chains import OptionSideFilterType import pandas as pd import matplotlib.pyplot as plt
lookupClient = LookupClientFactory.CreateNew() lookupClient.Connect()
def total_loss_at_strike(chainC, chainP, expiry_price): """Calculate loss at strike price""" # All call options with strike price below the expiry price will result in loss for option writers in_money_calls = chainC[chainC['Strike'] < expiry_price][["OpenInterest", "Strike"]] in_money_calls["CE loss"] = (expiry_price - in_money_calls['Strike'])*in_money_calls["OpenInterest"]
# All put options with strike price above the expiry price will result in loss for option writers in_money_puts = chainP[chainP['Strike'] > expiry_price][["OpenInterest", "Strike"]] in_money_puts["PE loss"] = (in_money_puts['Strike'] - expiry_price)*in_money_puts["OpenInterest"] total_loss = in_money_calls["CE loss"].sum() + in_money_puts["PE loss"].sum()
return total_loss
def createListofSymbolPlusStrikePrice(f_symbol, o_month, o_year, o_side):
''' Month codes: January: F February: G March: H April: J May: K June: M July: N August: Q September: U October: V November: X December: Z '''
f_symbol = str(f_symbol) o_month = str(o_month) o_year = str(o_year)
if( o_side == 1): side = OptionSideFilterType.C if( o_side == 2): side = OptionSideFilterType.P
try: ticks = lookupClient.Chains.GetChainFutureOption( f_symbol, side, o_month, o_year ) symbollist = '' strikepricelist = '' for tt in ticks: symbollist += str(tt.Symbol) symbollist += ',' strikepricelist += str(tt.StrikePrice) strikepricelist += ','
# remove last comma symbollist = symbollist[:len(symbollist)-1] except Exception as err: print(f"Unexpected {err=}, {type(err)=}")
return symbollist,strikepricelist
def getOpenInterestdata( sym, d1, d2 ): sym = str(sym) #ticks = lookupClient.Historical.GetHistoryDailyDatapoints(sym, 1) ticks = lookupClient.Historical.GetHistoryDailyTimeframe(sym, d1, d2) for tick in ticks: s = str(tick) datalist = s.split(',') #print(int(str(datalist[6]).replace(' OpenInterest: ',''))) oi = int(str(datalist[6]).replace(' OpenInterest: ',''))
return oi
def main(): f_symbol = '@NQ' o_month = 'M' o_year = '23'
yesterday = datetime.now() - timedelta(1) d1 = DateTime(yesterday.year,yesterday.month,yesterday.day) d2 = DateTime(yesterday.year,yesterday.month,yesterday.day)
# Calls symbollist,strikepricelist = createListofSymbolPlusStrikePrice(f_symbol, o_month, o_year, 1) list1 = symbollist.split(',') list2 = strikepricelist.split(',') df_calls = pd.DataFrame(list(zip(list1, list2)), columns =['Symbols', 'Strike']) df_calls = df_calls.astype({'Strike':'float'}) df_calls = df_calls.sort_values(by=['Strike']) df_calls['OpenInterest'] = 0 idx = 0 for index, row in df_calls.iterrows(): sym = row['Symbols'] oi = getOpenInterestdata( sym, d1, d2 ) df_calls.iloc[idx, 2] = oi #print(idx,row['Strike'],row['Symbols'],oi) idx += 1
print(df_calls)
# Puts symbollist,strikepricelist = createListofSymbolPlusStrikePrice(f_symbol, o_month, o_year, 2) list1 = symbollist.split(',') list2 = strikepricelist.split(',') df_puts = pd.DataFrame(list(zip(list1, list2)), columns =['Symbols', 'Strike']) df_puts = df_puts.astype({'Strike':'float'}) df_puts = df_puts.sort_values(by=['Strike']) df_puts['OpenInterest'] = 0
idx = 0 for index, row in df_puts.iterrows(): sym = row['Symbols'] oi = getOpenInterestdata( sym, d1, d2 ) df_puts.iloc[idx, 2] = oi #print(idx,row['Strike'],row['Symbols'],oi) idx += 1
print(df_puts)
strikes = list(df_calls['Strike']) losses = [total_loss_at_strike(df_calls, df_puts, strike)/1000000 for strike in strikes]
m = losses.index(min(losses)) print("Max pain > {}".format(strikes[m]))
plt.plot(strikes, losses) plt.ylabel('Total loss in (Millon)') plt.show()
if __name__ == "__main__": main()
yes it seems that this line (in the function getOpenInterestdata) makes it slow:
ticks = lookupClient.Historical.GetHistoryDailyTimeframe(sym, d1, d2)
the total code is below. What it does is it makes 2 pandas dataframes. 1 for Futures Call contracts and 1 for the Futures Put contracts. In the columns are, the symbols, strike price and Open interest.
It works but it is slow. The openInterest for various strike prices should be instantly accessible. At least the IQFeed chains App finds them almost instantly. So somethings is wrong with this code.
# filesname: charpHistoricalDataTest.py # to run code IQFeed should be launched already # to run code type in the CMD window (path to python should be known) # python charpHistoricalDataTest.py
# Dynamically add IQFeed.CSharpApiClient DLL import sys import clr assembly_path = r'C:/Program Files/AmiBroker/IQFeedCSharpApiClient' sys.path.append(assembly_path) clr.AddReference("IQFeed.CSharpApiClient") from System import DateTime from datetime import datetime, timedelta from IQFeed.CSharpApiClient.Lookup import LookupClientFactory from IQFeed.CSharpApiClient.Lookup.Chains import OptionSideFilterType import pandas as pd
lookupClient = LookupClientFactory.CreateNew() lookupClient.Connect()
def createListofSymbolPlusStrikePrice(f_symbol, o_month, o_year, o_side):
''' Month codes: January: F February: G March: H April: J May: K June: M July: N August: Q September: U October: V November: X December: Z '''
f_symbol = str(f_symbol) o_month = str(o_month) o_year = str(o_year)
if( o_side == 1): side = OptionSideFilterType.C if( o_side == 2): side = OptionSideFilterType.P
try: ticks = lookupClient.Chains.GetChainFutureOption( f_symbol, side, o_month, o_year ) symbollist = '' strikepricelist = '' for tt in ticks: symbollist += str(tt.Symbol) symbollist += ',' strikepricelist += str(tt.StrikePrice) strikepricelist += ','
# remove last comma symbollist = symbollist[:len(symbollist)-1] except Exception as err: print(f"Unexpected {err=}, {type(err)=}")
return symbollist,strikepricelist
def getOpenInterestdata( sym, d1, d2 ): sym = str(sym) #ticks = lookupClient.Historical.GetHistoryDailyDatapoints(sym, 1) ticks = lookupClient.Historical.GetHistoryDailyTimeframe(sym, d1, d2) for tick in ticks: s = str(tick) datalist = s.split(',') #print(int(str(datalist[6]).replace(' OpenInterest: ',''))) oi = int(str(datalist[6]).replace(' OpenInterest: ',''))
return oi
def main(): f_symbol = 'QNG' o_month = 'K' o_year = '23'
yesterday = datetime.now() - timedelta(1) d1 = DateTime(yesterday.year,yesterday.month,yesterday.day) d2 = DateTime(yesterday.year,yesterday.month,yesterday.day)
# Calls symbollist,strikepricelist = createListofSymbolPlusStrikePrice(f_symbol, o_month, o_year, 1) list1 = symbollist.split(',') list2 = strikepricelist.split(',') df_calls = pd.DataFrame(list(zip(list1, list2)), columns =['Symbols', 'Strike']) df_calls = df_calls.astype({'Strike':'float'}) df_calls = df_calls.sort_values(by=['Strike']) df_calls['OpenInterest'] = 0 idx = 0 for index, row in df_calls.iterrows(): sym = row['Symbols'] oi = getOpenInterestdata( sym, d1, d2 ) df_calls.iloc[idx, 2] = oi #print(idx,row['Strike'],row['Symbols'],oi) idx += 1
print(df_calls)
# Puts symbollist,strikepricelist = createListofSymbolPlusStrikePrice(f_symbol, o_month, o_year, 2) list1 = symbollist.split(',') list2 = strikepricelist.split(',') df_puts = pd.DataFrame(list(zip(list1, list2)), columns =['Symbols', 'Strike']) df_puts = df_puts.astype({'Strike':'float'}) df_puts = df_puts.sort_values(by=['Strike']) df_puts['OpenInterest'] = 0
idx = 0 for index, row in df_puts.iterrows(): sym = row['Symbols'] oi = getOpenInterestdata( sym, d1, d2 ) df_puts.iloc[idx, 2] = oi #print(idx,row['Strike'],row['Symbols'],oi) idx += 1
print(df_puts)
if __name__ == "__main__": main()
thanks. I also check in the Options Chain App and the Open Interest shown is the value of yesterdays close. So it is not updated. I mean the Volume is updating but not the OI. Not sure if this is normal, I am no expert on this.
Maybe I post my Python code later. It is really slow. What I do I first get the Option Chain list (for calls and puts). I put them in a pandas dataframe sorted for the strike price. Then I loop through all the symbols of the chain to find the OI for all the symbols. That takes too long.
Will post code complete later.
A snippet of the code shows what I do, see below. The function passes the future option symbol and the startdate plus enddate (which are the same and I use yesterdays date since todays values are zero). This is slow. It gives the correct OI values. Maybe it is because I get the OI from a string. I should be able to access it directly but I do not know the correct csharp code for that.
def getOpenInterestdata( sym, d1, d2 ): sym = str(sym) lookupClient = LookupClientFactory.CreateNew() lookupClient.Connect()
# Step 4 - Make any requests you need or want! #ticks = lookupClient.Historical.GetHistoryTickDatapoints("QNGK23C2250", 10) #ticks = lookupClient.Historical.GetHistoryDailyDatapoints(sym, 5) ticks = lookupClient.Historical.GetHistoryDailyTimeframe(sym, d1, d2)
for tick in ticks: s = str(tick) datalist = s.split(',') #print(int(str(datalist[6]).replace(' OpenInterest: ',''))) oi = int(str(datalist[6]).replace(' OpenInterest: ',''))
return oi
actually using the Csharp code I get access to OpenInterest data using GetHistoryDailyDatapoints, see code below.
About the OpenInterest. It seems the last data point is zero. Is this data updated only at certain times?
Data output from code below looks like:
C:\Users\win 10\AppData\Local\Programs\Python\Python38\mypython\iqfeed>python charpHistoricalDataTest.py Timestamp: 4/19/2023 12:00:00 AM, High: 0.181, Low: 0.181, Open: 0.181, Close: 0.181, PeriodVolume: 3, OpenInterest: 0, RequestId: Timestamp: 4/18/2023 12:00:00 AM, High: 0.192, Low: 0.13, Open: 0.154, Close: 0.19, PeriodVolume: 18, OpenInterest: 221, RequestId: Timestamp: 4/17/2023 12:00:00 AM, High: 0.155, Low: 0.09, Open: 0.099, Close: 0.143, PeriodVolume: 28, OpenInterest: 226, RequestId: Timestamp: 4/14/2023 12:00:00 AM, High: 0.08, Low: 0.039, Open: 0.055, Close: 0.079, PeriodVolume: 57, OpenInterest: 240, RequestId: Timestamp: 4/13/2023 12:00:00 AM, High: 0.073, Low: 0.053, Open: 0.073, Close: 0.055, PeriodVolume: 19, OpenInterest: 265, RequestId: Completed!
So this output I created at 2023-04-19 at 05:55 ET and the OpenInterest on the 19-th is showing 0. Why is it showing 0? Shouldn't that be showing the last value of the prior day? At what time of the day is it updated?
Thanks.
Python code using Csharp plugin
# python charpHistoricalDataTest.py
# Dynamically add IQFeed.CSharpApiClient DLL import sys import clr assembly_path = r'C:/Program Files/AmiBroker/IQFeedCSharpApiClient' sys.path.append(assembly_path) clr.AddReference("IQFeed.CSharpApiClient")
# Step 2 - Use the appropriate factory to create the client from IQFeed.CSharpApiClient.Lookup import LookupClientFactory #from IQFeed.CSharpApiClient.Lookup.Historical import LookupClientFactory lookupClient = LookupClientFactory.CreateNew()
# Step 3 - Connect it lookupClient.Connect()
# Step 4 - Make any requests you need or want! #ticks = lookupClient.Historical.GetHistoryTickDatapoints("QNGK23C2250", 10) ticks = lookupClient.Historical.GetHistoryDailyDatapoints("QNGK23C2250", 5)
for tick in ticks: print(tick)
print('Completed!')
thanks for your help. I will try that. I also managed to access the data inside Amibroker. But I use Python to access the list (chain) of options. Will later ask Amibroker if they also can add a function to access this chain of option symbols.
Is there also a call to access the list of expiration dates for a particular symbol? So if I give the futures symbol it would give a list of expiration dates?
For instance in the Python example using Yahoo data (see code below) the command in line 10, osym.options gives me a list of expiration dates for the stock symbol given.
For futures options it would coincide with the expiration of the underlying future. I guess for futures options you rather would want a list of expiration months. Not sure.
thank you
# python medium_options.py
import yfinance as yf import matplotlib.pyplot as plt
def main(): symbol = input("Enter the Symbol: " ) #symbol = 'UNG' osym = yf.Ticker(symbol) exps = osym.options print("Expiry dates:") print(exps) expiry = input("\nEnter the Expiry data [format: YYYY-MM-DD]: " )
#expiry = '2023-04-21' opc = osym.option_chain(expiry) opccalls = opc.calls opcputs = opc.puts print(opc.calls) print(opc.puts) print('') print(opc.calls.info()) ''' plt.subplot(211) plt.plot(opccalls['strike'],opccalls['openInterest']) plt.subplot(212) plt.plot(opcputs['strike'],opcputs['openInterest']) plt.show() ''' if __name__ == "__main__": main()
and yes I am after the "Futures Options" for now since I have an IQFeed subscription for US futures only. And I have no access to the "development library" since I only have a subscription to use the data.
actually using csharp I managed to get the list of options that belong to a chain for a certain month and year, see code below.
Now I still need to get the data. I have some code that gets the price data for the futures options but the Open Interest is apparently stored somewhere else. I still need to figure out how to access the Open Interest. Apparently this is not saved in a similar way as the price is.
Also the option chain lists are not saved in history apparently. I have access to historical futures options data but the "historical futures chain lists" are apparently not saved.
here the code that uses Csharp that gives the symbols of a chain
https://github.com/mathpaquette/IQFeed.CSharpApiClient/blob/master/docs/USING-WITH-PYTHON.md # Dynamically add IQFeed.CSharpApiClient DLL # assembly_path = r"C:\<folder>" # filename: iqfeedcsharpGetFuturesOptionChainAFL.py
if '__' + __file__ + '_initialized' not in globals(): globals()['__' + __file__ + '_initialized'] = True assembly_path = r'C:/Program Files/AmiBroker/IQFeedCSharpApiClient'
import sys sys.path.append(assembly_path)
# Reference IQFeed.CSharpApiClient DLL import clr clr.AddReference("IQFeed.CSharpApiClient")
from IQFeed.CSharpApiClient.Lookup import LookupClientFactory from IQFeed.CSharpApiClient.Lookup.Chains import OptionSideFilterType #import AmiPy
def getFuturesOptionsChainSymbols(f_symbol, o_month, o_year):
''' Month codes: January: F February: G March: H April: J May: K June: M July: N August: Q September: U October: V November: X December: Z '''
f_symbol = str(f_symbol) o_month = str(o_month) o_year = str(o_year)
lookupClient = LookupClientFactory.CreateNew() lookupClient.Connect()
try: # symtax Symbol (QNG), OptionSideFilterType.CP, Month Code, Year Code ticks = lookupClient.Chains.GetChainFutureOption( f_symbol, OptionSideFilterType.CP, o_month, o_year ) symbollist = '' for tt in ticks: symbollist += tt.Symbol symbollist += ','
# remove last comma symbollist = symbollist[:len(symbollist)-1] #AmiPy.Print(symbollist) except Exception as err: #AmiPy.Print(f"Unexpected {err=}, {type(err)=}") print(f"Unexpected {err=}, {type(err)=}")
return symbollist
def main(): optionchain = getFuturesOptionsChainSymbols("QNG", "K", "23") print(optionchain)
if __name__ == "__main__": main()
thanks for your help, I will try that
i think I understand the idea of the csharp plugin. "GetChainFutureOption" gives the list of symbols for "Futures Options". These symbols one can then use to retrieve the data. I was thinking the data would come with it but it is just a list. So hopefully I can use this list of symbols to retrieve the data.
# https://github.com/mathpaquette/IQFeed.CSharpApiClient/blob/master/docs/USING-WITH-PYTHON.md # Dynamically add IQFeed.CSharpApiClient DLL # assembly_path = r"C:\<folder>" # type in CMD window: python iqfeedcsharpapiclientOptionTest.py
assembly_path = r'C:/Program Files/AmiBroker/IQFeedCSharpApiClient'
import sys sys.path.append(assembly_path)
# Reference IQFeed.CSharpApiClient DLL import clr clr.AddReference("IQFeed.CSharpApiClient")
from IQFeed.CSharpApiClient.Lookup import LookupClientFactory from IQFeed.CSharpApiClient.Lookup.Chains import OptionSideFilterType
lookupClient = LookupClientFactory.CreateNew() lookupClient.Connect()
ticks = lookupClient.Chains.GetChainFutureOption( "QNG", OptionSideFilterType.CP, "K", '23')
for tt in ticks: print(tt.Symbol)
print('Completed!')
hi, I am just an IQFeed user so I do not have access to the development documentation. I have access to futures and "futures options" data via my subscription with IQFeed.
I want to use Python to get access to "futures option" chains (and maybe I add an Equity options subscription as well at some point).
For Yahoo Equity Options data there exists Python code that allows to have acces to put and call option chain data for a specific expiration date (see example code below). It basically puts the put and call data in a pandas dataframe.
I want to make similar dataframes for the IQFeed "futures option" data. I explain further below the Python code that can access Yahoo data.
# python medium_options.py
import yfinance as yf import matplotlib.pyplot as plt
def main(): symbol = input("Enter the Symbol: " ) #symbol = 'UNG' osym = yf.Ticker(symbol) exps = osym.options print("Expiry dates:") print(exps) expiry = input("\nEnter the Expiry data [format: YYYY-MM-DD]: " )
#expiry = '2023-04-21' opc = osym.option_chain(expiry) opccalls = opc.calls opcputs = opc.puts print(opc.calls) print(opc.puts) print(') print(opc.calls.info()) '' plt.subplot(211) plt.plot(opccalls['strike'],opccalls['openInterest']) plt.subplot(212) plt.plot(opcputs['strike'],opcputs['openInterest']) plt.show() '' if __name__ == "__main__": main()
The resulting dataframes looks like this:
contractSymbol lastTradeDate strike lastPrice bid ask change percentChange volume openInterest impliedVolatility inTheMoney contractSize currency 0 UNG230421P00002000 2023-03-27 13:33:21+00:00 2.0 0.05 0.00 0.04 0.00 0.000000 2.0 24 4.750004 False REGULAR USD 1 UNG230421P00003000 2023-04-10 16:31:05+00:00 3.0 0.01 0.00 0.01 0.00 0.000000 16.0 306 2.625003 False REGULAR USD 2 UNG230421P00004000 2023-04-14 14:03:58+00:00 4.0 0.01 0.00 0.01 0.00 0.000000 88.0 752 1.750001 False REGULAR USD 3 UNG230421P00004500 2023-04-14 17:42:34+00:00 4.5 0.01 0.00 0.01 0.00 0.000000 206.0 3347 1.375003 False REGULAR USD 4 UNG230421P00005000 2023-04-14 19:54:54+00:00 5.0 0.01 0.01 0.03 -0.02 -66.666670 242.0 5222 1.375003 False REGULAR USD 5 UNG230421P00005500 2023-04-14 19:55:37+00:00 5.5 0.02 0.01 0.03 -0.02 -50.000000 595.0 7400 0.984375 False REGULAR USD 6 UNG230421P00006000 2023-04-14 19:59:43+00:00 6.0 0.06 0.05 0.07 -0.08 -57.142853 6339.0 63012 0.859376 False REGULAR USD 7 UNG230421P00006500 2023-04-14 20:09:03+00:00 6.5 0.19 0.19 0.20 -0.14 -42.424248 2028.0 8081 0.828127 False REGULAR USD 8 UNG230421P00007000 2023-04-14 20:14:48+00:00 7.0 0.45 0.42 0.46 -0.23 -33.823532 1107.0 17013 0.730471 True REGULAR USD 9 UNG230421P00007500 2023-04-14 17:42:34+00:00 7.5 0.91 0.80 1.02 -0.25 -21.551720 68.0 1799 1.031255 True REGULAR USD 10 UNG230421P00008000 2023-04-14 19:43:35+00:00 8.0 1.32 1.29 1.35 -0.34 -20.481924 104.0 37005 0.781252 True REGULAR USD 11 UNG230421P00008500 2023-04-13 13:54:25+00:00 8.5 2.09 1.59 2.05 0.00 0.000000 4.0 58 0.968750 True REGULAR USD 12 UNG230421P00009000 2023-04-14 17:13:51+00:00 9.0 2.38 2.26 2.51 -0.24 -9.160297 4.0 6204 1.750001 True REGULAR USD
I have Python code to access historical data. The message rule used I found on this forum I believe. For instance I use this code to download historical futures data. Further explanation below this code.
def read_historical_data_socket(sock, recv_buffer=524288): buffer = "" data = "" while True: data = sock.recv(recv_buffer) buffer += data.decode()
# Check if the end message string arrives if "!ENDMSG!" in buffer: break
# Remove the end message string buffer = buffer[:-12] # Remove protocol message at the start buffer = buffer[22:] return buffer
def downloadTickDataPerDay2(sym, bdate, edate, filename, dataPath):
sym = str(sym) bdate = str(bdate) edate = str(edate) filename = str(filename) dataPath = str(dataPath)
host = "127.0.0.1" # Localhost port = 9100 # Historical data socket port message = "HTT,%s,%s,%s,,,,1\n" % ( sym, bdate, edate )
# Open a streaming socket to the IQFeed server locally sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((host, port)) sock.sendall(b'S,SET PROTOCOL,6.2\r\n')
# Send the historical data request # message and buffer the data sock.sendall(message.encode()) data = read_historical_data_socket(sock) sock.close
# remove blank line at start where the protocol message was removed data = data.strip() # Remove all the endlines and line-ending # comma delimiter from each record data = "".join(data.split("\r")) data = data.replace(",\n","\n")[:-1] data = data.replace("LH,","")
if data != 'E,!NO_DATA!,': # Write the data stream to disk f = open(dataPath + sym + "//" + filename, "w") f.write(data) f.close() else: print("No Data found ....")
so I am after Python code that can either download "futures option chains" and "equity options chains". It should give 1) a list of expiration dates 2) if the expiration date is given it should put the put and call option chains in for instance pandas dataframes
Probably the Python code would be similar to the code posted just above but I do not know the correct message rule and port etc.
I will also ask Math Paquette later using his Csharp plugin. I tried to use it but the documentation is basically the Csharp source code which is slightly above my head. Here is some code using the plugin which gives some output (assuming IQFeed is launched). However, I have not been able to find the put and call data. I would however prefer pure Python code without having to use the Csharp plugin.
thanks
# https://github.com/mathpaquette/IQFeed.CSharpApiClient/blob/master/docs/USING-WITH-PYTHON.md # Dynamically add IQFeed.CSharpApiClient DLL # assembly_path = r"C:\<folder>" # type in CMD window: python iqfeedcsharpapiclientOptionTest.py
assembly_path = r'C:/Program Files/AmiBroker/IQFeedCSharpApiClient'
import sys sys.path.append(assembly_path)
# Reference IQFeed.CSharpApiClient DLL import clr clr.AddReference("IQFeed.CSharpApiClient")
# from IQFeed.CSharpApiClient import IQFeedLauncher
# Step 2 - Use the appropriate factory to create the client from IQFeed.CSharpApiClient.Lookup import LookupClientFactory from IQFeed.CSharpApiClient.Lookup.Chains import OptionSideFilterType
lookupClient = LookupClientFactory.CreateNew()
# Step 3 - Connect it lookupClient.Connect()
ticks = lookupClient.Chains.GetChainFutureOption( "QNG", OptionSideFilterType.CP, "K", '23')
for tt in ticks: print(tt.Symbol,tt.StrikePrice) #print(dir(tt))
print('Completed!')
to finish off my message marathon here is the solution and I have to so say it works great
So when loading Python you have to additionally load:
clr.AddReference('System.Collections') from System import DateTime
then to get the data between 2 dates is done by using for instance
d1 = DateTime(2022,10,17,9,10,10) d2 = DateTime(2022,10,18,8,0,0) ticksFilename = lookupClient.Historical.File.GetHistoryTickTimeframe(sym,d1,d2,None,None,None,1)
so the parameters used in DatetTime are Year, Month, Day, Hour, Minute, Second Edited by emp on Oct 18, 2022 at 08:00 AM
well I made some progress. At least it seems to accept the type: <class 'System.DateTime'>
so this code at least makes the function work. So making some progress. I know the type it needs now. Still getting some weird results but I have something to work with now
import clr from pandas import to_datetime, Series clr.AddReference('System.Collections') from System.Collections.Generic import List from System import DateTime Contracts = to_datetime(Series(['13/10/2022','14/10/2022']))
DateList = List[DateTime](range(len(Contracts))) for i in range(len(Contracts)): DateList.Add(DateTime(Contracts.year,Contracts.month,Contracts.day))
d1 = DateList.get_Item(0) d2 = DateList.get_Item(1)
ticksFilename = lookupClient.Historical.File.GetHistoryTickTimeframe("@ES#",d1,d2,None,None,None,1)
Edited by emp on Oct 18, 2022 at 03:52 AM
and I know the endDate and beginDate are supposed to be of the DateTime type. I also tried this, see console printout below. Again I get a type error. So it does not accept "datetime" types and also no "str" types. Also no "int" types ....
Python 3.8.5 (tags/v3.8.5:580fbb0, Jul 20 2020, 15:57:54) [MSC v.1924 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> import clr >>> assembly_path = r'C:/Program Files/AmiBroker/IQFeedCSharpApiClient' >>> sys.path.append(assembly_path) >>> clr.AddReference("IQFeed.CSharpApiClient") <System.Reflection.RuntimeAssembly object at 0x000002E7DA40BDC0> >>> import time >>> import numpy as np >>> import pandas as pd >>> from IQFeed.CSharpApiClient.Lookup import LookupClientFactory >>> from IQFeed.CSharpApiClient.Lookup.Historical.Messages import TickMessage >>> import datetime >>> from System import DateTime >>> >>> # Create Lookup client >>> lookupClient = LookupClientFactory.CreateNew() >>> # Connect >>> lookupClient.Connect() >>> d1 = datetime.date(2022, 10, 13) >>> d2 = datetime.date(2022, 10, 14) >>> d1 datetime.date(2022, 10, 13) >>> d2 datetime.date(2022, 10, 14) >>> ticksFilename = lookupClient.Historical.File.GetHistoryTickTimeframe("@ES#",d1,d2,None,None,None,1) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: No method matches given arguments for GetHistoryTickTimeframe: (<class 'str'>, <class 'datetime.date'>, <class 'datetime.date'>, <class 'NoneType'>, <class 'NoneType'>, <class 'NoneType'>, <class 'int'>) >>>
hi, in response to an email from Gary:
I'd need to know what command mathpaquette is trying to send, and what failure message you're getting. An iqconnect log file would be helpful. To generate one, open the Diagnostics app and go to the Logging tab. Make sure "lookup request" "lookup data" and "lookup error" are all checked. Try making the request again in mathpaquette. then go back to the diagnostics tab and collect the log file. You can email it to support or post it here, and I can review it.
I add the diagnostics file but it seems no info there on the error. So I explain what I do. The IQFeed connection manager is launched via Amibroker. So I test the code in the Python 3.8 console.
First I load into the console:
import sys import clr assembly_path = r'C:/Program Files/AmiBroker/IQFeedCSharpApiClient' sys.path.append(assembly_path) clr.AddReference("IQFeed.CSharpApiClient") import time import numpy as np import pandas as pd from IQFeed.CSharpApiClient.Lookup import LookupClientFactory from IQFeed.CSharpApiClient.Lookup.Historical.Messages import TickMessage from datetime import datetime
# Create Lookup client lookupClient = LookupClientFactory.CreateNew() # Connect lookupClient.Connect()
so in the console what I did looks like:
Python 3.8.5 (tags/v3.8.5:580fbb0, Jul 20 2020, 15:57:54) [MSC v.1924 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> import clr >>> assembly_path = r'C:/Program Files/AmiBroker/IQFeedCSharpApiClient' >>> sys.path.append(assembly_path) >>> clr.AddReference("IQFeed.CSharpApiClient") <System.Reflection.RuntimeAssembly object at 0x000002560C99BDC0> >>> import time >>> import numpy as np >>> import pandas as pd >>> from IQFeed.CSharpApiClient.Lookup import LookupClientFactory >>> from IQFeed.CSharpApiClient.Lookup.Historical.Messages import TickMessage >>> from datetime import datetime >>> >>> # Create Lookup client >>> lookupClient = LookupClientFactory.CreateNew() >>> # Connect >>> lookupClient.Connect() >>> >>> >>> ticksFilename = lookupClient.Historical.File.GetHistoryTickDatapoints("@ES#",100,1) >>> ticksFilename = lookupClient.Historical.File.GetHistoryTickDays("@ES#",1,None,None,None,1) >>> ticksFilename = lookupClient.Historical.File.GetHistoryTickTimeframe("@ES#","20221013 093001","20221014 093020") Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: No method matches given arguments for GetHistoryTickTimeframe: (<class 'str'>, <class 'str'>, <class 'str'>) >>> ticksFilename = lookupClient.Historical.File.GetHistoryTickTimeframe("@ES#","20221013","20221014",None,None,None,1) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: No method matches given arguments for GetHistoryTickTimeframe: (<class 'str'>, <class 'str'>, <class 'str'>, <class 'NoneType'>, <class 'NoneType'>, <class 'NoneType'>, <class 'int'>) >>> ticksFilename = lookupClient.Historical.File.GetHistoryTickTimeframe("@ES#") Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: No method matches given arguments for GetHistoryTickTimeframe: (<class 'str'>) >>> ticksFilename = lookupClient.Historical.File.GetHistoryTickTimeframe("@ES#",None,None) Traceback (most recent call last): File "<stdin>", line 1, in <module> System.ArgumentException: Begin date or End date must have value. at IQFeed.CSharpApiClient.Lookup.Historical.Facades.HistoricalFileFacade.GetHistoryTickTimeframe(String symbol, Nullable`1 beginDate, Nullable`1 endDate, Nullable`1 maxDatapoints, Nullable`1 beginFilterTime, Nullable`1 endFilterTime, Nullable`1 dataDirection, String requestId, Nullable`1 datapointsPerSend) >>>
as you can see I use 2 of the 3 tickMessage functions succesfully, these 2:
ticksFilename = lookupClient.Historical.File.GetHistoryTickDatapoints("@ES#",100,1) ticksFilename = lookupClient.Historical.File.GetHistoryTickDays("@ES#",1,None,None,None,1)
there is a third function in which you can add the beinDate/Time endDate/Time. I tried all kinds of formats. For this error log I tried these 4:
ticksFilename = lookupClient.Historical.File.GetHistoryTickTimeframe("@ES#","20221013 093001","20221014 093020") ticksFilename = lookupClient.Historical.File.GetHistoryTickTimeframe("@ES#","20221013","20221014",None,None,None,1) ticksFilename = lookupClient.Historical.File.GetHistoryTickTimeframe("@ES#") ticksFilename = lookupClient.Historical.File.GetHistoryTickTimeframe("@ES#",None,None)
as you can see from the 4-th error message in the console it knows the function since the error it gives is:
>>> ticksFilename = lookupClient.Historical.File.GetHistoryTickTimeframe("@ES#",None,None) Traceback (most recent call last): File "<stdin>", line 1, in <module> System.ArgumentException: Begin date or End date must have value. at IQFeed.CSharpApiClient.Lookup.Historical.Facades.HistoricalFileFacade.GetHistoryTickTimeframe(String symbol, Nullable`1 beginDate, Nullable`1 endDate, Nullable`1 maxDatapoints, Nullable`1 beginFilterTime, Nullable`1 endFilterTime, Nullable`1 dataDirection, String requestId, Nullable`1 datapointsPerSend) >>>
I can see the 2 successful requests in the log, but not the last 4 unsuccessful. Going through the csharp source code I am pretty sure the format for the beginDate and endDate needs to be like:
"yyyyMMdd HHmmss"
And I also have other pure Python code that just passes the beginDate and endDate as strings in which I use (and this actually WORKS):
fdate = next_day.strftime("%Y") + next_day.strftime("%m") + next_day.strftime("%d") # format YYYYMMDD message = "HTT,%s,%s,%s,,,,1\n" % ( sym, fdate, fdate )
I tried about everything so I hope someone can figure it out.
thanks
hi,
i wonder if someone else is playing around with this. So I am already making good progress. From the examples (see csharp manual by mathpagquette) I can get for instance 1000 lines of data using:
ticksFilename = lookupClient.Historical.File.GetHistoryTickDatapoints("@ES#", 1000, 1)
also I succeeded getting a certain number of days using, e.g.
ticksFilename = lookupClient.Historical.File.GetHistoryTickDays("@ES#",3,None,None,None,1)
I am however having difficulties getting tick data from a begindate to an enddate.
In the source the format is given as:
public string GetHistoryTickTimeframe(string symbol, DateTime? beginDate, DateTime? endDate, int? maxDatapoints = null, TimeSpan? beginFilterTime = null, TimeSpan? endFilterTime = null, DataDirection? dataDirection = null, string requestId = null, int? datapointsPerSend = null) { return GetHistoryTickTimeframeAsync(symbol, beginDate, endDate, maxDatapoints, beginFilterTime, endFilterTime, dataDirection, requestId, datapointsPerSend).SynchronouslyAwaitTaskResult(); }
so I tried:
ticksFilename = lookupClient.Historical.File.GetHistoryTickTimeframe("@ES#",20221013,20221014,None,None,None,1)
but it rejects this. I tried various alternatives but it doesn't accept it. Could someone show the proper format? I use the same dateformat as IQFeed uses. I tried passing it as a string but no success
Thanks
well today it is already Sunday. Still no access to historical data here. Well I give up for today
already found this "ticks.csv" file. So this can be read at once into pandas and is very fast. Pretty excited about this.
Unfortunately the server is still down. At least I can't get historical data. Looks like everyone at IQFeed is on holiday. Is there no STATUS page or something like that? Since it is down now for more than 24 hours. I know it is weekend but some people need to write code in the weekends. Strange, seems like everybody left the shop. Guess they will show up around 9AM ET tomorrow (if we are lucky).
IQFeed has been down since Saturday. Or I can connect to the server but it does not give historical data. I am in the EU but I also checked with fellow trader in Singapore and he is not getting data either. So the problem is with IQFeed. This is a pain since I was working on code over the weekend. Code that is supposed to get historical and streaming data so I can not work on that over the whole weekend ...
|