Cointegración y Causalidad

Planteamiento: préstamos y depósitos del sector privado

Los préstamos y los depósitos forman parte del mismo balance bancario, por lo que se espera que no se alejen indefinidamente uno del otro. En El Salvador esto cobra importancia porque, desde la dolarización (2001), el sistema no tiene emisión monetaria propia ni política monetaria independiente, y los depósitos son una fuente central de fondeo del crédito.

La literatura ofrece dos lecturas de esa relación:

  • Intermediación (fondos prestables). Los bancos captan depósitos y luego los prestan. Los depósitos anteceden a los préstamos y, ante un desequilibrio, quienes se ajustan son los préstamos.
  • Dinero endógeno Los bancos otorgan crédito y, al hacerlo, crean el depósito correspondiente. Los préstamos anteceden a los depósitos y, ante un desequilibrio, quienes se ajustan son los depósitos.

Si ambas variables mantienen una relación estable en el largo plazo, esta puede escribirse como

\[L_t = c\,D_t^{\beta} \quad\Longrightarrow\quad \ln L_t = \ln c + \beta \ln D_t\]

donde \(L_t\) son los préstamos, \(D_t\) los depósitos y \(\beta\) es la elasticidad de largo plazo. Si \(\beta = 1\), los préstamos crecen en proporción a los depósitos y la razón préstamos/depósitos es estable; si \(\beta < 1\), los depósitos crecen más rápido. Las restricciones de liquidez y la regulación prudencial acotan esa razón, lo que da fundamento a esperar cointegración.

Esto deja tres preguntas contrastables: (1) si existe una relación de equilibrio de largo plazo (cointegración, sección 2); (2) cuál es su elasticidad \(\beta\); y (3) cuál variable se ajusta ante un desequilibrio y cuál anticipa a la otra en el corto plazo (VECM y Granger, secciones 2 y 3). La causalidad de Granger y los coeficientes de ajuste miden precedencia estadística, no causalidad estructural.

1. Prueba de raíz unitaria de Dickey & Fuller

1.1 Propósito de la prueba

La prueba de Dickey & Fuller (1979) contrasta si una serie de tiempo tiene una raíz unitaria, es decir, si es no estacionaria (\(I(1)\)) o estacionaria (\(I(0)\)). Una serie con raíz unitaria sigue un camino aleatorio: sus choques son permanentes y su varianza crece con el tiempo, \(Var(y_t) = t\,\sigma^2\) (Catalán). Se usa para:

  • Evitar regresiones espurias: relaciones con \(R^2\) alto y estadísticos \(t\) significativos entre series no estacionarias que en realidad no están relacionadas (Granger y Newbold, 1974; Montero, 2013).
  • Decidir si hay que diferenciar la serie: es \(I(d)\) si se vuelve estacionaria al diferenciarla \(d\) veces (Montero, 2013).
  • Verificar que las series sean \(I(1)\) antes de aplicar la prueba de Johansen (Sandoval).

1.2 Hipótesis de la prueba

Se parte de un proceso autorregresivo de orden 1 y se resta \(y_{t-1}\) en ambos lados:

\[y_t = \phi\, y_{t-1} + \varepsilon_t \quad\Rightarrow\quad \Delta y_t = (\phi - 1)\, y_{t-1} + \varepsilon_t = \alpha\, y_{t-1} + \varepsilon_t, \qquad \alpha = \phi - 1\]

\[H_0: \alpha = 0 \;\Rightarrow\; \phi = 1 \qquad \text{(raíz unitaria: la serie es no estacionaria)}\]

\[H_1: \alpha < 0 \;\Rightarrow\; \phi < 1 \qquad \text{(no hay raíz unitaria: la serie es estacionaria)}\]

¿Por qué estas hipótesis?

  • \(H_0\) es la postura de partida. Si \(\alpha = 0\), entonces \(\Delta y_t = \varepsilon_t\): la serie es un camino aleatorio y su nivel actual no influye en el cambio siguiente (Wikipedia). Solo se rechaza si los datos aportan evidencia en contra.
  • \(H_1\) es unilateral (\(\alpha < 0\)). Una serie estacionaria regresa a su media: los valores altos van seguidos de cambios negativos, y por eso el nivel predice el cambio con signo negativo (Wikipedia). Un \(\alpha > 0\) sería una serie explosiva. Para concluir que la serie es estacionaria se requiere rechazar \(H_0\) y que \(\hat\alpha\) sea negativo (Catalán).

Versión aumentada (ADF). Para corregir la autocorrelación de los errores se agregan \(k\) rezagos, y se puede incluir intercepto y tendencia:

\[\Delta y_t = \delta_0 + \delta_1 t + \alpha\, y_{t-1} + \sum_{i=1}^{k}\gamma_i\,\Delta y_{t-i} + \varepsilon_t\]

La hipótesis nula sigue siendo \(H_0: \alpha = 0\). Si se quita la tendencia (\(\delta_1 t\)) queda el modelo con intercepto, y si además se quita \(\delta_0\) queda el modelo sin términos; cada versión tiene sus propios valores críticos (Catalán; Wikipedia).

1.3 Sintaxis de implementación en R

Con la librería urca:

ur.df(y, type = c("none", "drift", "trend"), lags = 1,
      selectlags = c("Fixed", "AIC", "BIC"))
Argumento Descripción
y Serie de tiempo a la que se aplica la prueba.
type Modelo de la regresión: "none" (sin intercepto ni tendencia), "drift" (con intercepto) o "trend" (con intercepto y tendencia).
lags Número de rezagos \(k\). Con lags = 0 es la prueba simple y con lags > 0 la aumentada. Montero (2013) indica que normalmente basta con 4 a 7.
selectlags Cómo se eligen los rezagos: "Fixed" usa lags; "AIC" o "BIC" los eligen por criterio de información, con lags como máximo.

Con la librería tseries:

adf.test(x, alternative = c("stationary", "explosive"),
         k = trunc((length(x) - 1)^(1/3)))
Argumento Descripción
x Serie de tiempo (vector numérico o ts).
alternative Hipótesis alternativa: "stationary" (por defecto) o "explosive".
k Número de rezagos. Por defecto es trunc((length(x) - 1)^(1/3)).

Salida en R. Se aplican ambas funciones a una serie simulada que es un camino aleatorio (solo para mostrar cómo sale la salida):

set.seed(123)
sim <- cumsum(rnorm(100))                      # camino aleatorio

adf.test(sim, k = 0)                           # tseries
## 
##  Augmented Dickey-Fuller Test
## 
## data:  sim
## Dickey-Fuller = -1.9361, Lag order = 0, p-value = 0.6031
## alternative hypothesis: stationary
sim_df <- ur.df(sim, type = "trend", lags = 0) # urca
summary(sim_df)
## 
## ############################################### 
## # Augmented Dickey-Fuller Test Unit Root Test # 
## ############################################### 
## 
## Test regression trend 
## 
## 
## Call:
## lm(formula = z.diff ~ z.lag.1 + 1 + tt)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -2.33007 -0.54821 -0.05794  0.57726  2.18113 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)  
## (Intercept) -0.007472   0.183292  -0.041   0.9676  
## z.lag.1     -0.095260   0.049201  -1.936   0.0558 .
## tt           0.006675   0.003937   1.695   0.0933 .
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.9049 on 96 degrees of freedom
## Multiple R-squared:  0.04211,    Adjusted R-squared:  0.02215 
## F-statistic:  2.11 on 2 and 96 DF,  p-value: 0.1268
## 
## 
## Value of test-statistic is: -1.9361 1.7858 2.1101 
## 
## Critical values for test statistics: 
##       1pct  5pct 10pct
## tau3 -4.04 -3.45 -3.15
## phi2  6.50  4.88  4.16
## phi3  8.73  6.49  5.47

En adf.test() aparecen Dickey-Fuller (el estadístico), Lag order (el \(k\) usado) y p-value. En ur.df() aparecen la regresión estimada (z.lag.1 es \(\hat\alpha\)), el Value of test-statistic y los Critical values. Ambas dan el mismo estadístico porque adf.test() equivale a ur.df(type = "trend").

1.4 Estadístico de prueba

El estadístico es el cociente \(t\) del coeficiente de \(y_{t-1}\):

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

No sigue la distribución \(t\) de Student: tiene su propia distribución, la tabla de Dickey-Fuller (Wikipedia), construida por simulación (Dickey y Fuller, 1979; MacKinnon, 1994; Montero, 2013). Bajo \(H_0\) tiende a tomar valores negativos (Catalán).

En la salida de R: en ur.df() es el primer valor de Value of test-statistic is: (columna tau3), igual al t value de z.lag.1; en adf.test() es el valor que sigue a Dickey-Fuller =. Los otros dos valores de ur.df() (phi2 y phi3) son pruebas conjuntas que no se usan aquí.

sim_df@teststat[1, "tau3"]     # estadístico Dickey-Fuller
## [1] -1.936144

1.5 Criterio de decisión

El estadístico debe ser negativo, y para rechazar \(H_0\) tiene que ser menor (más negativo) que el valor crítico.

Función Regla (nivel de significancia del 5%)
ur.df() Se rechaza \(H_0\) si \(DF <\) valor crítico 5pct.
adf.test() Se rechaza \(H_0\) si el valor p \(< 0.05\).

En la salida de R: los valores críticos están en Critical values for test statistics:, fila tau3, columnas 1pct, 5pct y 10pct. ur.df() no da valor p; adf.test() sí (si aparece 0.01, significa que es menor o igual a \(0.01\)).

est <- sim_df@teststat[1, "tau3"]    # estadístico DF
cv  <- sim_df@cval["tau3", "5pct"]   # valor crítico al 5%
est < cv                             # TRUE = se rechaza H0
## [1] FALSE

En la serie simulada, \(-1.9361\) no es menor que \(-3.45\), por lo que no se rechaza \(H_0\) al 5%.

1.6 Interpretación del rechazo o no rechazo de la hipótesis nula

Decisión Interpretación
No se rechaza \(H_0\) (\(DF \geq\) valor crítico, o valor p \(> 0.05\)) No hay evidencia contra la raíz unitaria: la serie es no estacionaria (\(\phi = 1\)).
Se rechaza \(H_0\) (\(DF <\) valor crítico, o valor p \(< 0.05\)) La serie es estacionaria, \(I(0)\) (\(\phi < 1\)), siempre que \(\hat\alpha < 0\).

Si no se rechaza \(H_0\) en niveles, se repite la prueba con la primera diferencia: si ahí se rechaza, la serie es \(I(1)\). La prueba tiene bajo poder frente a procesos cercanos a la raíz unitaria (Wikipedia) y pierde fiabilidad si hay cambio estructural (Perron, 1989, citado en Montero, 2013).

1.7 Implementación de un ejemplo

Variables.

\[\Delta \log(\text{depósitos}_t) = \log(\text{depósitos}_t) - \log(\text{depósitos}_{t-1}) \qquad \Delta \log(\text{préstamos}_t) = \log(\text{préstamos}_t) - \log(\text{préstamos}_{t-1})\]

En el código se llaman dlog_depositos y dlog_prestamos.

Se aplica la prueba de Dickey-Fuller aumentada (ADF, con \(k = 4\) rezagos) a los préstamos y a los depósitos del sector privado (mensuales, 2010-2025). A cada serie se le aplica primero en niveles y luego en primera diferencia.

Hipótesis:

\[H_0: \text{la serie tiene raíz unitaria (no es estacionaria)} \qquad H_A: \text{la serie es estacionaria}\]

