I am attempting to run a rolling multivariate regression (14 explanatory variables) across a panel of 5000 stocks:
- For each of the 5000 stocks, I run 284 regressions (by rolling over my sample period).
- In summary: 1,420,000 regressions in total are ran for the panel.
To achieve this, I make use a nested "for loop": loop over securities and over time. Coefficients are exported to a csv file.
As expected, the issue is that the entire procedure takes a HUGE amount of time to complete. Would there be an efficient way of handling this? (As I realize that the "apply" function is more efficient than a "for loop", please keep in mind that given the huge processing time, the time gain from the alternative use of the "apply" function would still be minimal).
Here is a snapshot of the code:
sec = ncol(ret.zoo)
num.factors = ncol(data)
rows = nrow(ret.zoo) - 60 + 1
col.names <- c("gvkey", "date", "intercept", colnames(data))
write.table(as.data.frame(t(col.names)), file = paste(path, "betas.csv", sep = ""), row.names = FALSE, col.names = FALSE, sep = ",")
for(i in 1:sec) {
beta = data.frame(matrix(nc = num.factors + 3, nr = rows))
df = merge(ret.zoo[,i], data)
names(df) <- c("return", names(data))
for(j in 1:rows) {
#Checks if number of observations >=30. If so, regression is ran. Otherwise, it is not.
no.na = ret.zoo[j:(j+59),i][which(!is.na(coredata(ret.zoo[j:(j+59),i])))]
if(length(no.na) >= 30) {
beta[j,1] = substr(colnames(ret.zoo)[i],2,7)
beta[j,2] = as.character(index(df[(j+59),])) ### Date
beta[j,3:(num.factors+3)] = coef(lm(return ~., data = as.data.frame(df[j:(j+59),]), na.action = na.omit))
}
}
write.table(beta, file = paste(path, "betas.csv", sep = ""), append = T, sep = ",", row.names = FALSE, col.names = FALSE)
rm(beta)
}
Note that:
- sec: number of stocks (securities). Each security has a time series of returns.
- rows: number of time periods (over which we roll the regression)
- beta: matrix of coefficients of all regressions for each security. It is cleared every time for each sec.
MODEL:
Here is the regression model for each security i at time t :
R(i,t) = a(i,t) + b1(i,t)f1(t) + b2(i,t)f2(t) + .... + bn(i,t)fn(t) + e(i,t)
where b are the regression coefficients, f the factors, and e the residuals.
Note that i is in [1:5000], the number of factors n is 14, and time t is in [1:343] (343 months).
For each security i, we run this regression over rolling periods of 60 months (hence the j:j+59 in R code).
Each rolling regression is ran only if the non-NA number of observations of the rolling window for the dependent variable is >= 30 (While the independent variables cannot be NA, the dependent variables (here stock returns) can take NA values, if the stock drops from the index).
We then obtain 284 = 343 - 60 + 1 beta coefficients for each factor f for each security i. These are stored in the "beta" dataframe (the "beta" dataframe has nr = 284, and ncol = 14+3 (14 factors, intercept, date, and identifier).
So, in summary, we conduct 284 regressions per security, and we have a total of 5000 securities. That makes 1,420,000 regressions in total.
For some perspective, running this script takes about 50min to successfully complete.
Thank you,
lm(...)
, use $(X'X)^{-1}X'Y$. (ii) every so often do awrite.csv'
or asave
, andrm()
to clear memory, (iii) run the as.character on the whole vector of dates instead of on a single date in each loop iteration.. $\endgroup$data[complete.cases(data),]
$\endgroup$