I try to create an option universe. Working as instructed on other posts in the forum, I filtered option contract s in the OnSecuritiesChanged method (in contrast to what is shown on options docs example for option chain provider) and I can not add the option contract after filtering them out. I use self.AddOptionContract and it throws the following error
Runtime Error: NotSupportedException : BacktestingOptionChainProvider.GetOptionContractList(): SecurityType.Equity, SecurityType.Future, or SecurityType.Index is expected but was Option
here's the code
class MeasuredApricotCamel(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2021, 12, 17)
self.SetEndDate(2022,1,1)
self.SetCash(100000)
self.rebalanceTime = datetime.min
self.activeStocks = set()
self.activeOptions = set()
self.AddUniverse(self.CoarseFilter)
self.UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw
self.counter = 1000
def CoarseFilter(self, coarse):
if self.Time <= self.rebalanceTime:
return self.Universe.Unchanged
sortedByVolume = sorted(coarse, key = lambda x: x.Volume, reverse = True)
filtered = [x.Symbol for x in sortedByVolume if x.Price <= 200 and x.Price <= 50]
self.rebalanceTime = self.Time + timedelta(days = 45)
return filtered[0:10]
def OptionsFilter(self, stock):
contracts = self.OptionChainProvider.GetOptionContractList(stock, self.Time)
#selects the type of option to be Put contract
puts = [x for x in contracts if x.ID.OptionRight == OptionRight.Put]
#sorts contracts by closet expiring date date and closest strike price (sorts in ascending order)
puts = sorted(sorted(puts, key = lambda x: x.ID.Date), key = lambda x: x.ID.StrikePrice)
#then selects all contracts that meet our expiration criteria
#We want between 30 and 60 days as we do not want to hold our options close to expiration
puts = [x for x in puts if 30<(x.ID.Date - self.Time).days <= 60]
if not puts:
return
#selects the type of option to be Put contract
call = [x for x in contracts if x.ID.OptionRight ==OptionRight.Call]
#sorts contracts by closet expiring date date and closest strike price (sorts in ascending order)
call = sorted(sorted(call, key = lambda x: x.ID.Date), key = lambda x: x.ID.StrikePrice , reverse = True)
#then selects all contracts that meet our expiration criteria
call = [x for x in call if 30 <(x.ID.Date - self.Time).days <= 45]
if not call:
return
#will eventually return array of optimal puts and calls
#self.AddOptionContract(puts[0], Resolution.Minute)
#self.AddOptionContract(call[0], Resolution.Minute)
return (puts[0],call[0])
def OnSecuritiesChanged(self, changes):
for x in changes.RemovedSecurities:
self.Liquidate(x.Symbol)
self.activeStocks.remove(x.Symbol)
for x in changes.AddedSecurities:
self.activeStocks.add(x.Symbol)
options = self.OptionsFilter(x.Symbol)
loggg = ""
if options:
put, call = options[0], options[1]
self.activeOptions.add((put,call))
loggg += put.Value + ", " + call.Value
self.Log(loggg)
def checkOptionStatus(self, option):
if option.ID.Date < self.Time + timedelta(days = 7):
#It is time to sell
pass
pass
def OnData(self, data):
if self.activeOptions:
for option in self.activeOptions:
pass
if self.counter == 0:
self.Log(",".join([x.Value for x in self.activeStocks]))
#self.Log(self.activeOptions)
self.counter = 1000
else:
self.counter -= 1
Louis Szeto
Hi Yarden
OnSecuritiesChanged event handler will be called not only when equities are added into the universe, but also your newly added option contract! So, we'll have to add a check on the type of the added securities at line 67:
Best
Louis
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
Yarden Gur
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!