Criterio de decisión: se rechaza \(H_0\) si el valor p \(< 0.05\).

library(tseries)
library(forecast)

ruta_prestamos <- "C:/Users/JOSE CASTRO/OneDrive - office/Escritorio/Metodos Analisis/Prestamos.csv"
ruta_depositos <- "C:/Users/JOSE CASTRO/OneDrive - office/Escritorio/Metodos Analisis/Depositos.csv"

leer_serie <- function(archivo) {
  x <- read.csv(archivo, header = FALSE, skip = 5, nrows = 6,
                fileEncoding = "UTF-8-BOM", stringsAsFactors = FALSE)
  ts(unname(colSums(x[, -1])), start = c(2010, 1), frequency = 12)
}

log_prestamos <- log(leer_serie(ruta_prestamos))
log_depositos <- log(leer_serie(ruta_depositos))

Préstamos

# Gráfico
log_prestamos %>% autoplot(main = "Logaritmo de Préstamos del Sector Privado (2010-2025)",
                           xlab = "Años/Meses", ylab = "log(Préstamos)")

# ADF en niveles
adf.test(log_prestamos, k = 4)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  log_prestamos
## Dickey-Fuller = -3.1077, Lag order = 4, p-value = 0.1126
## alternative hypothesis: stationary
# ADF en primera diferencia
dlog_prestamos <- diff(log_prestamos)
adf.test(dlog_prestamos, k = 4)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  dlog_prestamos
## Dickey-Fuller = -4.9189, Lag order = 4, p-value = 0.01
## alternative hypothesis: stationary

Con \(k = 4\), en niveles el valor p es \(0.1126\), mayor que \(0.05\), por lo que no se rechaza \(H_0\): la serie no es estacionaria. En primera diferencia, el valor p es menor o igual a \(0.01\) (menor que \(0.05\)), por lo que se rechaza \(H_0\): la serie diferenciada es estacionaria. Por tanto, con \(k = 4\) los préstamos son \(I(1)\).

Depósitos

# Gráfico
log_depositos %>% autoplot(main = "Logaritmo de Depósitos del Sector Privado (2010-2025)",
                           xlab = "Años/Meses", ylab = "log(Depósitos)")

# ADF en niveles
adf.test(log_depositos, k = 4)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  log_depositos
## Dickey-Fuller = -1.1827, Lag order = 4, p-value = 0.9069
## alternative hypothesis: stationary
# ADF en primera diferencia
dlog_depositos <- diff(log_depositos)
adf.test(dlog_depositos, k = 4)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  dlog_depositos
## Dickey-Fuller = -7.2829, Lag order = 4, p-value = 0.01
## alternative hypothesis: stationary

En niveles, el valor p es \(0.9069\), mayor que \(0.05\), por lo que no se rechaza \(H_0\): la serie no es estacionaria. En primera diferencia, el valor p es menor o igual a \(0.01\) (menor que \(0.05\)), por lo que se rechaza \(H_0\): la serie diferenciada es estacionaria. Por tanto, los depósitos son \(I(1)\).

Los préstamos y los depósitos del sector privado son series \(I(1)\): ninguna es estacionaria en niveles y ambas lo son en primera diferencia, aunque en los préstamos este resultado depende del número de rezagos y se trata con cautela.

2. Cointegración en el enfoque de Soren Johansen.

2.1 Propósito de la prueba

La prueba de cointegración de Johansen es un método multivariado que se utiliza en econometría y análisis de series temporales para determinar si existe una relación de equilibrio a largo plazo entre dos o más series de tiempo no estacionarias integradas del mismo orden. Sus propósitos principales son:

  • Identificar relaciones de largo plazo: Evalúa si las variables comparten tendencias estocásticas comunes, haciendo que se muevan de forma coordinada a lo largo del tiempo.

  • Evitar regresiones espurias: Previene conclusiones erróneas producto de correlaciones coincidentes entre series no estacionarias.

  • Determinar el número de vectores de cointegración (\(r\)): Identifica la cantidad exacta de combinaciones lineales estacionarias que existen entre el conjunto de variables.

De este modo, la cointegración se refiere entonces a aquellas series que siendo no estacionarias terminan siendo estacionarias cuando se combinan. En palabras de Granger: «En la práctica, muchos pares de series macroeconómicas parecen tener dicha propiedad, tal como se deduce de la teoría económica»

2.2 Hipótesis de la prueba

La prueba parte de un VAR en niveles reescrito como modelo de corrección de errores (VECM):

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

\(\beta\) contiene la relación de equilibrio de largo plazo (vector de cointegración) y \(\alpha\) la velocidad con que cada variable corrige los desvíos. La cointegración se decide por el rango \(r\) de \(\Pi\). Con dos variables y el estadístico del máximo valor propio:

\[H_0: r = 0 \;\; \text{frente a} \;\; H_1: r = 1 \qquad \text{y, si se rechaza,} \qquad H_0: r \leq 1 \;\; \text{frente a} \;\; H_1: r = 2\]

\(r = 0\) indica que no hay cointegración; \(r = 1\), que hay una relación de equilibrio; \(r = 2\), que ambas series serían estacionarias en niveles.

2.3 Sintaxis de implementación en R

Con la librería urca:

ca.jo(x, type = c("eigen", "trace"), ecdet = c("none", "const", "trend"),
      K = 2, spec = c("longrun", "transitory"), season = NULL, dumvar = NULL)
