Causalidad de Granger

La causalidad de Granger plantea una pregunta puramente predictiva: ¿ayuda el pasado de una serie temporal a predecir otra, más allá de lo que ya aporta el propio pasado de esa serie? Esta entrada amplía la breve mención del post del modelo VAR, desarrollando a mano el test F que compara los modelos restringido y sin restringir, y mostrando por qué el test es capaz de detectar una relación predictiva real y asimétrica.

Modelo restringido frente a sin restringir

Para contrastar si \(x\) causa en el sentido de Granger a \(y\) con retardo \(p\), se comparan dos regresiones anidadas de \(y\) sobre su propio pasado:

\[\text{Restringido: } y_t = \alpha + \sum_{i=1}^p \beta_i y_{t-i} + \varepsilon_t\] \[\text{Sin restringir: } y_t = \alpha + \sum_{i=1}^p \beta_i y_{t-i} + \sum_{j=1}^p \gamma_j x_{t-j} + u_t\]

\[H_0: \gamma_1 = \gamma_2 = \cdots = \gamma_p = 0 \quad (x \text{ no causa en el sentido de Granger a } y)\]

Se contrasta \(H_0\) con un test F que compara cuánto se reduce la suma de cuadrados residual al añadir los retardos de \(x\):

\[F = \frac{(SCR_r - SCR_u)/q}{SCR_u/(n-k)}\]

donde \(q\) es el número de restricciones (los \(p\) retardos de \(x\) eliminados) y \(k\) es el número de parámetros del modelo sin restringir.

Ejemplo resuelto: ¿realmente x impulsa a y?

Dos series simuladas con una relación asimétrica conocida

Se simulan dos series en las que \(x\) impulsa realmente a \(y\) con un retardo de un periodo, y \(y\) NO impulsa a \(x\), así que el test debería detectar correctamente esa asimetría:

set.seed(1)
T <- 100
x <- numeric(T); y <- numeric(T)
for (t in 2:T) x[t] <- 0.5 * x[t-1] + rnorm(1)
for (t in 3:T) y[t] <- 0.3 * y[t-1] + 0.5 * x[t-1] + rnorm(1)

Contrastando el retardo 1 sobre las observaciones \(t=3,\ldots,100\) (\(n=98\)):

Modelo restringido: \(\hat y_t = 0{,}094 + 0{,}339\, y_{t-1}\), \(SCR_r = 107{,}80\), \(gl\) residuales \(= 96\).

Modelo sin restringir: \(\hat y_t = -0{,}019 + 0{,}303\, y_{t-1} + 0{,}446\, x_{t-1}\), \(SCR_u = 89{,}47\), \(gl\) residuales \(= 95\).

\[F = \frac{(107{,}80 - 89{,}47)/1}{89{,}47/95} = \frac{18{,}33}{0{,}9418} = 19{,}46\]

\(gl = (1, 95)\), \(p = 2{,}71 \times 10^{-5}\). Decisión: rechazamos \(H_0\), \(x\) causa en el sentido de Granger a \(y\).

Ahora se contrasta la dirección INVERSA (¿causa \(y\) a \(x\) en el sentido de Granger?), mismos datos, mismo retardo: \(F = 1{,}17\), \(gl = (1, 95)\), \(p = 0{,}282\). Decisión: no rechazamos \(H_0\), no hay evidencia de que \(y\) cause a \(x\) en el sentido de Granger, lo cual coincide correctamente con el proceso generador de datos real (solo \(x\) impulsaba a \(y\), nunca al revés).

lmtest::grangertest() ejecutado sobre los mismos datos reproduce esto de forma muy cercana (dirección directa: \(F \approx 19{,}67\), \(p \approx 2{,}45 \times 10^{-5}\); dirección inversa: \(F = 1{,}17\), \(p = 0{,}282\)); la pequeña diferencia numérica frente a los cálculos a mano se debe únicamente a cómo la función alinea internamente la muestra retardada, no a un desacuerdo real.

Example icon

Dos series temporales simuladas x e y, mostrando cómo y tiende a seguir a x con un retardo de un periodo

Visualmente, los picos de \(x\) tienden a repetirse en \(y\) un paso después, exactamente la dependencia retardada que detecta el test F.

Ampliación a un marco VAR completo

En la práctica, la causalidad de Granger se suele contrastar dentro de un modelo VAR ya ajustado, con vars::causality(), que ya cubre la estimación del VAR, la selección del retardo por AIC/BIC, las funciones de impulso-respuesta y la descomposición de la varianza del error de predicción. El ejemplo anterior con dos series y un único retardo es el caso más simple de exactamente esta misma lógica de test F, generalizada en un VAR a cualquier número de variables y retardos a la vez.

⚠️ La causalidad de Granger contrasta predictibilidad, no causalidad real

La causalidad de Granger indica que \(x\) contiene información que mejora la predicción de \(y\). NO establece que cambiar \(x\) vaya a cambiar \(y\). Contraejemplos clásicos: una tercera variable de confusión que impulsa ambas series de forma independiente, o una causalidad inversa por anticipación, los precios de una acción pueden parecer “causar en el sentido de Granger” los anuncios de resultados de una empresa simplemente porque el mercado descuenta las expectativas antes del anuncio, no porque los precios causen los resultados.

Ambas series también deben ser estacionarias antes de aplicar el test, o estar correctamente cointegradas y modeladas mediante un VECM, de lo contrario la distribución de referencia del test F no es válida. Conviene comprobarlo siempre antes con el test de Dickey-Fuller y con el post general de estacionariedad.

Ejecutar el test en R

set.seed(1)
T <- 100
x <- numeric(T); y <- numeric(T)
for (t in 2:T) x[t] <- 0.5 * x[t-1] + rnorm(1)
for (t in 3:T) y[t] <- 0.3 * y[t-1] + 0.5 * x[t-1] + rnorm(1)

library(lmtest)
grangertest(y ~ x, order = 1)   # ¿causa x a y en el sentido de Granger?
grangertest(x ~ y, order = 1)   # ¿causa y a x en el sentido de Granger?

# Dentro de un modelo VAR ya ajustado
library(vars)
fit <- VAR(cbind(x, y), p = 1, type = "const")
causality(fit, cause = "x")

💡 Elige bien el retardo, y contrasta siempre las dos direcciones

El retardo \(p\) del test de Granger debe elegirse igual que en la selección de retardo de un VAR: por AIC o BIC (consulta el post del modelo VAR). Contrasta siempre las DOS direcciones, como se hizo en el ejemplo resuelto anterior. Los sistemas reales son a menudo asimétricos, \(x\) puede causar en el sentido de Granger a \(y\) sin que \(y\) cause a \(x\), exactamente como se ha mostrado aquí, y contrastar solo una dirección corre el riesgo de pasar por alto esa asimetría por completo.