Estoy intentando realizar una regresión multivariante (14 variables explicativas) en un panel de 5000 acciones:
- Para cada una de las 5.000 acciones, realizo 284 regresiones (recorriendo el periodo de la muestra).
- En resumen: se han realizado 1.420.000 regresiones en total para el panel.
Para ello, utilizo un "bucle for" anidado: bucle sobre los valores y sobre el tiempo. Los coeficientes se exportan a un archivo csv.
Como era de esperar, el problema es que todo el procedimiento tarda una cantidad ENORME de tiempo en completarse. ¿Habría una manera eficiente de manejar esto? (Como me doy cuenta de que la función "aplicar" es más eficiente que un "bucle for", por favor, tenga en cuenta que dado el enorme tiempo de procesamiento, la ganancia de tiempo del uso alternativo de la función "aplicar" seguiría siendo mínima).
A continuación se muestra una instantánea del código:
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)
}
Tenga en cuenta que:
- sec: número de acciones (valores). Cada valor tiene una serie temporal de rendimientos.
- filas: número de periodos de tiempo (a lo largo de los cuales realizamos la regresión)
- beta: matriz de coeficientes de todas las regresiones para cada valor. Se borra cada vez para cada valor.
MODELO:
Este es el modelo de regresión para cada valor i en el momento 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)
donde b son los coeficientes de regresión, f los factores, y e los residuos.
Tenga en cuenta que i está en [1:5000], el número de factores n es 14, y el tiempo t está en [1:343] (343 meses).
-
Para cada valor i En este caso, ejecutamos esta regresión sobre períodos móviles de 60 meses (de ahí el j:j+59 en el código R).
-
Cada regresión rodante se ejecuta sólo si el no NA el número de observaciones de la ventana móvil para la variable dependiente es >= 30 (mientras que las variables independientes no pueden ser NA, las variables dependientes (en este caso los rendimientos de las acciones) pueden tomar valores NA, si la acción cae del índice).
-
Entonces obtenemos 284 = 343 - 60 + 1 coeficientes beta para cada factor f para cada valor i . Estos se almacenan en el marco de datos "beta" (el marco de datos "beta" tiene nr = 284, y ncol = 14+3 (14 factores, intercepción, fecha e identificador).
Así que, en resumen, realizamos 284 regresiones por valor, y tenemos un total de 5000 valores. Esto hace un total de 1.420.000 regresiones.
Para tener una perspectiva, la ejecución de este script tarda unos 50min en completarse con éxito.
Gracias,
3 votos
Bueno, para empezar, hay una alta probabilidad de que su ordenador portátil tiene más de un núcleo, empezar por hacer uso de todos los núcleos
1 votos
Dos ideas; (i) no correr
lm(...)
Utilizar $(X'X)^{-1}X'Y$ . (ii) cada cierto tiempo hacer unwrite.csv'
o unsave
yrm()
para limpiar la memoria, (iii) ejecutar el as.character en todo el vector de fechas en lugar de en una sola fecha en cada iteración del bucle..0 votos
Hecho para el reparto de personajes. Gracias. Sin embargo, el uso de la multiplicación vectorial/matricial en lugar de lm() podría inducir más cálculos previos: ten en cuenta que el vector Y podría tener NA's, mientras que el vector X no puede tomar valores NA. Esto significa que antes de calcular las betas OLS utilizando la forma matricial, tenemos que emparejar el índice de los valores no NA de X, con los valores relevantes de Y, para que estén alineados en el tiempo. La función match() que ayudaría a lograr eso tomaría tiempo en sí misma..
1 votos
Para la concordancia de no-NA intente
data[complete.cases(data),]
0 votos
@pyCthon Dado que todas las regresiones son independientes, parece que lo que sugieres podría mejorar realmente el tiempo de ejecución. Sin embargo, no estoy familiarizado con la computación paralela ni con su implementación en R. Aunque soy un amplio usuario de R, mis conocimientos no son de nivel avanzado.
0 votos
@Mariam en realidad es bastante sencillo y tienes suerte de que no sea tu jefe ;)
0 votos
Necesito utilizar una regresión rodante pero tengo problemas con ella, ¿puedo tener su conjunto de datos para examinar su código? tnx