Argumento Descripción
x Matriz o data.frame con las series en niveles (aquí, los logaritmos). No se diferencian: el modelo ya incorpora las diferencias.
type Estadístico de la prueba: "eigen" (máximo valor propio, \(\lambda_{max}\)) o "trace" (traza).
ecdet Componente determinista dentro de la relación de cointegración: "none" (ninguno), "const" (constante) o "trend" (tendencia). Con "none" no se fuerza un intercepto en el vector de cointegración; el modelo conserva una constante libre en la ecuación de corto plazo, que recoge la deriva de las series.
K Número de rezagos del VAR en niveles. En el VECM corresponden a \(K-1\) diferencias rezagadas. Debe ser al menos 2.
spec Forma de escribir el VECM: "longrun" (el término \(\Pi\) entra con rezago \(t-K\)) o "transitory" (entra con rezago \(t-1\)). Son dos parametrizaciones del mismo modelo: el estadístico de la prueba es el mismo y solo cambian los coeficientes de corto plazo.
season Frecuencia para incluir dummies estacionales centradas (por ejemplo, 12 en datos mensuales).
dumvar Variables dummy exógenas (por ejemplo, un quiebre o un episodio atípico).

Elección de \(K\). Se suele seleccionar con los criterios de información del VAR en niveles (librería vars):

VARselect(y, lag.max = 8, type = "const")$selection

Estimación del VECM una vez elegido \(r\):

cajorls(johansen_test, r = 1)   # coeficientes de largo plazo (beta) y ajuste (alpha)

2.4 Estadístico de prueba

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

\(T\) es el número efectivo de observaciones y \(\hat\lambda_{r_0+1}\) es el valor propio estimado de orden \(r_0+1\): cuanto mayor es, más evidencia de cointegración. En la salida de summary(), la columna test trae el estadístico de cada fila, y la fila r = 0 es la primera por contrastar.

2.5 Criterio de decisión

Se compara cada estadístico con su valor crítico, empezando por la fila r = 0****:

Función Regla (nivel de significancia del 5%)
ca.jo() Se rechaza \(H_0\) si el estadístico test \(>\) valor crítico 5pct de su fila.

El procedimiento es secuencial: si se rechaza r = 0, se pasa a r <= 1; el rango \(r\) es el primer valor que no se rechaza. Si ya r = 0 no se rechaza, el procedimiento se detiene y se concluye que no hay cointegración.

En la salida de R: los valores críticos están en las columnas 10pct, 5pct y 1pct de cada fila. A diferencia de las pruebas de raíz unitaria, aquí el rechazo ocurre con valores mayores que el crítico.

2.6 Interpretación del rechazo o no rechazo de la hipótesis nula

Resultado Interpretación
No se rechaza \(r = 0\) No hay evidencia de cointegración: no hay relación de equilibrio de largo plazo. Se trabajaría con un VAR en primeras diferencias.
Se rechaza \(r = 0\) y no se rechaza \(r \leq 1\) Hay exactamente un vector de cointegración (\(r = 1\)): las series comparten una relación de equilibrio de largo plazo. Se estima el VECM con cajorls(..., r = 1).
Se rechaza \(r = 0\) y \(r \leq 1\) (con dos variables) El rango es completo: las series serían estacionarias en niveles, y habría que revisar las pruebas de raíz unitaria.

Si hay cointegración, los resultados del VECM se leen así:

  • Vector \(\beta\) (largo plazo). Normalizado con la primera variable en 1, da la relación de equilibrio entre las series en logaritmos. El coeficiente es una elasticidad de largo plazo.
  • Coeficientes \(\alpha\) (ajuste). El coeficiente del término de corrección de error (ect1) mide qué parte del desequilibrio del mes anterior se corrige en cada ecuación. Un \(\alpha\) no significativo sugiere que esa variable no se ajusta al desequilibrio.

Dos precauciones: la cointegración indica una relación estadística de equilibrio, no causalidad; y el resultado puede depender de \(K\) y del componente determinista elegidos, por lo que conviene comprobar su robustez.

2.7 Implementación de un ejemplo

Habiendo comprobado que tanto la serie de Préstamos como la de Depósitos en logaritmos son integradas de orden 1, I(1), procedemos a evaluar si existe una relación de equilibrio de largo plazo mediante el procedimiento de Johansen y a estimar el Modelo de Corrección de Errores (VEC) correspondiente, siguiendo los lineamientos metodológicos de la bibliografía asignada (Chung, 2016).

Hipótesis (máximo valor propio):

\[H_0: r = 0 \;\; \text{frente a} \;\; H_1: r = 1; \qquad H_0: r \leq 1 \;\; \text{frente a} \;\; H_1: r = 2\]

Criterio de decisión: se rechaza \(H_0\) si el estadístico test es mayor que el valor crítico al 5%.

Código de Implementación en R

library(urca)
library(vars)

# 1. Series en niveles (logaritmos), en un solo objeto
datos_ejemplo <- cbind(log_prestamos, log_depositos)
colnames(datos_ejemplo) <- c("log_prestamos", "log_depositos")

# 2. Selección de rezagos del VAR en niveles
VARselect(datos_ejemplo, lag.max = 8, type = "const")$selection
## AIC(n)  HQ(n)  SC(n) FPE(n) 
##      1      1      1      1
# 3. Prueba de Johansen (máximo valor propio)
# type = "eigen": estadístico lambda max
# spec = "transitory": VECM con el término de largo plazo en t-1
# ecdet = "none": sin constante ni tendencia dentro del vector de cointegración
# K = 2: dos rezagos en el VAR en niveles (una diferencia rezagada)
johansen_test <- ca.jo(datos_ejemplo,
                       type = "eigen",
                       spec = "transitory",
                       ecdet = "none",
                       K = 2)
