I have a simple tail hedge strategy. 99% of portfolio in SPY and 1% in a put hedge. It rebalances every month. Backtesting from 1/1/2008 to 6/30/2020.
Everything seems to run fine, until 5/2/2011 when it stops backtesting and the error log shows :"Runtime Error: In Scheduled Event 'SPY: MonthStart: SPY: 90 min after MarketOpen', ArgumentNullException : Value cannot be null."
On 5/2/2011, it looks like the orders are still filled, but I see a tag on the buy of the put hedge that states "Warning: fill at stale price". I'm not sure if this is related to the runtime error, but I'm guessing so.
I can't figure out how to fix this issue, or what's really causing it. Any help would be much appreciated! I will post the code below.
Bodhi
class TailHedge(QCAlgorithm): def Initialize(self): self.SetStartDate(2008, 1, 1) self.SetEndDate(2020, 6, 30) self.SetCash(1000000) spy = self.AddEquity("SPY", Resolution.Minute) spy.SetDataNormalizationMode(DataNormalizationMode.Raw) self.SetSecurityInitializer(lambda x: x.SetMarketPrice(self.GetLastKnownPrice(x))) self.spy = spy.Symbol self.contract = None self.SetWarmUp(200) self.Schedule.On(self.DateRules.MonthStart("SPY"), self.TimeRules.AfterMarketOpen("SPY", 90), self.Rebalance) def OnData(self, data): if self.IsWarmingUp: return def Rebalance(self): self.Log("SpecificTime: Fired at : {0}".format(self.Time)) self.SetHoldings(self.spy, 0.99) self.Debug(str(self.Portfolio[self.spy].HoldingsValue)) if self.contract is None: self.contract = self.GetContract() self.SetHoldings(self.contract, 0.01) self.Debug(str(self.Portfolio[self.contract].HoldingsValue)) return if not self.contract is None: self.Liquidate(self.contract) self.RemoveSecurity(self.contract) self.contract = None self.contract = self.GetContract() self.SetHoldings(self.contract, 0.01) self.Debug(str(self.Portfolio[self.contract].HoldingsValue)) return def GetContract(self): targetStrike = self.Securities[self.spy].Price * 0.7 contracts = self.OptionChainProvider.GetOptionContractList(self.spy, self.Time) puts = [x for x in contracts if x.ID.OptionRight == OptionRight.Put] puts = sorted( sorted(puts, key = lambda x: x.ID.Date, reverse = True), key = lambda x: x.ID.StrikePrice) puts = [x for x in puts if (x.ID.StrikePrice - targetStrike) >= 0 and (x.ID.StrikePrice - targetStrike) < 6] puts = [x for x in puts if 50 < (x.ID.Date - self.Time).days <= 90] if len(puts) == 0: return None self.AddOptionContract(puts[0], Resolution.Minute) return puts[0]
Â
Bodhi
Anyone have a solution for this? I'm stuck.
Shile Wen
Hi The Dude,
This is because sometimes the self.contract value is None due to lines 49-50. To fix this, we need to make sure self.contract is not None before purchasing it, and I will show this fix in the attached backtest.
Best,
Shile Wen
Bodhi
That makes sense, but I'm wondering why there aren't any put options populated in puts[] during the second half of 2011. ..?
When I jump back in time and look at the available puts on 5/2/2011, there are plenty of puts that meet the requirements in GetContract (ie, expiration between 50-90 days out, with strike at 70% of SPY).Â
Therefore why is self.contract None during the later half of 2011?
I've attached a new backtest showing the strategy for year 2011 only.
Jared Broad
Data is flakey that far back (its already reported to AlgoSeek). I suggest running from 2012 onwards.
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.
Bodhi
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!