0
votes

I need to compute rolling window regressions in Python where the standard errors are corrected for HAC (Newey-West, 1987). I know that statsmodels has a function for rolling window regressions (Rolling Regression), but the standard errors cannot be corrected for HAC in this function. Therefore I have defined my own function.

I have a panel data set with 108,768 rows (410 unique funds) and the structure looks as follows:

df = pd.DataFrame({
    "Fund": ["A", "A", "A", "A", "B", "B", "B", "B"], 
    "Excess_Return": [np.NaN, 0.172, 0.0465, 0.039, 0.003995, -0.022139, 0.009518, 0.03233],
    "Regression_Constant": [1,1,1,1,1,1,1,1], 
    "RMRF": [0.0118,0.0557,0.0129,0.0403,0.0118,0.0557,0.0129,0.0403], 
    "SMB": [0.0445,0.1838,-0.1539,-0.0496,0.0445,0.1838,-0.1539,-0.0496], 
    "HML": [-0.0189,-0.0981,0.0823,0.0725,-0.0189,-0.0981,0.0823,0.0725], 
    "RMW": [-0.0629,-0.1876,0.1182,0.0767,-0.0629,-0.1876,0.1182,0.0767], 
    "CMA": [0.0474,-0.0035,-0.0161,0.0562,0.0474,-0.0035,-0.0161,0.0562]})

The function is defined as follows:

t = 36 # sliding window of length
min_t = 30 # minimum number of observations

alpha = []
t_alpha = []
t_RMRF = []
t_SMB = []
t_HML = []
t_RMW = []
t_CMA = []
R2 = []


def rolling_window_regression(dataframe):
    
    for i in range(len(dataframe) - t):
        
        y = dataframe["Excess_Return"].loc[i:i+t]
        X = dataframe[["Regression_Constant", "RMRF", "SMB",
                  "HML", "RMW", "CMA"]].loc[i:i+t]
        
        if y.count()<min_t:
                
            alpha.append(np.NaN)
            t_alpha.append(np.NaN)
            t_RMRF.append(np.NaN)
            t_SMB.append(np.NaN)
            t_HML.append(np.NaN)
            t_RMW.append(np.NaN)
            t_CMA.append(np.NaN)
            R2.append(np.NaN)
                
        else:
            
            lr = sm.OLS(y, X, missing = "drop")
            results = lr.fit(cov_type="HAC", cov_kwds={"maxlags":1})
            alpha.append(results.params[0])
            t_alpha.append(results.bse[0])
            t_RMRF.append(results.bse[1])
            t_SMB.append(results.bse[2])
            t_HML.append(results.bse[3])
            t_RMW.append(results.bse[4])
            t_CMA.append(results.bse[5])
            R2.append(results.rsquared)          

Since I have different funds, the rolling regressions need to be computed for each fund in my sample. Therefore, the command to run the function is as follows:

df.groupby("Fund", dropna = False).apply(rolling_window_regression)

When executing the function, instead of receiving a list of e.g. alphas (constants) with 108,768 entries, the list only contains 93,936 entries. I don't get why this is the case. Furthermore, for the first fund, the function returns correct values, however, for the remaining funds the results are just NaNs. Why might this be the case?