I have a DataFrame that represents stock returns. To split adjust the closing price, I have the following method:
def returns(ticker, start=None, end=None):
p = historical_prices(ticker, start, end, data='d', convert=True)
d = historical_prices(ticker, start, end, data='v', convert=True)
p['Dividends'] = d['Dividends']
p['Dividends'].fillna(value=0, inplace=True)
p['DivFactor'] = 1.
p['SAClose'] = p['Close']
records, fields = p.shape
for t in range(1, records):
p['SAClose'][t] = p['Adj Close'][t] / p['DivFactor'][t-1] + \
p['Dividends'][t-1]
p['DivFactor'][t] = p['DivFactor'][t-1] * \
(1 - p['Dividends'][t-1] / p['SAClose'][t])
p['Lagged SAClose'] = p['SAClose'].shift(periods=-1)
p['Cash Return'] = p['Dividends'] / p['Lagged SAClose']
p['Price Return'] = p['SAClose'] / p['Lagged SAClose'] - 1
return p.sort_index()
Note how SAClose (i.e. Split Adjusted Close) depends upon lagged DivFactor values. In turn, DivFactor depends on both lagged DivFactor values as well as the current SAClose value.
The method above works, but it is incredibly slow in the loop section. Is there a more efficient way for me to do this in pandas? Given the “circular” dependency (not really circular given the lags), I’m not sure how I could do either regular series math or use normal shift operations (e.g as I do with Cash Return).
You can try creating a cumulative adjustment factor series in one shot then you don’t need to loop: