UNIVERSIDAD DE EL SALVADOR

FACULTAD DE CIENCIAS ECONOMICAS

ESCUELA DE ECONOMIA

MATERIA: MÉTODOS PARA EL ANÁLISIS ECONÓMICO

TAREA A31: COINEGRACIÓN Y CAUSALIDAD

DOCENTE: JEFFRY ISAAC BONILLA MELARA

INTEGRANTES:

APELLIDOS NOMBRES CARNET PARTICIPACIÓN
PANIAGUA MUÑOZ CHRISTIAN ALEXANDER PM24066 \(100\%\)
MENDOZA CRUZ ENRIQUE ADOLFO MC24059 \(100\%\)
DELGADO CUELLAR GISELLE ABIGAIL DC24008 \(100\%\)
AGUILAR HERNÁNDEZ ANDREA SARAÍ AH22006 \(100\%\)
MORALES MONZÓN VANESSA MARÍA MM24056 \(100\%\)
ASCENCIO RAMÍREZ MATTHEW JEREMY AR23037 \(100\%\)

CICLO: II-2026

FECHA: 8 DE NOVIEMBRE DE 2026

CIUDAD UNIVERSITARIA, SAN SALVADOR, EL SALVADOR, CENTROAMERICA

Datos utilizados

Se trabaja con tres series mensuales de El Salvador para el periodo enero 2010 – diciembre 2025 (\(T=192\) observaciones), y cada prueba se desarrolla alrededor de una variable protagonista:

  • IVAE (Índice de Volumen de la Actividad Económica, serie original): es la variable de la prueba de Dickey-Fuller (sección 1).
  • IPC (Índice de Precios al Consumidor): es la variable de la prueba de Johansen (sección 2).
  • Remesas (remesas familiares mensuales en USD): es la variable de la prueba de Granger (sección 3).

La prueba de Dickey-Fuller es univariada, por lo que usa solo el IVAE. En cambio, Johansen y Granger comparan series entre sí y no pueden aplicarse a una única variable: Johansen necesita al menos dos series y Granger exactamente un par. Por eso, en la sección 2 el IPC se analiza junto con las remesas y en la sección 3 las remesas se analizan junto con el IVAE, que actúa solo como segunda serie del par.

library(readxl)
library(forecast)
library(TSstudio)
library(urca)
library(tseries)
library(lmtest)
library(kableExtra)

# Se lee solo la columna de datos (C) de cada archivo; col_names fija un nombre limpio
IVAE    <- read_excel("C:/Users/Paniagua/Downloads/econometria christian/Metodos/Datos/IVAE Serie_original.xlsx",     range = "C2:C193", col_names = "IVAE")

IPC     <- read_excel("C:/Users/Paniagua/Downloads/econometria christian/Metodos/Datos/IPC.xlsx",                     range = "C2:C193", col_names = "IPC")

Remesas <- read_excel("C:/Users/Paniagua/Downloads/econometria christian/Metodos/Datos/Remesas mensuales en USD.xlsx", range = "C2:C193", col_names = "Remesas")

# Serie de tiempo multivariada: frecuencia mensual a partir de enero de 2010
X <- ts(data = cbind(IVAE, IPC, Remesas),
        start = c(2010, 1),
        frequency = 12)

IVAEST    <- X[, "IVAE"]
IPCST     <- X[, "IPC"]
RemesasST <- X[, "Remesas"]

autoplot(X, facets = TRUE,
         main = "IVAE, IPC y Remesas de El Salvador, 2010-2025",
         xlab = "Años/Meses", ylab = "")

Resumen de las series
Serie Minimo Media Maximo
IVAE 84.70 107.93 144.30
IPC 100.44 114.53 131.47
Remesas 229.56 479.00 961.12

Las tres series tienen tendencia creciente y, en el caso del IVAE y las remesas, un patrón estacional marcado (picos en diciembre). Ambos rasgos son importantes para interpretar correctamente las pruebas que siguen.


1. Prueba de Raíz Unitaria de Dickey & Fuller

Propósito de la prueba

La prueba de Dickey-Fuller (DF) y su versión aumentada (ADF) sirve para determinar si una serie de tiempo es estacionaria o si, por el contrario, contiene una raíz unitaria (es decir, es no estacionaria, con tendencia estocástica). Es el paso previo obligatorio de cualquier análisis de cointegración: la prueba de Johansen requiere que las variables sean integradas de orden uno, \(I(1)\), y esto se verifica con DF/ADF.

Hipótesis de la prueba

Se parte de un proceso autorregresivo de primer orden:

\[y_t=\varphi\, y_{t-1}+\varepsilon_t,\qquad \varepsilon_t \sim \text{i.i.d.}(0,\sigma^2)\]

Si \(|\varphi|<1\) los choques se disipan con el tiempo y la serie es estacionaria; si \(\varphi=1\) los choques son permanentes (caminata aleatoria) y la serie es no estacionaria. Restando \(y_{t-1}\) a ambos lados se obtiene la forma que realmente se estima:

\[\Delta y_t=(\varphi-1)\,y_{t-1}+\varepsilon_t=\tau\, y_{t-1}+\varepsilon_t,\qquad \tau=\varphi-1\]

Con constante, tendencia determinística y \(p\) rezagos de \(\Delta y_t\) (versión aumentada, que corrige la autocorrelación de los errores):

\[\Delta y_t=\alpha+\beta t+\tau\, y_{t-1}+\sum_{i=1}^{p}\delta_i\,\Delta y_{t-i}+\varepsilon_t\]

Las hipótesis son:

\[H_0:\ \tau=0\ (\varphi=1)\ \text{ la serie tiene raíz unitaria (no estacionaria)}\]

\[H_a:\ \tau<0\ (\varphi<1)\ \text{ la serie es estacionaria}\]

¿Por qué se plantean así? La hipótesis nula es el caso que se quiere descartar con evidencia: asumir que la serie es una caminata aleatoria es la postura conservadora, porque tratar como estacionaria una serie que no lo es produce regresiones espurias. Solo si los datos son suficientemente incompatibles con \(\varphi=1\) se rechaza \(H_0\). La alternativa es unilateral (\(\tau<0\)) porque \(\tau>0\) implicaría una serie explosiva, que no es el caso de interés económico.

Sintaxis de implementación

ur.df(y, type = "trend", lags = 0, selectlags = "Fixed")
  • y: la serie de tiempo a evaluar.
  • type: especificación determinística. "none" (sin constante ni tendencia), "drift" (con constante) o "trend" (con constante y tendencia). Con series que crecen en el tiempo se usa "trend"; para series en primeras diferencias suele bastar "drift".
  • lags: número de rezagos de \(\Delta y_t\) incluidos. Con lags = 0 es la prueba DF simple; con lags > 0 es la ADF.
  • selectlags: "Fixed" usa exactamente lags; "AIC" o "BIC" eligen el mejor número hasta lags.
adf.test(x, alternative = "stationary", k = 0)
  • x: la serie de tiempo.
  • alternative: hipótesis alternativa ("stationary" por defecto).
  • k: número de rezagos del término autorregresivo (k = 0 es DF simple). Esta función ya incluye constante y tendencia y reporta directamente el valor \(p\).

Estadístico de prueba

El estadístico es el cociente \(t\) del coeficiente \(\tau\), pero no sigue una distribución \(t\) de Student bajo \(H_0\), sino la distribución de Dickey-Fuller (valores críticos más exigentes):

\[DF=\frac{\hat\tau}{SE(\hat\tau)}\]

En la salida de urca, @teststat contiene tres estadísticos (tau3, phi2, phi3) y el que corresponde a la prueba de raíz unitaria es el primero, tau3. En @cval se encuentran sus valores críticos al 1 %, 5 % y 10 %:

A <- ur.df(IVAEST, type = "trend", lags = 0)
A@teststat[, 1]   # estadístico DF (tau3)
## [1] -8.720597
A@cval[1, ]       # valores críticos de tau3
##  1pct  5pct 10pct 
## -3.99 -3.43 -3.13

Con tseries el estadístico y el valor \(p\) se extraen así:

B <- suppressWarnings(adf.test(IVAEST, k = 0))
B$statistic
## Dickey-Fuller 
##     -8.720597
B$p.value
## [1] 0.01

Criterio de decisión

Como la región de rechazo está en la cola izquierda, se compara el estadístico con el valor crítico (negativo) o el valor \(p\) con el nivel de significancia \(\alpha=0.05\):

\[\text{Se rechaza } H_0 \text{ si } DF < \tau_{crítico} \;\;(\text{equivale a } |DF|>|\tau_{crítico}|) \quad \text{ó} \quad p_{value}<0.05\]

\[\text{No se rechaza } H_0 \text{ si } DF \geq \tau_{crítico} \quad \text{ó} \quad p_{value}\geq 0.05\]

DF <- as.vector(A@teststat[, 1])
tc <- as.vector(A@cval[1, 2])   # valor crítico al 5 %

if (DF < tc) {
  "Se rechaza H0: la serie es estacionaria"
} else {
  "No se rechaza H0: la serie tiene raíz unitaria (no estacionaria)"
}
## [1] "Se rechaza H0: la serie es estacionaria"

Interpretación del rechazo, o no rechazo de la Hipótesis Nula

  • Si se rechaza \(H_0\): hay evidencia de que \(\varphi<1\); la serie es estacionaria, sus choques son transitorios y puede modelarse en niveles.
  • Si no se rechaza \(H_0\): no hay evidencia de estacionariedad; se considera que la serie tiene raíz unitaria y se debe diferenciar (y probar si la serie diferenciada sí es estacionaria, lo que la clasificaría como \(I(1)\)).

Implementación de un ejemplo

Descomposición de la serie

ts_decompose(IVAEST, type = "additive", showline = TRUE)

La descomposición muestra una tendencia creciente y un componente estacional fuerte (picos en diciembre), dos rasgos que condicionan la prueba.

Prueba DF con lags = 0 (especificación básica)

Hipótesis:

\[H_0:\ \tau=0\ \text{ (el IVAE tiene raíz unitaria)}\qquad H_a:\ \tau<0\ \text{ (el IVAE es estacionario)}\]

adf_tab <- function(lista, lags, type = "trend") {
  do.call(rbind, lapply(names(lista), function(n) {
    a <- ur.df(lista[[n]], type = type, lags = lags)
    data.frame(Serie = n,
               Estadistico = a@teststat[1, 1],
               Critico_5 = a@cval[1, 2],
               Critico_10 = a@cval[1, 3],
               Decision = ifelse(a@teststat[1, 1] < a@cval[1, 2],
                                 "Se rechaza H0 (estacionaria)",
                                 "No se rechaza H0 (raíz unitaria)"))
  }))
}

T0 <- adf_tab(list(IVAE = IVAEST), lags = 0)
T0 %>% kable(digits = 3, align = "c",
             caption = "DF sobre el IVAE, type = 'trend', lags = 0") %>%
  kable_material(c("striped", "hover"))
DF sobre el IVAE, type = ‘trend’, lags = 0
Serie Estadistico Critico_5 Critico_10 Decision
IVAE -8.721 -3.43 -3.13 Se rechaza H0 (estacionaria)

Con lags = 0 el estadístico del IVAE es -8.72, muy por debajo del valor crítico de -3.43 al 5 %, por lo que se rechazaría \(H_0\) y el IVAE parecería estacionario (con tseries, adf.test(IVAEST, k = 0) arroja un valor \(p\) de 0.0100).

Prueba ADF con lags = 12 (corrección por estacionalidad)

La prueba DF simple supone errores sin autocorrelación. En una serie mensual con estacionalidad como el IVAE ese supuesto no se cumple y la prueba con lags = 0 tiende a rechazar \(H_0\) de manera engañosa: la oscilación estacional se confunde con reversión a la media. Por eso se repite la prueba incorporando 12 rezagos (un año completo de dinámica):

T12 <- adf_tab(list(IVAE = IVAEST), lags = 12)
T12 %>% kable(digits = 3, align = "c",
              caption = "ADF sobre el IVAE, type = 'trend', lags = 12") %>%
  kable_material(c("striped", "hover"))
ADF sobre el IVAE, type = ‘trend’, lags = 12
Serie Estadistico Critico_5 Critico_10 Decision
IVAE -2.877 -3.43 -3.13 No se rechaza H0 (raíz unitaria)
suppressWarnings(adf.test(IVAEST, k = 12))$p.value
## [1] 0.2089538

Ahora el estadístico es -2.88, mayor que el valor crítico de -3.43: no se rechaza \(H_0\). Con tseries el valor \(p\) es 0.2090, mayor que 0.05, lo que confirma que el IVAE en niveles tiene raíz unitaria.

¿Es \(I(1)\)? Prueba sobre la primera diferencia

Para que una serie sea \(I(1)\) debe tener raíz unitaria en niveles y ser estacionaria al diferenciarla una vez. En diferencias ya no hay tendencia, por lo que se usa type = "drift":

TD <- adf_tab(list(`Δ IVAE` = diff(IVAEST)), lags = 12, type = "drift")
TD %>% kable(digits = 3, align = "c",
             caption = "ADF sobre la primera diferencia del IVAE, type = 'drift', lags = 12") %>%
  kable_material(c("striped", "hover"))
ADF sobre la primera diferencia del IVAE, type = ‘drift’, lags = 12
Serie Estadistico Critico_5 Critico_10 Decision
Δ IVAE -4.047 -2.88 -2.57 Se rechaza H0 (estacionaria)

El estadístico de la primera diferencia (-4.05) es menor que el crítico de -2.88: se rechaza \(H_0\) y la serie diferenciada es estacionaria. Se concluye que el IVAE es \(I(1)\): no es estacionario en niveles, pero sí en primeras diferencias.


2. Cointegración en el enfoque de Soren Johansen

Propósito de la prueba

La prueba de Johansen determina si dos o más series \(I(1)\) están cointegradas, es decir, si aunque cada una sea no estacionaria existe una o más combinaciones lineales de ellas que sí son estacionarias (relaciones de equilibrio de largo plazo). Además, a diferencia de Engle-Granger, estima cuántas relaciones de cointegración existen (el rango \(r\)), lo que permite trabajar con un modelo de corrección de error vectorial (VECM).

Económicamente, ¿el nivel de precios (IPC) y las remesas se mueven juntos en el largo plazo, de modo que se desvían de una relación común solo temporalmente? Como la prueba requiere al menos dos series, el IPC se analiza junto con las remesas (\(m=2\)).

Hipótesis de la prueba

Sea \(Y_t=(IPC_t,\ Remesas_t)'\) un vector de \(m=2\) variables \(I(1)\) modelado como un VAR de orden \(K\):

\[Y_t=\mu+A_1Y_{t-1}+A_2Y_{t-2}+\dots+A_KY_{t-K}+\varepsilon_t\]

Restando \(Y_{t-1}\) y reagrupando se obtiene su representación en mecanismo de corrección de error (VECM):

\[\Delta Y_t=\mu+\Pi\, Y_{t-1}+\sum_{i=1}^{K-1}\Gamma_i\,\Delta Y_{t-i}+\varepsilon_t\]

con

\[\Pi=\sum_{i=1}^{K}A_i-I,\qquad \Gamma_i=-\sum_{j=i+1}^{K}A_j\]

La matriz \(\Pi\) recoge la información de largo plazo y su rango \(r=\text{rango}(\Pi)\) determina el resultado:

  • \(r=0\): \(\Pi\) es la matriz nula; no hay cointegración y el sistema debe modelarse con un VAR en diferencias.
  • \(0<r<m\): \(\Pi=\alpha\beta'\), donde \(\beta\) contiene los \(r\) vectores de cointegración y \(\alpha\) los coeficientes de ajuste (velocidad de corrección al equilibrio).
  • \(r=m\): todas las variables serían estacionarias en niveles (no aplica si son \(I(1)\)).

El enfoque de máximo valor propio ("eigen") contrasta de forma secuencial:

\[H_0:\ r=r_0\ \text{(existen exactamente } r_0 \text{ relaciones de cointegración)}\qquad H_a:\ r=r_0+1\]

empezando por \(r_0=0\) (con \(m=2\) solo hay dos contrastes: \(r=0\) y \(r\leq1\)):

\[H_0:\ r=0\ \text{ (no existe cointegración)}\qquad H_a:\ r=1\]

La nula es “no hay cointegración” porque es el punto de partida conservador: salvo evidencia en contra, se supone que las series \(I(1)\) no comparten tendencia estocástica. Si se rechaza, se contrasta \(r\leq1\) contra \(r=2\) (rango completo), y el procedimiento se detiene en la primera hipótesis que no se rechaza; ese valor es el rango estimado.

Sintaxis de implementación

ca.jo(x, type = "eigen", ecdet = "trend", K = 2, season = NULL)
  • x: matriz o serie de tiempo multivariada con las variables (aquí Y, con IPC y Remesas).
  • type: estadístico a usar. "eigen" = máximo valor propio (\(\lambda_{max}\)); "trace" = traza.
  • ecdet: componente determinístico. "none", "const" (constante en la relación de cointegración) o "trend" (tendencia lineal en la relación de cointegración). Se usa "trend" porque las series muestran tendencia.
  • K: orden del VAR en niveles (número de rezagos); por defecto 2. La prueba es sensible a esta elección y conviene elegirlo con criterios de información.
  • season: frecuencia para agregar dummies estacionales centradas (por ejemplo 12 en datos mensuales).

Estadístico de prueba

El estadístico de máximo valor propio para contrastar \(H_0:\ r=r_0\) es:

\[\lambda_{max}(r_0)=-T\,\ln\left(1-\hat\lambda_{r_0+1}\right)\]

donde \(\hat\lambda_{r_0+1}\) es el valor propio (correlación canónica) estimado número \(r_0+1\) y \(T\) el tamaño de muestra efectivo. En la salida de R, @teststat entrega los estadísticos en orden inverso: primero \(r\leq1\) y al final \(r=0\); @cval trae sus valores críticos (columnas al 10 %, 5 % y 1 %).

Y <- X[, c("IPC", "Remesas")]                    # sistema bivariado

J <- ca.jo(Y, type = "eigen", ecdet = "trend")   # K = 2 por defecto
J@teststat      # [1] r<=1, [2] r=0
## [1]  1.781798 30.276180
J@cval          # valores críticos (columnas: 10pct, 5pct, 1pct)
##          10pct  5pct  1pct
## r <= 1 | 10.49 12.25 16.26
## r = 0  | 16.85 18.96 23.65

La salida completa:

summary(J)
## 
## ###################### 
## # Johansen-Procedure # 
## ###################### 
## 
## Test type: maximal eigenvalue statistic (lambda max) , with linear trend in cointegration 
## 
## Eigenvalues (lambda):
## [1] 0.147300701041072318320246 0.009334048772907584459735
## [3] 0.000000000000000003509925
## 
## Values of teststatistic and critical values of test:
## 
##           test 10pct  5pct  1pct
## r <= 1 |  1.78 10.49 12.25 16.26
## r = 0  | 30.28 16.85 18.96 23.65
## 
## Eigenvectors, normalised to first column:
## (These are the cointegration relations)
## 
##                IPC.l2    Remesas.l2    trend.l2
## IPC.l2      1.0000000  1.0000000000  1.00000000
## Remesas.l2 -0.1202263 -0.0002351946  0.01660414
## trend.l2    0.2037015 -0.1815918768 -0.05774871
## 
## Weights W:
## (This is the loading matrix)
## 
##                IPC.l2   Remesas.l2                  trend.l2
## IPC.d     -0.01443809 -0.008923349  0.0000000000000003051115
## Remesas.d  3.36493288 -0.475157533 -0.0000000000001672507971

Criterio de decisión

Para cada hipótesis secuencial:

\[\text{Se rechaza } H_0 \text{ si } \lambda_{max}>\lambda_{crítico}\ (5\%)\]

\[\text{No se rechaza } H_0 \text{ si } \lambda_{max}\leq\lambda_{crítico}\ (5\%)\]

(Nótese que es lo inverso de la prueba DF: aquí la región de rechazo está en la cola derecha.)

joh_tab <- function(j) {
  est <- rev(j@teststat)            # r=0, r<=1
  cri <- rev(j@cval[, 2])           # 5 %
  data.frame(Hipotesis_nula = c("r = 0", "r ≤ 1"),
             Estadistico = est,
             Critico_5 = cri,
             Decision = ifelse(est > cri, "Se rechaza H0", "No se rechaza H0"))
}
rango <- function(tab) sum(cumprod(tab$Decision == "Se rechaza H0"))

TJ <- joh_tab(J)
TJ %>% kable(digits = 3, align = "c",
             caption = "Johansen (eigen, ecdet = 'trend', K = 2)") %>%
  kable_material(c("striped", "hover"))
Johansen (eigen, ecdet = ‘trend’, K = 2)
Hipotesis_nula Estadistico Critico_5 Decision
r = 0 &#124; r = 0 30.276 18.96 Se rechaza H0
r <= 1 &#124; r ≤ 1 1.782 12.25 No se rechaza H0

Interpretación del rechazo, o no rechazo de la Hipótesis Nula

  • Se rechaza \(H_0:\ r=0\): hay al menos una relación de cointegración; las series comparten tendencias estocásticas y existe equilibrio de largo plazo.
  • No se rechaza \(H_0:\ r=0\): no hay evidencia de cointegración; las series no tienen relación de largo plazo y deben analizarse en diferencias.
  • Si además se rechazara \(r\leq1\), el rango sería completo (\(r=m=2\)); el primer \(r_0\) que no se rechaza es el número de vectores de cointegración.

Implementación de un ejemplo

Condición previa: IPC y remesas deben ser \(I(1)\)

Se verifica con la ADF de la sección 1 (12 rezagos en niveles y en primeras diferencias):

N12 <- adf_tab(list(IPC = IPCST, Remesas = RemesasST), lags = 12)
D12 <- adf_tab(list(`Δ IPC` = diff(IPCST), `Δ Remesas` = diff(RemesasST)),
               lags = 12, type = "drift")
rbind(N12, D12) %>%
  kable(digits = 3, align = "c", caption = "ADF con 12 rezagos: niveles y primeras diferencias") %>%
  kable_material(c("striped", "hover"))
ADF con 12 rezagos: niveles y primeras diferencias
Serie Estadistico Critico_5 Critico_10 Decision
IPC -2.238 -3.43 -3.13 No se rechaza H0 (raíz unitaria)
Remesas -1.280 -3.43 -3.13 No se rechaza H0 (raíz unitaria)
Δ IPC -2.745 -2.88 -2.57 No se rechaza H0 (raíz unitaria)
Δ Remesas -4.122 -2.88 -2.57 Se rechaza H0 (estacionaria)

En niveles ni el IPC (-2.24) ni las remesas (-1.28) superan el crítico de -3.43: ambas tienen raíz unitaria. Las remesas diferenciadas sí son estacionarias (-4.12); el IPC diferenciado (-2.74) queda cerca del crítico del 5 % (-2.88) y lo rechaza al 10 % (-2.57), por lo que se trata a ambas series como \(I(1)\).

Prueba de Johansen sobre IPC y Remesas

Resultados con la especificación básica (K = 2):

  • Para \(H_0:\ r=0\) el estadístico es 30.28 y el valor crítico al 5 % es 18.96: se rechaza \(H_0\); existe al menos una relación de cointegración.
  • Para \(H_0:\ r\leq1\) el estadístico es 1.78 frente a un crítico de 12.25: no se rechaza \(H_0\); no hay evidencia de rango completo.

Por tanto, el rango estimado es \(\hat r=\) 1: existe 1 vector de cointegración entre el IPC y las remesas.

Sensibilidad: estacionalidad y número de rezagos

Como las remesas son estacionales y la prueba es sensible a \(K\), se repite incorporando dummies estacionales mensuales (season = 12) y con \(K=3\):

J_s2 <- ca.jo(Y, type = "eigen", ecdet = "trend", K = 2, season = 12)
J_s3 <- ca.jo(Y, type = "eigen", ecdet = "trend", K = 3, season = 12)

TS2 <- joh_tab(J_s2)
TS3 <- joh_tab(J_s3)

TS2 %>% kable(digits = 3, align = "c",
              caption = "Johansen con season = 12, K = 2") %>%
  kable_material(c("striped", "hover"))
Johansen con season = 12, K = 2
Hipotesis_nula Estadistico Critico_5 Decision
r = 0 &#124; r = 0 21.352 18.96 Se rechaza H0
r <= 1 &#124; r ≤ 1 2.643 12.25 No se rechaza H0
TS3 %>% kable(digits = 3, align = "c",
              caption = "Johansen con season = 12, K = 3") %>%
  kable_material(c("striped", "hover"))
Johansen con season = 12, K = 3
Hipotesis_nula Estadistico Critico_5 Decision
r = 0 &#124; r = 0 19.495 18.96 Se rechaza H0
r <= 1 &#124; r ≤ 1 3.418 12.25 No se rechaza H0

Con dummies estacionales el estadístico para \(r=0\) baja a 21.35 (\(K=2\)) y 19.49 (\(K=3\)) frente a un crítico de 18.96; en ambos casos el rango estimado es \(\hat r=\) 1. La conclusión (existe una relación de largo plazo entre IPC y remesas) se mantiene, aunque con estacionalidad el rechazo de \(r=0\) es ajustado, por lo que la evidencia es menos contundente que en la especificación básica.

Lectura económica: el nivel de precios y las remesas no pueden alejarse indefinidamente uno del otro; las remesas sostienen el consumo de los hogares y, con ello, la demanda y los precios, y las desviaciones de corto plazo se corrigen con el tiempo mediante los coeficientes de ajuste \(\alpha\).


3. Causalidad en el sentido de Granger

Propósito de la prueba

La prueba de causalidad de Granger evalúa si los valores pasados de una serie \(x\) ayudan a predecir otra serie \(y\), además de lo que ya explican los valores pasados de \(y\). Es una noción de precedencia y capacidad predictiva, no de causalidad estructural: que \(x\) “cause en el sentido de Granger” a \(y\) significa que \(x\) aporta información adelantada, no necesariamente que \(x\) determine a \(y\).

Hipótesis de la prueba

Para contrastar si \(x\) causa a \(y\) se estiman dos regresiones con \(q\) rezagos (order = q).

Modelo no restringido (incluye los rezagos de \(x\)):

\[y_t=\alpha_0+\sum_{i=1}^{q}\alpha_i\,y_{t-i}+\sum_{j=1}^{q}\beta_j\,x_{t-j}+\varepsilon_t\]

Modelo restringido (solo rezagos de \(y\)):

\[y_t=\alpha_0+\sum_{i=1}^{q}\alpha_i\,y_{t-i}+u_t\]

\[H_0:\ \beta_1=\beta_2=\dots=\beta_q=0\ \text{ ($x$ no causa a $y$ en el sentido de Granger)}\]

\[H_a:\ \text{al menos un } \beta_j\neq0\ \text{ ($x$ causa a $y$ en el sentido de Granger)}\]

La nula es que los rezagos de \(x\) no aportan capacidad predictiva: se parte de que no hay precedencia temporal y solo se concluye lo contrario si los rezagos de \(x\) mejoran significativamente el ajuste. La prueba es direccional, por lo que se hace en los dos sentidos (\(x\to y\) y \(y\to x\)); puede haber causalidad en un sentido, en ambos (retroalimentación) o en ninguno.

Sintaxis de implementación

library(lmtest)
grangertest(y ~ x, order = 1, data = datos)
  • y ~ x: fórmula; la prueba contrasta si x causa a y (la variable a explicar va a la izquierda).
  • order: número \(q\) de rezagos de \(x\) y de \(y\) incluidos en las regresiones (order = 1 es causalidad de primer orden).
  • data: objeto con las series (aquí la serie multivariada X).

Estadístico de prueba

Se usa el estadístico \(F\) que compara la suma de cuadrados de los residuos de los modelos restringido (\(SCR_R\)) y no restringido (\(SCR_{NR}\)):

\[F=\frac{(SCR_R-SCR_{NR})/q}{SCR_{NR}/(n-k)}\ \sim\ F_{(q,\ n-k)}\]

donde \(q\) es el número de rezagos de \(x\) (restricciones) y \(k\) el número de parámetros del modelo no restringido. En la salida de R el estadístico aparece en la columna F y su valor \(p\) en Pr(>F):

grangertest(IVAE ~ Remesas, order = 1, data = X)

Criterio de decisión

\[\text{Se rechaza } H_0 \text{ si } F>F_{crítico} \quad \text{ó} \quad p_{value}<0.05\]

\[\text{No se rechaza } H_0 \text{ si } F\leq F_{crítico} \quad \text{ó} \quad p_{value}\geq0.05\]

Interpretación del rechazo, o no rechazo de la Hipótesis Nula

  • Si se rechaza \(H_0\): los rezagos de \(x\) mejoran la predicción de \(y\); hay causalidad de Granger de \(x\) hacia \(y\).
  • Si no se rechaza \(H_0\): los rezagos de \(x\) no aportan información predictiva adicional; no hay evidencia de que \(x\) cause a \(y\).

Implementación de un ejemplo

Se prueban los dos sentidos posibles entre las remesas y el IVAE con order = 1. Las remesas son la variable de interés y el IVAE es la segunda serie del par:

pares <- list(c("Remesas", "IVAE"), c("IVAE", "Remesas"))

gr_tab <- function(datos, order) {
  do.call(rbind, lapply(pares, function(p) {
    g <- grangertest(as.formula(paste(p[2], "~", p[1])), order = order, data = datos)
    data.frame(Hipotesis_nula = paste(p[1], "no causa a", p[2]),
               F = g$F[2],
               Valor_p = g$`Pr(>F)`[2],
               Decision = ifelse(g$`Pr(>F)`[2] < 0.05, "Se rechaza H0", "No se rechaza H0"))
  }))
}

G1 <- gr_tab(X, order = 1)
G1 %>% kable(digits = 4, align = "c",
             caption = "Causalidad de Granger, niveles, order = 1") %>%
  kable_material(c("striped", "hover"))
Causalidad de Granger, niveles, order = 1
Hipotesis_nula F Valor_p Decision
Remesas no causa a IVAE 29.3060 0.0000 Se rechaza H0
IVAE no causa a Remesas 3.6457 0.0577 No se rechaza H0

Resultados con order = 1:

  • Remesas → IVAE: \(F=\) 29.31, \(p\) < 0.001: se rechaza \(H_0\); las remesas rezagadas ayudan a predecir la actividad económica.
  • IVAE → Remesas: \(F=\) 3.65, \(p=\) 0.0577: no se rechaza \(H_0\) al 5 % (sí al 10 %); evidencia débil de que el IVAE anticipa a las remesas.

Con un rezago, la causalidad va de las remesas hacia la actividad económica.

Sensibilidad: series estacionarias y más rezagos

Dos advertencias sobre estos resultados: (i) las series en niveles son \(I(1)\), así que la prueba en niveles puede sobrestimar la significancia; y (ii) con datos mensuales un rezago no captura la dinámica anual. Se repite la prueba con las primeras diferencias (estacionarias) y 12 rezagos:

Dx <- diff(X)
G12 <- gr_tab(Dx, order = 12)
G12 %>% kable(digits = 4, align = "c",
              caption = "Causalidad de Granger, primeras diferencias, order = 12") %>%
  kable_material(c("striped", "hover"))
Causalidad de Granger, primeras diferencias, order = 12
Hipotesis_nula F Valor_p Decision
Remesas no causa a IVAE 2.3204 0.0094 Se rechaza H0
IVAE no causa a Remesas 4.5510 0.0000 Se rechaza H0

Con diferencias y 12 rezagos se rechaza \(H_0\) en ambos sentidos (Remesas → IVAE: \(p=\) 0.0094; IVAE → Remesas: \(p\) < 0.001), es decir, hay retroalimentación entre remesas y actividad económica. Lo que sí es robusto a la especificación es que las remesas anticipan al IVAE; que el IVAE anticipe a las remesas solo aparece al considerar la dinámica anual.


Conclusiones

  1. Raíz unitaria (IVAE): con la prueba DF simple (lags = 0) el IVAE parece estacionario, pero es un resultado inducido por su estacionalidad; con 12 rezagos tiene raíz unitaria en niveles y es estacionario en primeras diferencias, es decir, \(I(1)\).
  2. Cointegración (IPC y remesas): la prueba de Johansen detecta una relación de largo plazo entre el IPC y las remesas (rango estimado \(\hat r=\) 1), que se mantiene al incorporar estacionalidad aunque con un rechazo más ajustado.
  3. Causalidad de Granger (remesas e IVAE): las remesas tienen poder predictivo sobre el IVAE tanto en niveles con un rezago como en diferencias con 12 rezagos; el sentido inverso solo aparece con la dinámica anual.
  4. Moraleja metodológica: en series mensuales estacionales el resultado de las pruebas depende del número de rezagos y del tratamiento de la estacionalidad, por lo que siempre conviene reportar la sensibilidad.

Referencias

  • Dickey, D. A. y Fuller, W. A. (1979). Distribution of the estimators for autoregressive time series with a unit root. Journal of the American Statistical Association, 74, 427-431.
  • Engle, R. F. y Granger, C. W. J. (1987). Co-integration and error correction: representation, estimation, and testing. Econometrica, 55(2), 251-276.
  • Granger, C. W. J. y Newbold, P. (1974). Spurious regressions in econometrics. Journal of Econometrics, 2, 111-120.
  • Johansen, S. y Juselius, K. (1990). Maximum likelihood estimation and inference on cointegration, with applications to the demand for money. Oxford Bulletin of Economics and Statistics, 52(2), 169-210.
  • Catalán, H. Teoría de cointegración (curso internacional Construcción de escenarios económicos y econometría avanzada, CEPAL/Universidad Nacional de Colombia).
  • Chung, V. Modelos VEC en R.
  • Montero, R. (2013). Variables no estacionarias y cointegración. Documentos de Trabajo en Economía Aplicada, Universidad de Granada.
  • finnstats (2021). Granger causality test in R (with example). R-bloggers.