Paquetes y funciones auxiliares. Todo el código usa
datos incluidos en los paquetes o guardados en la carpeta
datos/, de modo que el documento se puede compilar sin
conexión a internet.
library(urca) # ur.df(), ca.jo()
library(tseries) # adf.test()
library(lmtest) # grangertest()
library(vars) # VARselect()
library(readxl) # lectura del archivo de Bitcoin
# Número máximo de rezagos sugerido por Montero (2013, p. 5)
regla_montero <- function(N) floor(4 * (N / 100)^(2 / 9))
# Resumen de una prueba ur.df(): rezagos usados, estadístico tau, valor crítico y decisión al 5 %
resumen_adf <- function(prueba, serie, espec) {
tau <- prueba@teststat[1, 1] # el primer valor es el estadístico tau
critico <- prueba@cval[1, "5pct"] # fila tau1, tau2 o tau3, según la especificación
rezagos <- sum(grepl("z.diff.lag", rownames(prueba@testreg$coefficients)))
data.frame(Serie = serie, Especificacion = espec, Rezagos = rezagos,
Tau = round(tau, 3), Critico_5 = critico,
Decision_5 = ifelse(tau < critico, "Se rechaza H0", "No se rechaza H0"))
}
Una serie de tiempo es un conjunto de observaciones de una variable recogidas en orden a lo largo del tiempo, con una frecuencia diaria, mensual, trimestral o anual. La mayoría de las series económicas, como el PIB, los precios o los agregados monetarios, no son estacionarias, y eso condiciona la forma de analizarlas.
Una serie \(\{x_t\}\) es estacionaria en sentido débil cuando su media, su varianza y sus autocovarianzas no dependen del momento en que se observa (Montero, 2013, pp. 3-4):
\[ \mathbb{E}(x_t) = \mu \;\; \forall t, \qquad \operatorname{Var}(x_t) = \sigma^2 < \infty \;\; \forall t, \qquad \operatorname{Cov}(x_t, x_{t-k}) = \gamma_k \;\; \forall t, \forall k . \]
Una serie estacionaria fluctúa alrededor de una media constante, con una amplitud más o menos estable. En la práctica se reconoce primero en el gráfico: una serie con tendencia, cambios de nivel o varianza creciente no es estacionaria, y su función de autocorrelación decae lentamente, mientras que la de una serie estacionaria cae a cero con rapidez (Hyndman y Athanasopoulos, 2021, sec. 9.1).
Una serie es integrada de orden \(d\), \(I(d)\), si hay que diferenciarla \(d\) veces para volverla estacionaria: \(I(0)\) denota una serie estacionaria e \(I(1)\) una serie con una raíz unitaria (Montero, 2013, pp. 3-4). Las variables macroeconómicas suelen ser \(I(1)\) (Real Academia Sueca de Ciencias, 2003, pp. 5-6).
Cuando se regresan entre sí dos series no estacionarias, la regresión puede mostrar coeficientes significativos y un \(R^2\) alto aunque no exista ninguna relación entre ellas. En palabras de Montero (2013), “las estimaciones de regresiones con variables no estacionarias son espurias salvo que estas estén cointegradas” (p. 1). Granger y Newbold (1974, p. 115) lo mostraron por simulación: al regresar entre sí dos paseos aleatorios independientes, la hipótesis de “no relación” se rechazaba en alrededor de tres de cada cuatro casos.
Diferenciar las series evita el problema, pero descarta los niveles, que es donde suele formularse la teoría económica (Real Academia Sueca de Ciencias, 2003, pp. 4-5). La cointegración permite trabajar en niveles sin caer en una regresión espuria.
Los tres temas del informe se aplican en secuencia:
Montero (2013, pp. 3-4) resume qué hacer según el orden de integración de las series:
| Caso | Qué hacer |
|---|---|
| Todas las series son \(I(0)\) | Estimar de la forma habitual (MCO) |
| Series no estacionarias de distinto orden | No se puede estimar la relación entre ellas |
| Series del mismo orden, no cointegradas | Regresión espuria: transformar las series o estimar en primeras diferencias |
| Series no estacionarias y cointegradas | Relación de largo plazo en niveles más un modelo de corrección de errores para el corto plazo |
| Sección | Serie | Frecuencia y muestra | Fuente |
|---|---|---|---|
| 2 | Precio de cierre del Bitcoin (USD) | Mensual, 2015:1 a 2025:12 | Archivo datos/Bitcoin_data.xlsx, pendiente
fuente. |
| 3 | PIB per cápita de El Salvador (USD constantes de 2015), en logaritmos | Anual, 1965 a 2025 | Banco Mundial (2026), indicador NY.GDP.PCAP.KD,
guardado en datos/pib_pc_slv.csv |
| 4 y 5 | Dinero real (M2), ingreso real, tasa de bonos y tasa de depósitos de Dinamarca | Trimestral, 1974:1 a 1987:3 | Datos denmark de Johansen y Juselius (1990, como se
citó en Pfaff, 2024a) |
| 6 | Población de gallinas y producción de huevos de EE. UU. | Anual, 1930 a 1983 | Datos ChickEgg de Thurman y Fisher (1988, como se citó
en Hothorn et al., 2022) |
La prueba de Dickey y Fuller (1979, como se citó en MacKinnon, 2010) sirve para determinar si una serie es estacionaria o si tiene una raíz unitaria. Es el primer paso antes de relacionar series entre sí: indica si una serie puede usarse en niveles o si debe diferenciarse, y da el orden de integración que necesitan las pruebas de cointegración y de causalidad.
Se parte de un proceso autorregresivo de primer orden:
\[ y_t = \rho\, y_{t-1} + \varepsilon_t, \qquad \varepsilon_t \sim \text{ruido blanco}. \]
Si \(|\rho| < 1\) el proceso es estacionario; si \(\rho = 1\) es un paseo aleatorio: el valor de hoy es el de ayer más un choque, y los choques nunca se desvanecen. Al restar \(y_{t-1}\) en ambos lados se obtiene la regresión de la prueba:
\[ \Delta y_t = \delta\, y_{t-1} + \varepsilon_t, \qquad \delta = \rho - 1 . \]
Las hipótesis son:
\[ H_0:\ \delta = 0 \;\; (\rho = 1) \qquad \text{la serie tiene raíz unitaria (no es estacionaria)} \]
\[ H_1:\ \delta < 0 \;\; (\rho < 1) \qquad \text{la serie es estacionaria} \]
La prueba es de cola izquierda: un valor \(\delta > 0\) correspondería a una serie explosiva, que no es la alternativa de interés.
Versión aumentada (ADF). Si los errores están autocorrelacionados, se agregan rezagos de \(\Delta y_t\) a la regresión. Con \(p\) rezagos, las tres especificaciones de la prueba son (Montero, 2013, pp. 4-5):
\[ \text{(1) sin constante ni tendencia:}\quad \Delta y_t = \delta\, y_{t-1} + \sum_{i=1}^{p} \gamma_i\, \Delta y_{t-i} + u_t \]
\[ \text{(2) con constante:}\quad \Delta y_t = a_0 + \delta\, y_{t-1} + \sum_{i=1}^{p} \gamma_i\, \Delta y_{t-i} + u_t \]
\[ \text{(3) con constante y tendencia:}\quad \Delta y_t = a_0 + a_1 t + \delta\, y_{t-1} + \sum_{i=1}^{p} \gamma_i\, \Delta y_{t-i} + u_t \]
El término \(\sum \gamma_i\, \Delta y_{t-i}\) corrige la autocorrelación de los errores (Montero, 2013, p. 5). El autor recomienda usar la versión con tendencia y elegir el número de rezagos con la regla
\[ p = \left\lfloor 4 \left( \frac{N}{100} \right)^{2/9} \right\rfloor , \]
que da entre 3 y 6 rezagos para muestras de 30 a 1000 observaciones (Montero, 2013, p. 5). En este informe la regla fija el número máximo de rezagos y el criterio de Akaike (AIC) elige cuántos usar.
urcaLa función ur.df() estima la regresión de Dickey-Fuller
y calcula el estadístico del coeficiente de \(y_{t-1}\):
ur.df(y, type = c("none", "drift", "trend"), lags = 1,
selectlags = c("Fixed", "AIC", "BIC"))
| Argumento | Descripción |
|---|---|
y |
Serie a la que se aplica la prueba (vector u objeto
ts). No admite valores faltantes. |
type |
Especificación: "none" es el modelo (1),
"drift" el modelo (2) y "trend" el modelo
(3). |
lags |
Número de rezagos de \(\Delta
y_t\). Con lags = 0 se obtiene la prueba de
Dickey-Fuller simple. |
selectlags |
"Fixed" usa exactamente lags rezagos;
"AIC" o "BIC" toman lags como
máximo y eligen con ese criterio de información. |
ur.df() no reporta un p-valor: el estadístico se compara
con valores críticos tabulados (Hamilton, 1994, y Dickey y Fuller, 1981,
como se citó en Pfaff, 2024a), que se reproducen en la tabla de valores críticos de la sección
siguiente.
tseriesadf.test(x, alternative = c("stationary", "explosive"),
k = trunc((length(x) - 1)^(1/3)))
| Argumento | Descripción |
|---|---|
x |
Serie a la que se aplica la prueba (vector u objeto
ts). |
alternative |
Hipótesis alternativa: "stationary" (por defecto, cola
izquierda) o "explosive" (\(\rho
> 1\)). |
k |
Número de rezagos de \(\Delta
y_t\). Con k = 0 se obtiene la prueba de
Dickey-Fuller simple. |
Esta función siempre incluye constante y tendencia (modelo 3) y, a
diferencia de ur.df(), reporta un p-valor (Trapletti y
Hornik, 2026).
Para mostrar cómo cambia la prueba según el argumento
type, se usa el precio de cierre mensual del Bitcoin, de
enero de 2015 a diciembre de 2025.
bitcoin <- read_excel("datos/Bitcoin_data.xlsx", sheet = "DATOS")
btc <- ts(bitcoin$Price, start = c(2015, 1), frequency = 12)
plot(btc, main = "Precio de cierre mensual del Bitcoin", xlab = "Año", ylab = "USD")
La serie crece con fuerza y tiene episodios de alzas y caídas que no
regresan a un nivel fijo. Se aplica la prueba de Dickey-Fuller simple
(lags = 0) con las tres especificaciones:
tabla_btc <- rbind(
resumen_adf(ur.df(btc, type = "none", lags = 0), "Bitcoin", "Sin constante ni tendencia"),
resumen_adf(ur.df(btc, type = "drift", lags = 0), "Bitcoin", "Con constante"),
resumen_adf(ur.df(btc, type = "trend", lags = 0), "Bitcoin", "Con constante y tendencia"))
tabla_btc
| Serie | Especificacion | Rezagos | Tau | Critico_5 | Decision_5 |
|---|---|---|---|---|---|
| Bitcoin | Sin constante ni tendencia | 0 | 0.586 | -1.95 | No se rechaza H0 |
| Bitcoin | Con constante | 0 | -0.365 | -2.88 | No se rechaza H0 |
| Bitcoin | Con constante y tendencia | 0 | -2.039 | -3.43 | No se rechaza H0 |
En las tres especificaciones el estadístico es mayor que el valor crítico al 5 % (0.586 frente a -1.95, -0.365 frente a -2.88 y -2.039 frente a -3.43), así que en ningún caso se rechaza la hipótesis nula: no hay evidencia contra la raíz unitaria en el precio del Bitcoin.
Con tseries se obtiene el mismo estadístico del modelo
con constante y tendencia, ahora con un p-valor:
adf_btc <- adf.test(btc, k = 0)
print(adf_btc, digits = 6)
##
## Augmented Dickey-Fuller Test
##
## data: btc
## Dickey-Fuller = -2.039, Lag order = 0, p-value = 0.56
## alternative hypothesis: stationary
El p-valor, 0.5603, es mayor que 0.05, así que tampoco se rechaza la raíz unitaria.
La prueba usa el estadístico \(\tau\), que es el cociente \(t\) del coeficiente de \(y_{t-1}\):
\[ \tau = \frac{\hat{\delta}}{\operatorname{EE}(\hat{\delta})} . \]
Aunque se calcula como un estadístico \(t\), no sigue la distribución \(t\) de Student, ni en muestras finitas ni asintóticamente, y sus valores críticos se obtienen por simulación (MacKinnon, 2010, p. 2). Esos valores críticos son más negativos que los habituales: en el modelo con constante, el valor crítico asintótico al 5 % es −2.862 (MacKinnon, 2010, p. 9), mientras que el de la normal estándar sería −1.645. Usar la \(t\) llevaría a rechazar la raíz unitaria con demasiada frecuencia.
Cómo identificarlo en la salida de R. En
summary(ur.df(...)) hay que ubicar la línea
Value of test-statistic is:.
t value de la fila z.lag.1 en la tabla de
coeficientes, porque z.lag.1 es \(y_{t-1}\).phi1, phi2,
phi3) son estadísticos \(F\) sobre la constante y la tendencia; no
son el estadístico principal de la prueba.type |
Fila con la que se compara \(\tau\) |
|---|---|
"none" |
tau1 |
"drift" |
tau2 |
"trend" |
tau3 |
La columna Pr(>|t|) de la tabla de coeficientes
no es el p-valor de la prueba, porque usa la
distribución \(t\), que no es válida
bajo \(H_0\).
Los valores críticos de \(\tau\) dependen de la especificación de la regresión y del tamaño de la muestra. Gujarati y Porter (2010, tabla D.7) los resumen al 1 % y al 5 %:
| Tamaño de la muestra | \(\tau_{nc}\) 1 % | \(\tau_{nc}\) 5 % | \(\tau_{c}\) 1 % | \(\tau_{c}\) 5 % | \(\tau_{ct}\) 1 % | \(\tau_{ct}\) 5 % | \(F^{\dagger}\) 1 % | \(F^{\dagger}\) 5 % | \(F^{\ddagger}\) 1 % | \(F^{\ddagger}\) 5 % |
|---|---|---|---|---|---|---|---|---|---|---|
| 25 | −2.66 | −1.95 | −3.75 | −3.00 | −4.38 | −3.60 | 10.61 | 7.24 | 8.21 | 5.68 |
| 50 | −2.62 | −1.95 | −3.58 | −2.93 | −4.15 | −3.50 | 9.31 | 6.73 | 7.02 | 5.13 |
| 100 | −2.60 | −1.95 | −3.51 | −2.89 | −4.04 | −3.45 | 8.73 | 6.49 | 6.50 | 4.88 |
| 250 | −2.58 | −1.95 | −3.46 | −2.88 | −3.99 | −3.43 | 8.43 | 6.34 | 6.22 | 4.75 |
| 500 | −2.58 | −1.95 | −3.44 | −2.87 | −3.98 | −3.42 | 8.34 | 6.30 | 6.15 | 4.71 |
| \(\infty\) | −2.58 | −1.95 | −3.43 | −2.86 | −3.96 | −3.41 | 8.27 | 6.25 | 6.09 | 4.68 |
Nota. Tomado de Gujarati y Porter (2010, tabla D.7).
Cómo se usa la tabla:
type = "none", fila tau1 de
ur.df()); \(c\), con
constante ("drift", tau2); y \(ct\), con constante y tendencia
("trend", tau3). Cuantos más términos
determinísticos tiene la regresión, más negativo es el valor crítico:
con 100 observaciones y al 5 %, pasa de −1.95 a −2.89 y a −3.45.ur.df()
usa estos mismos valores y, cuando el tamaño de la muestra no aparece en
la tabla, toma la fila del tamaño inmediatamente superior: con el
Bitcoin (132 observaciones) usa la fila 250 y con el PIB de El Salvador
(61 observaciones), la fila 100.ur.df() corresponden a
phi3 y phi2. Este informe solo usa las
columnas de \(\tau\).La prueba es de cola izquierda, así que se rechaza con valores muy negativos de \(\tau\):
\[ \text{se rechaza } H_0 \iff \tau < \tau_{\text{crítico}}, \qquad \text{no se rechaza } H_0 \iff \tau \geq \tau_{\text{crítico}} . \]
El nivel de referencia habitual es el 5 %. Con
adf.test(), que da un p-valor, la regla equivalente es
rechazar \(H_0\) si \(p < 0.05\) (Montero, 2013, pp. 4-5).
No rechazar \(H_0\) no demuestra que exista una raíz unitaria, solo que los datos no dan evidencia suficiente en contra. Por eso conviene complementar la prueba con la KPSS, cuya hipótesis nula es la contraria: que la serie es estacionaria (Kwiatkowski et al., 1992, como se citó en Hyndman y Athanasopoulos, 2021). También hay que tener cuidado con los cambios estructurales: si una serie es estacionaria alrededor de una tendencia con un quiebre, las pruebas habituales tienden a no rechazar la raíz unitaria (Perron, 1989, como se citó en Montero, 2013).
Se usa el PIB per cápita real de El Salvador, en dólares constantes
de 2015 y con frecuencia anual, en logaritmos. Los datos se descargaron
del Banco Mundial con el paquete wbstats y se guardaron en
datos/pib_pc_slv.csv para que los resultados no cambien si
el banco revisa la serie:
library(wbstats)
datos <- wb_data(indicator = "NY.GDP.PCAP.KD", country = "SLV",
start_date = 1965, end_date = 2025)
Paso 1: gráfico y correlograma. Montero (2013, p. 4) recomienda empezar por el gráfico de la serie y su correlograma.
pib_datos <- read.csv("datos/pib_pc_slv.csv")
pib <- ts(log(pib_datos$pib_pc_usd2015), start = min(pib_datos$anio), frequency = 1)
N_pib <- length(pib)
op <- par(mfrow = c(1, 2), mar = c(4, 4, 3, 1))
plot(pib, main = "log del PIB per cápita", xlab = "Año", ylab = "")
acf(pib, main = "Correlograma (niveles)")
par(op)
El logaritmo del PIB per cápita sube hasta finales de los setenta, cae con fuerza durante los ochenta, se recupera desde 1990 y tiene una caída puntual en 2020. No hay una media estable a la que regrese, y el correlograma decae lentamente, que es el patrón de una serie no estacionaria (Hyndman y Athanasopoulos, 2021, sec. 9.1).
Paso 2: prueba ADF en niveles. Con \(N = 61\) observaciones, la regla de Montero da un máximo de 3 rezagos. Se usa el modelo con constante y tendencia:
p_pib <- regla_montero(N_pib)
adf_pib_niv <- ur.df(pib, type = "trend", lags = p_pib, selectlags = "AIC")
summary(adf_pib_niv)
##
## ###############################################
## # Augmented Dickey-Fuller Test Unit Root Test #
## ###############################################
##
## Test regression trend
##
##
## Call:
## lm(formula = z.diff ~ z.lag.1 + 1 + tt + z.diff.lag)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.15372 -0.00863 0.00157 0.01517 0.12407
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.342070 0.277569 1.23 0.223
## z.lag.1 -0.044833 0.035579 -1.26 0.213
## tt 0.000755 0.000405 1.86 0.068 .
## z.diff.lag 0.352269 0.129852 2.71 0.009 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.0375 on 53 degrees of freedom
## Multiple R-squared: 0.187, Adjusted R-squared: 0.141
## F-statistic: 4.06 on 3 and 53 DF, p-value: 0.0114
##
##
## Value of test-statistic is: -1.26 1.615 1.742
##
## 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
Lectura de la salida:
z.diff.lag de la
tabla de coeficientes.Value of test-statistic: \(\tau =
-1.26\), igual al t value de
z.lag.1.tau3 son -4.04 (1 %), -3.45 (5
%) y -3.15 (10 %). Como \(-1.26 >
-3.45\), no se rechaza \(H_0\): la serie en niveles tiene raíz
unitaria.Paso 3: prueba ADF en primeras diferencias. La primera diferencia del logaritmo es, aproximadamente, la tasa de crecimiento del PIB per cápita. Ya no tiene tendencia, así que se usa el modelo con constante:
adf_pib_dif <- ur.df(diff(pib), type = "drift", lags = p_pib, selectlags = "AIC")
tabla_pib <- rbind(res_niv, resumen_adf(adf_pib_dif, "Δlog(PIB pc)", "Diferencias, con constante"))
tabla_pib
| Serie | Especificacion | Rezagos | Tau | Critico_5 | Decision_5 |
|---|---|---|---|---|---|
| log(PIB pc) | Niveles, con tendencia | 1 | -1.260 | -3.45 | No se rechaza H0 |
| Δlog(PIB pc) | Diferencias, con constante | 1 | -3.489 | -2.89 | Se rechaza H0 |
En primeras diferencias, \(\tau = -3.489\) es menor que el valor crítico al 5 % (-2.89), así que se rechaza \(H_0\): la tasa de crecimiento es estacionaria.
Conclusión del ejemplo. El logaritmo del PIB per cápita de El Salvador es integrado de orden uno, \(I(1)\): no es estacionario en niveles y se vuelve estacionario al diferenciarlo una vez. Esta conclusión trata la caída de finales de los setenta como parte del proceso; si se tratara como un cambio estructural, la conclusión podría cambiar, que es la limitación señalada por Perron (1989, como se citó en Montero, 2013).
La prueba de Johansen sirve para determinar cuántas relaciones de equilibrio de largo plazo (vectores de cointegración) existen entre un conjunto de variables \(I(1)\). Aunque cada serie sea no estacionaria, puede existir una combinación lineal \(\beta' X_t\) que sí sea estacionaria: las variables se mueven juntas en el largo plazo y las desviaciones del equilibrio son transitorias.
El método de Engle y Granger (1987, como se citó en Real Academia Sueca de Ciencias, 2003) estima por MCO una relación de largo plazo y aplica una prueba de raíz unitaria a los residuos (Real Academia Sueca de Ciencias, 2003, pp. 7-8). Johansen, en cambio, trabaja con el sistema completo y estima por máxima verosimilitud todas las relaciones a la vez (Real Academia Sueca de Ciencias, 2003, p. 8):
| Engle-Granger | Johansen | |
|---|---|---|
| Marco | Una ecuación (residuos de MCO) | VAR de todas las variables |
| Número de relaciones | Solo una | Hasta \(n-1\); se estima cuántas hay |
| Variable dependiente | Hay que elegirla | No hace falta |
Sea \(X_t\) un vector de \(n\) variables \(I(1)\). Un VAR en niveles se puede reescribir como un modelo de corrección de errores vectorial (VECM) (Johansen, 2014, p. 5):
\[ \Delta X_t = \Pi X_{t-1} + \sum_{i=1}^{K-1} \Gamma_i\, \Delta X_{t-i} + \mu + \varepsilon_t . \]
\(\Delta X_t\) y los términos en diferencias son estacionarios; para que la ecuación sea coherente, \(\Pi X_{t-1}\) también tiene que serlo. Eso depende del rango de la matriz \(\Pi\), \(r = \operatorname{rango}(\Pi)\) (Johansen, 1988, p. 5):
| Rango de \(\Pi\) | Interpretación |
|---|---|
| \(r = 0\) | No hay cointegración; corresponde un VAR en primeras diferencias. |
| \(0 < r < n\) | Hay \(r\) relaciones de cointegración y \(\Pi = \alpha\beta'\). |
| \(r = n\) | Todas las variables son estacionarias en niveles. |
Cuando hay cointegración, \(\Pi = \alpha\beta'\), donde \(\alpha\) y \(\beta\) son matrices de \(n \times r\) (Johansen, 2014, pp. 4-5):
Johansen estima el modelo por máxima verosimilitud y obtiene unos valores propios \(\hat\lambda_1 > \hat\lambda_2 > \dots > \hat\lambda_n\), entre 0 y 1; el número de valores propios significativamente distintos de cero es el rango de \(\Pi\) (Johansen, 1988, pp. 7-9).
Antes de aplicar la prueba hay que comprobar que ninguna serie sea \(I(2)\) (Johansen, 2014, p. 7) y decidir qué términos determinísticos (constante, tendencia) se incluyen, porque esa elección cambia los valores críticos (Johansen, 1991).
Johansen (1991) propone dos estadísticos, que contrastan hipótesis distintas sobre \(r\):
Prueba de la traza (para \(r_0 = 0, 1, \dots, n-1\)):
\[ H_0:\ \operatorname{rango}(\Pi) \leq r_0 \qquad \text{frente a} \qquad H_1:\ \operatorname{rango}(\Pi) > r_0 \]
Prueba del máximo valor propio:
\[ H_0:\ \operatorname{rango}(\Pi) = r_0 \qquad \text{frente a} \qquad H_1:\ \operatorname{rango}(\Pi) = r_0 + 1 \]
Se parte de \(r_0 = 0\) (no hay cointegración), igual que en Dickey-Fuller la nula es la raíz unitaria: es el supuesto que debe refutarse con evidencia. El procedimiento es secuencial:
La prueba se hace con ca.jo() del paquete
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, data.frame u objeto ts con las
\(n\) variables \(I(1)\) en columnas. |
type |
"trace": prueba de la traza; "eigen":
prueba del máximo valor propio. |
ecdet |
Término determinístico dentro de la relación de
cointegración: "none", "const" o
"trend". |
K |
Número de rezagos del VAR en niveles. Debe ser \(K \geq 2\). |
spec |
Forma del VECM: "longrun" o "transitory".
Las dos dan la misma inferencia sobre \(\Pi\). |
season |
Frecuencia de los datos (4 trimestral, 12
mensual) para incluir dummies estacionales; NULL no las
incluye. |
Los valores críticos que reporta ca.jo() provienen de
Osterwald-Lenum (1992, como se citó en Pfaff, 2024a).
Para elegir el número de rezagos \(K\) se usa VARselect() del
paquete vars (Pfaff, 2024b), que estima el VAR en niveles
con 1 a lag.max rezagos y reporta el rezago que minimiza
cada criterio de información:
VARselect(y, lag.max = 10, type = c("const", "trend", "both", "none"), season = NULL)
Con \(T\) observaciones y los valores propios ordenados \(\hat\lambda_1 > \dots > \hat\lambda_n\):
Estadístico de la traza (Johansen, 1988, p. 10):
\[ \lambda_{\text{traza}}(r_0) = -T \sum_{i = r_0 + 1}^{n} \ln\left(1 - \hat\lambda_i\right) \]
Estadístico del máximo valor propio (Johansen, 1991):
\[ \lambda_{\max}(r_0) = -T \ln\left(1 - \hat\lambda_{r_0 + 1}\right) \]
Si los valores propios que según \(H_0\) deberían ser cero lo son realmente, los estadísticos son pequeños; un estadístico grande indica que hay más cointegración de la que supone \(H_0\). Ninguno de los dos sigue una distribución \(\chi^2\): sus valores críticos se obtienen por simulación (Johansen, 1988, p. 12) y dependen de \(n - r\) y de los términos determinísticos (Johansen, 2014, pp. 12-13).
Dónde están en la salida de R. En
summary(ca.jo(...)):
Eigenvalues (lambda): los \(\hat\lambda_i\).Values of teststatistic and critical values of test:
una fila por cada hipótesis nula. La columna test es el
estadístico y las columnas 10pct, 5pct y
1pct son los valores críticos.Eigenvectors, normalised to first column: los vectores
de cointegración \(\hat\beta\), uno por
columna.Weights W: la matriz de ajuste \(\hat\alpha\).La tabla se lee de abajo hacia arriba, empezando por la fila \(r = 0\):
test es mayor que el valor crítico al 5 %,
se rechaza \(H_0\) y
se pasa a la fila de arriba.test es menor que el valor crítico (no se
rechaza \(H_0\)); el \(r\) de esa fila es el número estimado de
vectores de cointegración.Antes de interpretar el rango conviene revisar que los residuos del modelo no tengan autocorrelación (Johansen, 2014, p. 10).
Se usan los datos denmark de urca: series
trimestrales de 1974:1 a 1987:3 (55 observaciones) con las que Johansen
y Juselius (1990, como se citó en Pfaff, 2024a) estimaron una función de
demanda de dinero para Dinamarca. Las variables son LRM
(logaritmo del dinero real, M2), LRY (logaritmo del ingreso
real), IBO (tasa de los bonos) e IDE (tasa de
los depósitos bancarios).
data(denmark)
dk <- ts(denmark[, c("LRM", "LRY", "IBO", "IDE")], start = c(1974, 1), frequency = 4)
plot(dk, main = "Datos denmark (1974:1-1987:3)", xlab = "Año")
Paso 1: orden de integración. Se aplica la prueba ADF a cada serie, en niveles con tendencia y en diferencias con constante:
p_dk <- regla_montero(nrow(dk))
do.call(rbind, lapply(colnames(dk), function(v) rbind(
resumen_adf(ur.df(dk[, v], type = "trend", lags = p_dk, selectlags = "AIC"), v, "Niveles, con tendencia"),
resumen_adf(ur.df(diff(dk[, v]), type = "drift", lags = p_dk, selectlags = "AIC"), v, "Diferencias, con constante"))))
| Serie | Especificacion | Rezagos | Tau | Critico_5 | Decision_5 |
|---|---|---|---|---|---|
| LRM | Niveles, con tendencia | 2 | -1.704 | -3.45 | No se rechaza H0 |
| LRM | Diferencias, con constante | 1 | -2.984 | -2.89 | Se rechaza H0 |
| LRY | Niveles, con tendencia | 1 | -2.339 | -3.45 | No se rechaza H0 |
| LRY | Diferencias, con constante | 1 | -4.814 | -2.89 | Se rechaza H0 |
| IBO | Niveles, con tendencia | 1 | -2.013 | -3.45 | No se rechaza H0 |
| IBO | Diferencias, con constante | 1 | -4.379 | -2.89 | Se rechaza H0 |
| IDE | Niveles, con tendencia | 1 | -2.419 | -3.45 | No se rechaza H0 |
| IDE | Diferencias, con constante | 1 | -4.708 | -2.89 | Se rechaza H0 |
En niveles ninguna serie rechaza la raíz unitaria, y en diferencias las cuatro la rechazan al 5 %. Las cuatro series son \(I(1)\) y ninguna es \(I(2)\), como exige la prueba.
Paso 2: número de rezagos. Los datos son
trimestrales, así que se incluyen dummies estacionales, como en el
ejemplo de la documentación de ca.jo() (Pfaff, 2024a):
VARselect(dk, lag.max = 5, type = "const", season = 4)$selection
## AIC(n) HQ(n) SC(n) FPE(n)
## 2 1 1 2
El AIC y el FPE eligen 2 rezagos, y el HQ y el SC eligen 1. Como
ca.jo() exige \(K \geq
2\), se usa \(K = 2\).
Paso 3: prueba del máximo valor propio. Se sigue la
especificación de la documentación del paquete: constante dentro de la
relación de cointegración (ecdet = "const") y dummies
estacionales.
jo_eigen <- ca.jo(dk, type = "eigen", ecdet = "const", K = 2, spec = "longrun", season = 4)
summary(jo_eigen)
##
## ######################
## # Johansen-Procedure #
## ######################
##
## Test type: maximal eigenvalue statistic (lambda max) , without linear trend and constant in cointegration
##
## Eigenvalues (lambda):
## [1] 4.332e-01 1.776e-01 1.128e-01 4.341e-02 6.668e-16
##
## Values of teststatistic and critical values of test:
##
## test 10pct 5pct 1pct
## r <= 3 | 2.35 7.52 9.24 12.97
## r <= 2 | 6.34 13.75 15.67 20.20
## r <= 1 | 10.36 19.77 22.00 26.81
## r = 0 | 30.09 25.56 28.14 33.24
##
## Eigenvectors, normalised to first column:
## (These are the cointegration relations)
##
## LRM.l2 LRY.l2 IBO.l2 IDE.l2 constant
## LRM.l2 1.000 1.000 1.0000 1.000 1.0000
## LRY.l2 -1.033 -1.368 -3.2267 -1.884 -0.6337
## IBO.l2 5.207 0.243 0.5383 24.399 1.6966
## IDE.l2 -4.216 6.841 -5.6474 -14.298 -1.8952
## constant -6.060 -4.271 7.8964 -2.263 -8.0330
##
## Weights W:
## (This is the loading matrix)
##
## LRM.l2 LRY.l2 IBO.l2 IDE.l2 constant
## LRM.d -0.21295 -0.004815 0.035011 2.029e-03 2.000e-13
## LRY.d 0.11502 0.019750 0.049938 1.109e-03 -2.480e-13
## IBO.d 0.02318 -0.010596 0.003480 -1.574e-03 -1.733e-14
## IDE.d 0.02941 -0.030229 -0.002812 -4.768e-05 9.676e-15
Paso 4: prueba de la traza. Con la misma especificación, solo se muestra la tabla de la prueba:
jo_traza <- ca.jo(dk, type = "trace", ecdet = "const", K = 2, spec = "longrun", season = 4)
cbind(test = round(jo_traza@teststat, 2), jo_traza@cval)
## test 10pct 5pct 1pct
## r <= 3 | 2.35 7.52 9.24 12.97
## r <= 2 | 8.69 17.85 19.96 24.60
## r <= 1 | 19.06 32.00 34.91 41.07
## r = 0 | 49.14 49.65 53.12 60.16
Lectura de las dos tablas, de abajo hacia arriba:
Las dos pruebas no coinciden. Puede pasar porque contrastan alternativas distintas: el máximo valor propio se concentra en el primer valor propio, que aquí es claramente el más grande (0.433 frente a 0.178 del segundo), mientras que la traza lo suma con los demás, que son pequeños. Además, con pocas observaciones los resultados deben leerse con cautela (Johansen, 2014, p. 13).
Paso 5: el vector de cointegración. Con \(r = 1\) interesa la primera columna de los
vectores propios, normalizada con LRM igual a 1:
beta1 <- jo_eigen@V[, 1] / jo_eigen@V[1, 1]
round(beta1, 3)
## LRM.l2 LRY.l2 IBO.l2 IDE.l2 constant
## 1.000 -1.033 5.207 -4.216 -6.060
Como \(\hat\beta' X_t\) es estacionario, la relación de largo plazo es
\[ LRM_t -1.033\, LRY_t +5.207\, IBO_t -4.216\, IDE_t -6.060 = u_t, \qquad u_t \sim I(0), \]
y, al despejar el dinero real,
\[ LRM_t \approx 1.033\, LRY_t -5.207\, IBO_t +4.216\, IDE_t +6.060 . \]
Tiene la forma de una función de demanda de dinero: la elasticidad
ingreso de largo plazo es cercana a 1 (1.03), la tasa de los bonos
(costo de oportunidad de mantener dinero) reduce la demanda y la tasa de
los depósitos (rendimiento propio de M2) la aumenta. En la matriz
Weights W, el coeficiente de ajuste de LRM es
negativo (-0.213): cuando el dinero real está por encima de su nivel de
equilibrio, tiende a bajar en el trimestre siguiente.
Conclusión del ejemplo. Hay evidencia de una relación de largo plazo entre dinero, ingreso y tasas de interés en Dinamarca, sostenida por la prueba del máximo valor propio al 5 %, con la traza en el límite. Por eso el resultado debe reportarse con esa reserva.
La noción proviene de Granger (1969, como se citó en Hecq et al., 2023), quien propuso definiciones de causalidad que se pueden comprobar con datos. Según el propio autor, la causa ocurre antes que el efecto y contiene información única sobre él, de modo que ayuda a pronosticarlo aun después de usar toda la demás información (Granger, 2004, sec. “Causalidad”).
Se dice que \(x\) causa en el sentido de Granger a \(y\) si los valores pasados de \(x\) ayudan a predecir \(y\), además de lo que ya predicen los valores pasados de \(y\). Es un concepto de predictibilidad, no de causalidad en sentido fuerte: Granger la llamó “causalidad de Granger” para distinguirla de la causalidad verdadera (Granger, 2004, sec. “Causalidad”). Además, el resultado depende de las variables incluidas: si se omiten variables relacionadas, la causalidad encontrada puede ser un artefacto (Hecq et al., 2023, sec. 1).
Para probar si \(x\) causa a \(y\) se estima una regresión de \(y\) sobre sus propios rezagos y los de \(x\) (modelo no restringido):
\[ y_t = c + \sum_{i=1}^{p} a_i\, y_{t-i} + \sum_{i=1}^{p} b_i\, x_{t-i} + u_t . \]
Las hipótesis son:
\[ H_0:\ b_1 = b_2 = \dots = b_p = 0 \qquad (x \text{ no causa a } y \text{ en el sentido de Granger}) \]
\[ H_1:\ b_i \neq 0 \text{ para al menos un } i \qquad (x \text{ causa a } y \text{ en el sentido de Granger}) \]
Bajo \(H_0\) el modelo se reduce al modelo restringido, que solo tiene rezagos de \(y\):
\[ y_t = c + \sum_{i=1}^{p} a_i\, y_{t-i} + u_t . \]
Las \(p\) restricciones se prueban de forma conjunta con una prueba \(F\) (Stock y Watson, 2001, pp. 104-105). Para saber si \(y\) causa a \(x\) se intercambian los papeles: los dos sentidos se prueban por separado.
Se usa la función grangertest() del paquete
lmtest:
grangertest(formula, data = list(), order = 1) # método con fórmula
grangertest(x, y, order = 1) # método por defecto
| Argumento | Descripción |
|---|---|
formula |
Se escribe y ~ x y responde a la pregunta
“¿x causa a y?”: a la izquierda va la variable
que se quiere predecir y a la derecha la posible causa. |
x, y |
En el método por defecto, las dos series; se prueba si
x causa a y. |
order |
Número \(p\) de rezagos, que se aplica a las dos variables. |
data |
data.frame u objeto ts con las
variables. |
La función compara el modelo no restringido con el restringido mediante una prueba de Wald, y solo admite series bivariadas (Hothorn et al., 2022).
El estadístico es una \(F\) para las \(p\) restricciones:
\[ F = \frac{\left(SCR_R - SCR_{NR}\right)/p}{SCR_{NR}/(n - 2p - 1)} \;\sim\; F_{(p,\ n - 2p - 1)} \quad \text{bajo } H_0 , \]
donde \(SCR_R\) y \(SCR_{NR}\) son las sumas de cuadrados de los residuos de los modelos restringido y no restringido, y \(n\) es el número de observaciones usadas. Si el pasado de \(x\) no aporta nada, las dos sumas son parecidas y \(F\) es pequeño.
En la salida de grangertest(), Model 1 es
el no restringido y Model 2 el restringido; la columna
F es el estadístico y Pr(>F) su
p-valor.
Con un nivel de significancia del 5 %:
Pr(>F) \(<
0.05\), se rechaza \(H_0\).Pr(>F) \(\geq
0.05\), no se rechaza \(H_0\).Cuidado con la no estacionariedad. Con series \(I(1)\) o cointegradas, la prueba no tiene la distribución habitual (Hecq et al., 2023, sec. 2.1). Por eso primero se determina el orden de integración de las series:
| Caso | Cómo se prueba la causalidad |
|---|---|
| Todas las series \(I(0)\) | Regresión en niveles y prueba \(F\) |
| Series \(I(1)\) no cointegradas | Regresión en primeras diferencias |
| Series \(I(1)\) cointegradas | VECM; la causalidad también pasa por el término de corrección de errores |
| Orden de integración dudoso | Procedimiento de Toda y Yamamoto (1995, como se citó en Hecq et al., 2023), con rezagos adicionales |
Se usan los datos ChickEgg de lmtest:
población de gallinas y producción de huevos de Estados Unidos (en
millones de docenas), anual, de 1930 a 1983.
data(ChickEgg)
ce <- ts(ChickEgg, start = 1930)
plot(ce, main = "ChickEgg: gallinas y huevos en Estados Unidos, 1930-1983", xlab = "Año")
Paso 1: orden de integración.
p_ce <- regla_montero(nrow(ce))
do.call(rbind, lapply(colnames(ce), function(v) rbind(
resumen_adf(ur.df(ce[, v], type = "trend", lags = p_ce, selectlags = "AIC"), v, "Niveles, con tendencia"),
resumen_adf(ur.df(diff(ce[, v]), type = "drift", lags = p_ce, selectlags = "AIC"), v, "Diferencias, con constante"))))
| Serie | Especificacion | Rezagos | Tau | Critico_5 | Decision_5 |
|---|---|---|---|---|---|
| chicken | Niveles, con tendencia | 2 | -2.515 | -3.45 | No se rechaza H0 |
| chicken | Diferencias, con constante | 1 | -4.255 | -2.89 | Se rechaza H0 |
| egg | Niveles, con tendencia | 1 | -1.837 | -3.45 | No se rechaza H0 |
| egg | Diferencias, con constante | 1 | -4.096 | -2.89 | Se rechaza H0 |
Las dos series tienen raíz unitaria en niveles y son estacionarias en diferencias: son \(I(1)\). Por eso la prueba se aplica sobre las primeras diferencias.
Paso 2: la prueba de Granger en las dos direcciones, con 3 rezagos, como en el ejemplo de la documentación del paquete (Hothorn et al., 2022):
dce <- diff(ce)
# ¿Las gallinas causan (en el sentido de Granger) a los huevos?
g_gallinas_huevos <- grangertest(egg ~ chicken, order = 3, data = dce)
g_gallinas_huevos
| Res.Df | Df | F | Pr(>F) |
|---|---|---|---|
| 43 | NA | NA | NA |
| 46 | -3 | 0.2245 | 0.8788 |
# ¿Los huevos causan (en el sentido de Granger) a las gallinas?
g_huevos_gallinas <- grangertest(chicken ~ egg, order = 3, data = dce)
g_huevos_gallinas
| Res.Df | Df | F | Pr(>F) |
|---|---|---|---|
| 43 | NA | NA | NA |
| 46 | -3 | 2.932 | 0.0441 |
egg ~ chicken, \(F =
0.225\) y Pr(>F) \(=
0.879\). Como el p-valor es mayor que 0.05, no se
rechaza \(H_0\): no hay
evidencia de que las gallinas ayuden a predecir los huevos.chicken ~ egg, \(F =
2.932\) y Pr(>F) \(=
0.044\). Es menor que 0.05, así que se rechaza
\(H_0\): los huevos ayudan a predecir a
las gallinas.Paso 3: sensibilidad al número de rezagos.
do.call(rbind, lapply(1:4, function(o) data.frame(
Rezagos = o,
p_gallinas_causan_huevos = round(grangertest(egg ~ chicken, order = o, data = dce)[2, "Pr(>F)"], 4),
p_huevos_causan_gallinas = round(grangertest(chicken ~ egg, order = o, data = dce)[2, "Pr(>F)"], 4))))
| Rezagos | p_gallinas_causan_huevos | p_huevos_causan_gallinas |
|---|---|---|
| 1 | 0.4646 | 0.0023 |
| 2 | 0.6816 | 0.0268 |
| 3 | 0.8788 | 0.0441 |
| 4 | 0.8881 | 0.0064 |
Con 1 a 4 rezagos, el p-valor de “las gallinas causan a los huevos” es alto y el de “los huevos causan a las gallinas” es menor que 0.05: la conclusión no depende del número de rezagos.
Conclusión del ejemplo. La causalidad en el sentido de Granger va de los huevos a las gallinas y no al revés: el pasado de la producción de huevos ayuda a predecir la población de gallinas, pero no a la inversa. En ese sentido predictivo, “el huevo fue primero”. Como se trata de predictibilidad, el resultado no dice nada sobre mecanismos biológicos o económicos.
ur.df() o
adf.test(). El precio del Bitcoin y el PIB per cápita de El
Salvador tienen raíz unitaria en niveles, y el PIB es \(I(1)\).ca.jo().
En los datos de Dinamarca, el máximo valor propio indica una relación de
cointegración con la forma de una demanda de dinero, aunque la traza
queda en el límite.grangertest().
En el ejemplo, la producción de huevos ayuda a predecir la población de
gallinas y no al revés. Es causalidad predictiva, no estructural.Banco Mundial. (2026). PIB per cápita (US$ a precios constantes de 2015) [Indicador NY.GDP.PCAP.KD]. World Development Indicators. Consultado el 7 de noviembre de 2026. https://data.worldbank.org/indicator/NY.GDP.PCAP.KD
Granger, C. W. J. (2004). Time series analysis, cointegration, and applications. En T. Frängsmyr (Ed.), Les Prix Nobel. The Nobel Prizes 2003. Nobel Foundation. https://escholarship.org/uc/item/2nb9f668
Granger, C. W. J., & Newbold, P. (1974). Spurious regressions in econometrics. Journal of Econometrics, 2(2), 111-120. https://doi.org/10.1016/0304-4076(74)90034-7
Gujarati, D. N., & Porter, D. C. (2010). Econometría (5.ª ed.). McGraw-Hill.
Hecq, A., Margaritella, L., & Smeekes, S. (2023). Inference in non-stationary high-dimensional VARs (arXiv:2302.01434v2). arXiv. https://arxiv.org/abs/2302.01434
Hothorn, T., Zeileis, A., Farebrother, R. W., & Cummins, C. (2022). lmtest: Testing linear regression models (Versión 0.9-40) [Paquete de R]. https://CRAN.R-project.org/package=lmtest
Hyndman, R. J., & Athanasopoulos, G. (2021). Forecasting: Principles and practice (3.ª ed.). OTexts. https://otexts.com/fpp3/
Johansen, S. (1988). Statistical analysis of cointegration vectors. Journal of Economic Dynamics and Control, 12(2-3), 231-254. https://doi.org/10.1016/0165-1889(88)90041-3 (Se consultó el preprint de 1987 de la Universidad de Copenhague; las páginas citadas corresponden a esa versión).
Johansen, S. (1991). Estimation and hypothesis testing of cointegration vectors in Gaussian vector autoregressive models. Econometrica, 59(6), 1551-1580. https://doi.org/10.2307/2938278 (Se consultó el preprint de 1989 de la Universidad de Copenhague).
Johansen, S. (2014). Times series: Cointegration (Discussion Paper No. 14-24). Department of Economics, University of Copenhagen. https://www.economics.ku.dk/research/publications/wp/dp_2014/1424.pdf
MacKinnon, J. G. (2010). Critical values for cointegration tests (Queen’s Economics Department Working Paper No. 1227). Queen’s University. https://doi.org/10.22004/ag.econ.273723
Montero, R. (2013). Variables no estacionarias y cointegración (Documentos de Trabajo en Economía Aplicada). Universidad de Granada.
Pfaff, B. (2024a). urca: Unit root and cointegration tests for time series data (Versión 1.3-4) [Paquete de R]. https://CRAN.R-project.org/package=urca
Pfaff, B. (2024b). vars: VAR modelling (Versión 1.6-1) [Paquete de R]. https://CRAN.R-project.org/package=vars
Real Academia Sueca de Ciencias. (2003). Time-series econometrics: Cointegration and autoregressive conditional heteroskedasticity [Información avanzada sobre el Premio de Ciencias Económicas 2003]. https://www.nobelprize.org/prizes/economic-sciences/2003/advanced-information/
Stock, J. H., & Watson, M. W. (2001). Vector autoregressions. Journal of Economic Perspectives, 15(4), 101-115. https://doi.org/10.1257/jep.15.4.101
Trapletti, A., & Hornik, K. (2026). tseries: Time series analysis and computational finance (Versión 0.10-63) [Paquete de R]. https://CRAN.R-project.org/package=tseries
## R 4.6.1 | urca 1.3.4 | vars 1.6.1 | lmtest 0.9.40 | tseries 0.10.63