Hello,

I'm working to try and add some information to a DataFrame of options data. To start, I'm just trying to add in the DTE for each row, using df.Apply() and a lambda function to calculate the DTE. The calculation works correctly but adding the new column to the DataFrame fails. I have tried the code on my local machine and it works, but using the QuantConnect web-based IDE it fails. Does anyone know what I might be doing wrong?

In particular I'm getting a KeyError when I try and use df.Apply() to create a new column with a calculation, the KeyError being generated only when the new column is added onto the existing DataFrame.

 

Thanks very much!

 

 The following code line runs fine on my local machine:

def calcDTE(expiry, currDate):
    a = pd.to_datetime(expiry)
    b = pd.to_datetime(currDate)
    return (a-b)/np.timedelta64(1,'D')


#this works just fine on local machine
df['DTE'] = df.apply(lambda x: calcDTE(x['expiry'], time), axis=1)

However the same code fails with KeyError on ‘DTE’ when I run it on the web-based IDE:

def getDTE(self, expiry, currentDate):
        expiryTS = pd.to_datetime(expiry)
        currentDateTS = pd.to_datetime(currentDate)
        diff = (expiryTS - currentDateTS) / np.timedelta64(1,'D')
        return diff

#this causes KeyError on 'DTE' on web-based IDE
rawDF['DTE'] = rawDF.apply(lambda row: self.getDTE(row['expiry'], self.Time), axis=1) 

The full code with context is below, my guess is that something about the functions being part of a class messes up the addition of a new column?

class MuscularTanHorse(QCAlgorithm):

    def Initialize(self):
        self.SetEndDate(2021, 3, 3)  # Set Start Date
        self.SetStartDate(2021,3,1)
        equities = ['MSFT']
        for ticker in equities:
            self.AddEquity(ticker, Resolution.Daily)
            option = self.AddOption(ticker, Resolution.Daily)
            option.SetFilter(self.UniverseFunc)
        
        self.SetCash(100000)  # Set Strategy Cash

    def getDTE(self, expiry, currentDate):
        expiryTS = pd.to_datetime(expiry)
        currentDateTS = pd.to_datetime(currentDate)
        diff = (expiryTS - currentDateTS) / np.timedelta64(1,'D')
        return diff

    def addInfoToDF(self, rawDF, priceHistory): 
        #trying to just add the DTE for now
        testSeries = rawDF.apply(lambda row: self.getDTE(row['expiry'], self.Time), axis=1) #this works, returns series
        rawDF['DTE'] = rawDF.apply(lambda row: self.getDTE(row['expiry'], self.Time), axis=1) #this does not work, KeyError on 'DTE'
        newDF = rawDF.assign(d=dteSeries.values) #does not work, KeyError on 'd'
  
        

    def UniverseFunc(self, universe):
        return universe.IncludeWeeklys().Expiration(TimeSpan.FromDays(0),
                                               TimeSpan.FromDays(20)).Strikes(-3,3)
    def OnData(self, data):
        self.optionData = data.OptionChains
      
        for stockSymbol in data.OptionChains:
            optionchain = stockSymbol.Value #extract this stock's option chain
            underlyingTicker = optionchain.Underlying.Symbol.ToString() #extract the stock's ticker
            underlyingPriceHist = self.History(self.Symbol(underlyingTicker),365) #get recent price history for further calculation
            
            rawDF = pd.DataFrame([[x.Right,float(x.Strike),x.Expiry,float(x.BidPrice),float(x.AskPrice)] for x in optionchain],index=[x.Symbol.Value for x in optionchain], columns=['type', 'strike', 'expiry', 'ask price', 'bid price']) #put options data into DataFrame
            
            dfWithData = self.addInfoToDF(rawDF, underlyingPriceHist) #pass df to helper function to add data
        
        return
        

Author