summary(johansen_test)
## 
## ###################### 
## # Johansen-Procedure # 
## ###################### 
## 
## Test type: maximal eigenvalue statistic (lambda max) , with linear trend 
## 
## Eigenvalues (lambda):
## [1] 0.08642861 0.00287735
## 
## Values of teststatistic and critical values of test:
## 
##           test 10pct  5pct  1pct
## r <= 1 |  0.55  6.50  8.18 11.65
## r = 0  | 17.17 12.91 14.90 19.19
## 
## Eigenvectors, normalised to first column:
## (These are the cointegration relations)
## 
##                  log_prestamos.l1 log_depositos.l1
## log_prestamos.l1        1.0000000         1.000000
## log_depositos.l1       -0.6441204        -1.074015
## 
## Weights W:
## (This is the loading matrix)
## 
##                 log_prestamos.l1 log_depositos.l1
## log_prestamos.d      0.004994236     -0.003666559
## log_depositos.d      0.028784749      0.003316645
# 4. Estimación del VECM con r = 1
modelo_vecm <- cajorls(johansen_test, r = 1)
modelo_vecm$beta
##                        ect1
## log_prestamos.l1  1.0000000
## log_depositos.l1 -0.6441204
summary(modelo_vecm$rlm)
## Response log_prestamos.d :
## 
## Call:
## lm(formula = log_prestamos.d ~ ect1 + constant + log_prestamos.dl1 + 
##     log_depositos.dl1 - 1, data = data.mat)
## 
## Residuals:
##        Min         1Q     Median         3Q        Max 
## -0.0113335 -0.0025997 -0.0002199  0.0022145  0.0128031 
## 
## Coefficients:
##                    Estimate Std. Error t value Pr(>|t|)  
## ect1               0.004994   0.003419   1.461   0.1457  
## constant          -0.013026   0.011433  -1.139   0.2560  
## log_prestamos.dl1  0.158821   0.071835   2.211   0.0283 *
## log_depositos.dl1  0.006433   0.032917   0.195   0.8453  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.004341 on 186 degrees of freedom
## Multiple R-squared:  0.5391, Adjusted R-squared:  0.5292 
## F-statistic: 54.39 on 4 and 186 DF,  p-value: < 2.2e-16
## 
## 
## Response log_depositos.d :
## 
## Call:
## lm(formula = log_depositos.d ~ ect1 + constant + log_prestamos.dl1 + 
##     log_depositos.dl1 - 1, data = data.mat)
## 
## Residuals:
##       Min        1Q    Median        3Q       Max 
## -0.024606 -0.005749 -0.000290  0.005942  0.031861 
## 
## Coefficients:
##                    Estimate Std. Error t value Pr(>|t|)    
## ect1               0.028785   0.007449   3.864 0.000154 ***
## constant          -0.090939   0.024912  -3.650 0.000340 ***
## log_prestamos.dl1 -0.240145   0.156528  -1.534 0.126680    
## log_depositos.dl1 -0.075038   0.071725  -1.046 0.296831    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.009459 on 186 degrees of freedom
## Multiple R-squared:  0.2492, Adjusted R-squared:  0.2331 
## F-statistic: 15.43 on 4 and 186 DF,  p-value: 6.411e-11

Criterio de decisión y resultado

  • Paso 1 (\(H_0: r = 0\)). El estadístico es \(17.17\) y el valor crítico al 5% es \(14.9\) (al 1%, \(19.19\)). Como es mayor, se rechaza \(H_0\) al 5%, aunque no al 1%.
  • Paso 2 (\(H_0: r \leq 1\)). El estadístico es \(0.55\), menor que el valor crítico al 5% (\(8.18\)). No se rechaza \(H_0\).
  • Conclusión de la prueba. Existe una relación de cointegración (\(r = 1\)) entre préstamos y depósitos.

Estimación y análisis del modelo VEC

1. Relación de largo plazo. El vector normalizado \(\beta\) da la ecuación de equilibrio:

\[\ln(\text{Préstamos}_t) - 0.644\,\ln(\text{Depósitos}_t) = 0\]

Es decir, a largo plazo un aumento de 1% en los depósitos del sector privado se asocia con un aumento de aproximadamente 0.64% en los préstamos. Como el coeficiente es menor que 1, los préstamos crecen menos que proporcionalmente respecto a los depósitos en el largo plazo.

2. Mecanismo de ajuste. Los coeficientes del término de corrección de error (ect1) son:

Ecuación \(\alpha\) Estadístico \(t\) Valor p
Préstamos 0.005 1.46 0.146
Depósitos 0.0288 3.86 < 0.001

El término ect1 es positivo cuando los préstamos están por encima de su equilibrio respecto a los depósitos. En la ecuación de depósitos, \(\alpha\) es positivo y significativo: ante ese desequilibrio, los depósitos suben para restablecer el equilibrio. En la ecuación de préstamos, \(\alpha\) es cercano a cero y no es significativo: los préstamos no responden de forma significativa al desequilibrio. El ajuste recae entonces principalmente sobre los depósitos.

Robustez

El resultado depende de \(K\), por lo que se repite la prueba con otros rezagos y con dummies estacionales mensuales:

res <- t(sapply(2:8, function(k) {
  j <- ca.jo(datos_ejemplo, type = "eigen", spec = "transitory", ecdet = "none", K = k)
  c(K = k, `r=0` = j@teststat[2], `r<=1` = j@teststat[1])
}))
res_est <- t(sapply(2:4, function(k) {
  j <- ca.jo(datos_ejemplo, type = "eigen", spec = "transitory", ecdet = "none",
             K = k, season = 12)
  c(K = k, `r=0` = j@teststat[2], `r<=1` = j@teststat[1])
}))
knitr::kable(round(res, 2), caption = "Estadístico lambda max por K (valores críticos al 5%: 14,90 para r = 0 y 8,18 para r <= 1)")
Estadístico lambda max por K (valores críticos al 5%: 14,90 para r = 0 y 8,18 para r <= 1)
K r=0 r<=1
2 17.17 0.55
3 19.48 0.70
4 20.72 1.18
5 16.50 1.01
6 20.03 1.19
7 23.91 0.94
8 16.35 1.16
knitr::kable(round(res_est, 2), caption = "Con dummies estacionales mensuales (season = 12)")
Con dummies estacionales mensuales (season = 12)
K r=0 r<=1
2 20.22 0.50
3 18.61 0.79
4 21.80 1.26

