Hello, 

I am getting this error when running the below algorithm… anyone has an idea how to fix it or what to do? 

"Runtime Error: '?SPY' wasn't found in the OptionChains object, likely because there was no-data at this moment in time and it wasn't possible to fillforward historical data. Please check the data exists before accessing it with data.ContainsKey("?SPY") in DataDictionary.cs:line 224"

Here is the Code:

from datetime import timedelta
from AlgorithmImports import *

class VirtualYellowGiraffe(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2023, 5, 8)
        self.SetEndDate(2023, 5, 9)
        self.SetCash(100000)
        self.equity = self.AddEquity("SPY", Resolution.Minute)
        self.symbol = self.equity.Symbol

        self.InitOptionsAndGreeks(self.equity)

        self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(9, 35), self.OpenPosition)
        self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(12, 0), self.ClosePosition)

        self.targetProfitPercent = 0.10
        self.positionOpen = False
        self.putContract = None
        self.callContract = None

    def InitOptionsAndGreeks(self, theEquity):
        theEquity.SetDataNormalizationMode(DataNormalizationMode.Raw)
        self.SetWarmup(30, Resolution.Daily)
        self.SetSecurityInitializer(lambda x: x.SetMarketPrice(self.GetLastKnownPrice(x)))
        theOptionSubscription = self.AddOption(theEquity.Symbol)
        theOptionSubscription.PriceModel = OptionPriceModels.CrankNicolsonFD()
        theOptionSubscription.SetFilter(self.OptionsFilterFunction)

    def OpenPosition(self):
        if not self.IsWarmingUp and not self.positionOpen:
            self.putContract = self.SellAnOTMPut(0.5, 0)
            self.callContract = self.SellAnOTMCall(0.5, 0)
            self.positionOpen = True

    def ClosePosition(self):
        if self.positionOpen:
            currentProfit = self.CalculateProfit()
            if currentProfit >= self.targetProfitPercent:
                self.ClosePositions()
            else:
                self.ClosePositions()
                self.positionOpen = False

    def CalculateProfit(self):
        putPrice = self.Securities[self.putContract.Symbol].Price
        callPrice = self.Securities[self.callContract.Symbol].Price
        putCost = self.putContract.AskPrice + self.putContract.BidPrice
        callCost = self.callContract.AskPrice + self.callContract.BidPrice
        totalCost = putCost + callCost
        currentProfit = (totalCost - (putPrice + callPrice)) / totalCost
        return currentProfit

    def ClosePositions(self):
        self.Liquidate(self.putContract.Symbol)
        self.Liquidate(self.callContract.Symbol)
        self.positionOpen = False

    def SellAnOTMPut(self, target_DELTA, target_DTE):
        putContract = self.SelectContractByDelta(self.equity.Symbol, target_DELTA, target_DTE, OptionRight.Put)
        orderMessage = f"Stock @ ${self.CurrentSlice[self.equity.Symbol].Close} |" + \
                       f"STO {putContract.Symbol} " + \
                       f"({round(putContract.Greeks.Delta,2)} Delta)"
        self.Debug(f"{self.Time} {orderMessage}")
        self.MarketOrder(putContract.Symbol, -1, False, orderMessage)
        return putContract

    def SellAnOTMCall(self, target_DELTA, target_DTE):
        callContract = self.SelectContractByDelta(self.equity.Symbol, target_DELTA, target_DTE, OptionRight.Call)
        orderMessage = f"Stock @ ${self.CurrentSlice[self.equity.Symbol].Close} |" + \
                       f"STO {callContract.Symbol} " + \
                       f"({round(callContract.Greeks.Delta,2)} Delta)"
        self.Debug(f"{self.Time} {orderMessage}")
        self.MarketOrder(callContract.Symbol, -1, False, orderMessage)
        return callContract

    def SelectContractByDelta(self, symbolArg, strikeDeltaArg, expiryDTE, optionRightArg=OptionRight.Call):
        canonicalSymbol = self.AddOption(symbolArg)
        theOptionChain = self.CurrentSlice.OptionChains[canonicalSymbol.Symbol]
        theExpiryDate = self.Time + timedelta(days=expiryDTE)
        filteredContracts = [x for x in theOptionChain if x.Right == optionRightArg]
        contractsSortedByExpiration = sorted(filteredContracts, key=lambda p: abs(p.Expiry - theExpiryDate), reverse=False)
        closestExpirationDate = contractsSortedByExpiration[0].Expiry
        contractsMatchingExpiryDTE = [contract for contract in contractsSortedByExpiration if contract.Expiry == closestExpirationDate]
        closestContract = min(contractsMatchingExpiryDTE, key=lambda x: abs(abs(x.Greeks.Delta) - strikeDeltaArg))
        return closestContract

    def OptionsFilterFunction(self, optionsContractsChain):
        strikeCount = 10
        min_Expiry_DTE = 0
        max_Expiry_DTE = 45
        return optionsContractsChain.IncludeWeeklys() \
                                    .Strikes(-strikeCount, strikeCount) \
                                    .Expiration(timedelta(min_Expiry_DTE), timedelta(max_Expiry_DTE))