Quant500 Academy

2. Características: retardos y ventanas móviles

Nivel 8: Series Temporales - Estacionariedad

Una serie temporal debe reformularse como un problema de aprendizaje supervisado antes de poder aplicarle algoritmos de machine learning. En una serie temporal no existe el concepto de variables de entrada y de salida: solo hay una columna de valores y un índice de tiempo. Tenemos que elegir la variable a predecir y construir mediante ingeniería de características todas las entradas que usaremos para predecir pasos futuros.

Lo que hay que transformar es esto:

en esto:

Características de retardo (lag features). Son la forma clásica de convertir una predicción temporal en aprendizaje supervisado. El enfoque más simple es predecir el valor en el instante siguiente (t+1) dado el valor actual (t). En pandas, shift(k) desplaza la serie k posiciones hacia abajo, de modo que en la fila de hoy aparece el valor de hace k días:

values = pd.DataFrame(df.values)
df2 = pd.concat([values.shift(2), values.shift(1), values], axis=1)
df2.columns = ['t-2', 't-1', 't']
df2.head()

Las dos primeras filas contendrán valores nulos: en la primera observación no existe un t-1 ni un t-2. Es el precio inevitable de mirar hacia atrás y la razón por la que un modelo con muchos retardos pierde el arranque de la muestra.

Estadísticos de ventana móvil (rolling window). Un paso más allá de añadir valores retardados en bruto es añadir un resumen de los valores de los instantes previos. Podemos calcular estadísticos sobre los valores que caen dentro de una ventana deslizante e incluirlos como características. El más útil suele ser la media de los valores anteriores, la media móvil:

values = pd.DataFrame(df.values)
shifted = values.shift(1)
window = shifted.rolling(window=2)
means = window.mean()

df3 = pd.concat([means, values], axis=1)
df3.columns = ['mean(t-2,t-1)', 't']
df3.head()

Fíjate en el detalle crítico: primero se desplaza y después se aplica la ventana. Ese shift(1) es lo que garantiza que la media de la fila t se calcula con t-2 y t-1, sin incluir el propio valor de t. Si aplicaras values.rolling(window=2).mean() directamente, la característica de la fila t contendría información del instante t, es decir, del propio valor que quieres predecir. Eso es sesgo de anticipación (lookahead bias), el error que más backtests espectaculares y falsos ha producido en la historia del trading cuantitativo.

Estadísticos de ventana expansiva (expanding window). Otro tipo de ventana útil incluye todos los datos previos de la serie. Se llama ventana expansiva y ayuda a llevar la cuenta de los límites de lo observado hasta la fecha:

values = pd.DataFrame(df.values)
window = values.expanding()

df4 = pd.concat([window.mean(), values], axis=1)
df4.columns = ['mean', 't']
df4.head()

La diferencia práctica entre ambas: la ventana móvil tiene memoria finita y olvida el pasado lejano, por lo que se adapta a cambios de régimen; la expansiva nunca olvida, así que se vuelve cada vez más estable y cada vez más lenta en reaccionar. Para máximos históricos, drawdowns o normalizaciones acumuladas, la expansiva es la correcta. Para una media que deba reflejar el mercado actual, la móvil.

El resto de Quant500

Lo que estás aprendiendo, aplicado al índice todos los días:

La cartera del modelo, cada semana en tu correo

Cada sábado, su semana en un minuto: cómo fue, lo mejor y lo peor, y qué directivos compraron con su dinero. Y el día que el modelo se rehace, qué entra y qué sale. Es una simulación, no un consejo. Como mucho un correo a la semana, sin publicidad y sin cuenta; te das de baja con un clic. Lo hace una persona: Pol Gracia.

Cartera modelo con resultados simulados, no una recomendación personalizada. Tu correo se usa solo para esto: privacidad.

Detrás de la Academia y del resto de Quant500 hay una sola persona: Pol Gracia Serrahima.