La conclusión de \(r = 1\) se mantiene para los rezagos probados hasta \(K = 8\) y con dummies estacionales; el estadístico de \(r = 0\) deja de superar el valor crítico cuando \(K\) es muy grande (por ejemplo, \(K = 13\)). Por eso se reporta \(K = 2\), el mínimo que admite ca.jo(), con su robustez.

3. Causalidad en el sentido de Granger

3.1 Propósito de la prueba,¿Para qué se usa?

La prueba de causalidad de Granger sirve para examinar si una serie de tiempo puede utilizarse para pronosticar otra (finnstats, 2021). Parte de un principio básico: el pasado y el presente pueden causar el futuro, pero el futuro no puede causar el pasado. Por eso, una variable \(X\) causa en el sentido de Granger a una variable \(Y\) cuando el valor de \(X_t\) ayuda a predecir \(Y_{t+1}\) (Kuersteiner, 2010, p. 119).

La predictibilidad, por sí sola, solo indica dependencia estadística entre variables. Lo que permite interpretarla como una relación causal es el orden temporal impuesto: la correlación es simétrica y no indica dirección, mientras que la flecha del tiempo sí la indica (Kuersteiner, 2010, p. 119).

La prueba se utiliza para:

  • Establecer la dirección de la relación predictiva entre variables: de \(X\) hacia \(Y\), de \(Y\) hacia \(X\), en ambas direcciones (retroalimentación) o en ninguna.
  • Contrastar, con datos observados, relaciones de precedencia temporal en contextos donde no es posible realizar experimentos(Kuersteiner, 2010, p. 132).

3.2 Hipotesis de la prueba

Las hipótesis son:

La hipótesis nula: representa la ausencia de causalidad;los rezagos de \(X\) no aportan información sobre \(Y\) una vez que ya se consideran los rezagos de \(Y\). Es el modelo más simple (restringido) y se mantiene mientras los datos no den evidencia en contra. Es la traducción a parámetros de la definición de no causalidad: agregar el pasado de \(X\) no cambia la distribución (ni la varianza de predicción) de \(Y_{t+1}\) (Kuersteiner, 2010, p. 119).

\[H_0: \beta_1 = \beta_2 = \cdots = \beta_p = 0 \qquad \text{($X$ no causa a $Y$ en el sentido de Granger)}\]

La hipótesis alternativa: es conjunta, basta con que un coeficiente \(\beta_j\) sea distinto de cero para que el pasado de \(X\) mejore la predicción de \(Y\).

\[H_1: \exists \, j \in \{1,\dots,p\} \;\text{tal que}\; \beta_j \neq 0 \qquad \text{($X$ causa a $Y$ en el sentido de Granger)}\]

3.3 Sintaxis de implementación en R

La prueba de Granger se implementa en R con dos funciones: grangertest() del paquete lmtest, que compara directamente el modelo restringido y el no restringido, y causality() del paquete vars, que se aplica sobre un modelo VAR ya estimado. Antes, el número de rezagos \(p\) se elige con VARselect().

# 1. Elegir el número de rezagos p
VARselect(y, lag.max = 12, type = "const")

# 2. Prueba de Granger con lmtest
grangertest(y ~ x, order = p, data = datos)

# 3. Prueba de Granger con vars
modelo <- VAR(y, p = p, type = "const")
causality(modelo, cause = "x")

Argumentos de grangertest() (paquete lmtest)

Argumento Qué indica En el ejemplo
formula Se escribe y ~ x: y es la variable que se quiere predecir y x la supuesta causa. La prueba evalúa si x causa a y dlog_prestamos ~ dlog_depositos
order Número de rezagos \(p\) que se incluyen de ambas variables (por defecto 1) order = p
data Data frame que contiene las variables de la fórmula dd_df
na.action Qué hacer con valores faltantes (por defecto los omite) no se modifica

Argumentos de causality() (paquete vars)

Argumento Qué indica En el ejemplo
x Modelo VAR ya estimado con VAR() mod
cause Nombre de la variable que se prueba como causa. Si no se indica, toma la primera "dlog_depositos"
vcov., boot, boot.runs Opcionales: matriz de covarianzas alternativa y valor \(p\) por bootstrap. Por defecto no se usan no se usan

Argumentos de VARselect() y VAR() (paquete vars)

Argumento Qué indica En el ejemplo
y Las series a analizar, en una matriz o serie de tiempo múltiple dd
lag.max Máximo de rezagos que VARselect() evalúa con los criterios AIC, HQ, SC y FPE 12
type Términos determinísticos: "const" incluye un intercepto "const"
p Número de rezagos del VAR p

Cómo leer la salida. En grangertest(), el Model 1 es el modelo no restringido (rezagos de \(Y\) y de \(X\)) y el Model 2 el restringido (solo rezagos de \(Y\)). El estadístico \(F\) y el valor \(p\) (Pr(>F)) aparecen en la segunda fila, y Res.Df del Modelo 1 corresponde a \(n-k\) de la sección 3.4. En causality(), el resultado $Granger entrega directamente F-Test, df1, df2 y p-value. Esta función calcula los grados de libertad del denominador sobre todo el sistema, por lo que su valor \(p\) puede diferir levemente del de grangertest() aunque el estadístico \(F\) sea el mismo.

3.4 Estadístico de la prueba

La prueba de Granger se basa en un estadístico \(F\) que compara dos regresiones estimadas con la misma muestra (finnstats, 2021). Una de ellas es la regresión restringida, que impone \(H_0\), y la otra es la no restringida (o completa), que no la impone.

Modelo restringido (bajo \(H_0\): los rezagos de \(X\) no explican a \(Y\)), que solo incluye los rezagos de \(Y\).

Modelo no restringido (completo), que incluye además los rezagos de \(X\).

El estadístico se construye con la suma de cuadrados de los residuos (SSR, por sus siglas en inglés) de cada modelo:

\[F = \frac{\left(SSR_{r} - SSR_{nr}\right)/q}{SSR_{nr}/\left(n - k\right)}\]

donde:

Símbolo Significado En la prueba de Granger
\(SSR_{r}\) Suma de cuadrados residuales del modelo restringido Modelo solo con rezagos de \(Y\)
\(SSR_{nr}\) Suma de cuadrados residuales del modelo no restringido Modelo con rezagos de \(Y\) y de \(X\)
\(q\) Número de restricciones impuestas por \(H_0\) \(q = p\) (los coeficientes \(\beta_1,\dots,\beta_p\))
\(n\) Número de observaciones efectivas de la regresión Se pierden \(p\) observaciones por los rezagos
\(k\) Número de parámetros del modelo no restringido \(k = 2p + 1\) (constante, \(p\) rezagos de \(Y\) y \(p\) de \(X\))
\(n-k\) Grados de libertad residuales del modelo no restringido \(n - 2p - 1\)

3.5 Criterio de decisión

Se fija un nivel de significancia \(\alpha\) (por ejemplo, \(\alpha = 0.05\)) y se decide de cualquiera de estas dos formas equivalentes:

a) Mediante el valor \(p\):

\[\text{Se rechaza } H_0 \iff p\text{-valor} < \alpha\]

b) Mediante el valor crítico:

\[\text{Se rechaza } H_0 \iff F_{\text{calculado}} > F_{\alpha;\, p,\, T-2p-1}\]

Se rechaza la hipótesis nula, y se infiere que \(X\) causa a \(Y\) en el sentido de Granger, cuando el valor \(p\) es menor que el nivel de significancia elegido (finnstats, 2021). En caso contrario, no se rechaza \(H_0\).

3.6 Interpretación del rechazo/no rechazo

Se rechaza \(H_0\) (\(p\)-valor \(< \alpha\)): los rezagos de \(X\) mejoran la predicción de \(Y\). Se concluye que \(X\) causa a \(Y\) en el sentido de Granger: conocer los valores pasados de \(X\) es útil para pronosticar los valores futuros de \(Y\) (finnstats, 2021).

No se rechaza \(H_0\) (\(p\)-valor \(\geq \alpha\)): no hay evidencia suficiente de que el pasado de \(X\) aporte información predictiva sobre \(Y\). Se concluye que \(X\) no causa a \(Y\) en el sentido de Granger, lo cual no equivale a afirmar que no exista ninguna relación entre las variables.

3.7 Implementación de un ejemplo

Se aplica la prueba de causalidad de Granger a los préstamos y a los depósitos del sector privado (datos mensuales, 2010-2025) para ver si existe precedencia temporal entre ambas variables, en las dos direcciones que plantea la introducción: de los depósitos a los préstamos (intermediación) y de los préstamos a los depósitos (dinero endógeno).

Variables. En la sección 1 se verificó que los logaritmos de ambas series pueden tratarse como \(I(1)\) (los préstamos con cautela, pues el resultado depende del número de rezagos) y que sus primeras diferencias son estacionarias. Por eso la prueba se aplica a las diferencias del logaritmo, log_prestamos y log_depositos, que equivalen aproximadamente a la tasa de crecimiento mensual de cada variable.

Hipótesis. Se prueban dos direcciones:

  • \(H_0\): los depósitos no causan a los préstamos en el sentido de Granger, contra \(H_1\): sí los causan.
  • \(H_0\): los préstamos no causan a los depósitos en el sentido de Granger, contra \(H_1\): sí los causan.

Criterio de decisión. Se rechaza \(H_0\) si el valor \(p\) es menor que \(\alpha = 0.05\) (equivalentemente, si \(F_{calculado} > F_{crítico}\)).

Carga de librerías

library(lmtest)
library(vars)
library(knitr)

Gráfico de las series transformadas

dlog_prestamos <- diff(log_prestamos)
dlog_depositos <- diff(log_depositos)
dd <- cbind(dlog_depositos, dlog_prestamos)

plot(dd, main = "Crecimiento mensual de depósitos y préstamos (2010-2025)")

Al transformar las series en tasas de crecimiento mensual (diferencia del logaritmo), desaparece la tendencia creciente que mostraban los niveles en la sección 1. Ambas series oscilan alrededor de una tasa positiva (en promedio, \(0.47\%\) mensual en depósitos y \(0.45\%\) en préstamos), lo que es coherente con la estacionariedad que indicó la prueba de Dickey-Fuller. Los depósitos presentan variaciones mensuales más amplias que los préstamos (desviación estándar de \(0.97\%\) frente a \(0.45\%\)), y su crecimiento promedio aumenta hacia el final del periodo (de \(0.17\%\) mensual en 2010-2013 a \(0.86\%\) en 2024-2025). Los préstamos se desaceleran en 2020, con varias tasas negativas en la segunda mitad del año (la más baja, de \(-0.6\%\) en agosto).

Elegir número de rezagos

dd  <- cbind(dlog_depositos, dlog_prestamos)
sel <- VARselect(dd, lag.max = 12, type = "const")
sel$selection
## AIC(n)  HQ(n)  SC(n) FPE(n) 
##      1      1      1      1
p <- unname(sel$selection["SC(n)"])   # criterio de Schwarz (BIC)
p
## [1] 1

Los criterios AIC, HQ, SC y FPE coinciden en \(p = 1\), por lo que se estima el modelo con un rezago. Con \(n = 190\) observaciones efectivas, el modelo no restringido tiene 187 grados de libertad residuales.

La prueba de Granger en dos direcciones

dd_df <- as.data.frame(dd)

# H0: los depósitos NO causan (Granger) a los préstamos
g_dep_pre <- grangertest(dlog_prestamos ~ dlog_depositos, order = p, data = dd_df)
g_dep_pre
## Granger causality test
## 
## Model 1: dlog_prestamos ~ Lags(dlog_prestamos, 1:1) + Lags(dlog_depositos, 1:1)
## Model 2: dlog_prestamos ~ Lags(dlog_prestamos, 1:1)
##   Res.Df Df      F Pr(>F)
## 1    187                 
## 2    188 -1 0.2236 0.6368
# H0: los préstamos NO causan (Granger) a los depósitos
g_pre_dep <- grangertest(dlog_depositos ~ dlog_prestamos, order = p, data = dd_df)
g_pre_dep
## Granger causality test
## 
## Model 1: dlog_depositos ~ Lags(dlog_depositos, 1:1) + Lags(dlog_prestamos, 1:1)
## Model 2: dlog_depositos ~ Lags(dlog_depositos, 1:1)
##   Res.Df Df      F Pr(>F)
## 1    187                 
## 2    188 -1 0.4385 0.5087

Otra forma de implementarlo

mod <- VAR(dd, p = p, type = "const")
causality(mod, cause = "dlog_depositos")$Granger
## 
##  Granger causality H0: dlog_depositos do not Granger-cause
##  dlog_prestamos
## 
## data:  VAR object mod
## F-Test = 0.22363, df1 = 1, df2 = 374, p-value = 0.6366
causality(mod, cause = "dlog_prestamos")$Granger
## 
##  Granger causality H0: dlog_prestamos do not Granger-cause
##  dlog_depositos
## 
## data:  VAR object mod
## F-Test = 0.43847, df1 = 1, df2 = 374, p-value = 0.5083

Tabla resumen con valor crítico

tab_g <- data.frame(
  Direccion   = c("Depósitos → Préstamos", "Préstamos → Depósitos"),
  Rezagos     = p,
  F_calculado = c(g_dep_pre$F[2], g_pre_dep$F[2]),
  F_critico   = c(qf(0.95, p, g_dep_pre$Res.Df[1]),
                  qf(0.95, p, g_pre_dep$Res.Df[1])),
  Valor_p     = c(g_dep_pre$`Pr(>F)`[2], g_pre_dep$`Pr(>F)`[2])
)
tab_g$Decision <- ifelse(tab_g$Valor_p < 0.05,
                         "Se rechaza H0: hay evidencia de causalidad",
                         "No se rechaza H0: no hay evidencia de causalidad")
kable(tab_g, digits = 4)
Direccion Rezagos F_calculado F_critico Valor_p Decision
Depósitos → Préstamos 1 0.2236 3.8917 0.6368 No se rechaza H0: no hay evidencia de causalidad
Préstamos → Depósitos 1 0.4385 3.8917 0.5087 No se rechaza H0: no hay evidencia de causalidad

Resultados. En la dirección Depósitos → Préstamos, el estadístico es \(F = 0.2236\) (valor crítico \(3.8917\)) con un valor \(p\) de \(0.6368\). En la dirección Préstamos → Depósitos, es \(F = 0.4385\) con un valor \(p\) de \(0.5087\). En ambos casos \(F < F_{crítico}\) y \(p > 0.05\), por lo que no se rechaza \(H_0\). Las dos implementaciones (lmtest y vars) llevan a la misma conclusión. El estadístico \(F\) es el mismo; el valor p cambia en el tercer decimal porque causality() usa 374 grados de libertad residuales (las dos ecuaciones del VAR) y grangertest() usa 187.

Interpretación. Con un rezago mensual, el crecimiento pasado de los depósitos no ayuda a predecir el de los préstamos, y tampoco ocurre lo contrario. Sin embargo, este resultado depende del número de rezagos: con \(p = 1\), \(2\) y \(3\) no se rechaza \(H_0\) en ninguna dirección, pero con \(p = 4\) a \(7\) se rechaza en la dirección depósitos → préstamos (valores p entre \(0.0035\) y \(0.0287\)), mientras que préstamos → depósitos no se rechaza; con \(p = 8\) se rechaza en ambas direcciones. Esto apunta a que los depósitos anticipan a los préstamos, aunque solo con rezagos más largos que los que sugieren los criterios de información.

Una explicación posible del resultado con \(p = 1\) es que depósitos y préstamos se ajusten de forma simultánea dentro del mismo mes. Otra es que su relación sea de largo plazo y se pierda al trabajar con diferencias: la prueba de Johansen (sección 2.7) encontró una relación de cointegración, y en el modelo VEC el término de corrección de error es significativo en la ecuación de depósitos y no en la de préstamos, es decir, en el largo plazo los depósitos responden a los desequilibrios respecto a los préstamos. La evidencia es, por tanto, mixta. Esto no implica independencia entre las variables.

Limitaciones. El resultado depende del número de rezagos, de la ventana de datos (por ejemplo, un cambio de régimen como la pandemia puede distorsionar la relación) y de que la prueba se hace en diferencias, sin el término de corrección de error que surge de la cointegración. Además, la causalidad de Granger mide precedencia predictiva, no causalidad estructural.

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.

MacKinnon, J. G. (1994). Approximate asymptotic distribution functions for unit-root and cointegration tests. Journal of Business & Economic Statistics, 12, 167-176.

Lecturas consultadas: Montero, R. (2013), Variables no estacionarias y cointegración; Catalán, H., Teoría de cointegración (CEPAL); Wikipedia, Prueba de Dickey-Fuller.

Documentación de los paquetes urca y tseries de R. finnstats. (2021, noviembre). Granger causality test in R (with example). R-bloggers. https://www.r-bloggers.com/2021/11/granger-causality-test-in-r-with-example/

Kuersteiner, G. M. (2010). Granger–Sims causality. En S. N. Durlauf y L. E. Blume (Eds.), Macroeconometrics and time series analysis (pp. 119-134). Palgrave Macmillan. (Obra original publicada en 2008)