Prueba de Raíz Unitaria de Dickey & Fuller
Propósito de la prueba
La prueba de Dickey-Fuller se utiliza para determinar si una serie
temporal tiene una raíz unitaria, es decir, si es no estacionaria \((I(1))\). Esto es fundamental porque muchas
técnicas econométricas requieren series estacionarias para evitar
regresiones espurias.
Hipótesis de la prueba
\(H_0:\,\phi = 1\) La serie tiene
raíz unitaria, no estacionaria
\(H_1:\,\phi < 1\) La serie es
estacionaria
Fundamento
Bajo \(H_0\), la serie sigue un
camino aleatorio, mientras que bajo \(H_1\), la serie es estacionaria y revertirá
a su media.
Sintaxis en R
knitr::include_graphics("1.jpeg")

Argumentos:
y: Serie temporal a analizar
type: Especificación del modelo
“none”: Sin intercepto ni tendencia
“drift”: Con intercepto
“trend”: Con intercepto y tendencia
lags: Número de rezagos para corregir
autocorrelación
selectlags: Criterio para selección automática
de rezagos
Estadístico de prueba
R genera el estadístico tau2 (para modelo con drift)
o tau3 (para modelo con trend), que sigue una
distribución Dickey-Fuller.
Criterio de decisión
En la salida, se comparan:
Test statistic vs Critical values
Si p-value < 0.05 → Se rechaza \(H_0\)
• Interpretación Rechazo \(H_0\): La
serie es estacionaria (\(I(0)\))
No rechazo \(H_0\): La serie tiene
raíz unitaria (\(I(1)\))
Ejemplo implementado
library(urca)
library(tseries)
# Generar datos ejemplo
set.seed(123)
serie_estacionaria <- arima.sim(model = list(ar = 0.7), n = 100)
serie_no_estacionaria <- cumsum(rnorm(100))
# Prueba ADF
adf_est <- ur.df(serie_estacionaria, type = "drift", lags = 1)
adf_noest <- ur.df(serie_no_estacionaria, type = "drift", lags = 1)
# Resultados
cat("Serie Estacionaria:\n")
## Serie Estacionaria:
##
## ###############################################
## # Augmented Dickey-Fuller Test Unit Root Test #
## ###############################################
##
## Test regression drift
##
##
## Call:
## lm(formula = z.diff ~ z.lag.1 + 1 + z.diff.lag)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.36098 -0.58014 -0.05011 0.55372 2.18961
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.008277 0.089802 0.092 0.926755
## z.lag.1 -0.277166 0.076864 -3.606 0.000498 ***
## z.diff.lag -0.010036 0.102720 -0.098 0.922371
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.8885 on 95 degrees of freedom
## Multiple R-squared: 0.1398, Adjusted R-squared: 0.1217
## F-statistic: 7.718 on 2 and 95 DF, p-value: 0.0007835
##
##
## Value of test-statistic is: -3.6059 6.5017
##
## Critical values for test statistics:
## 1pct 5pct 10pct
## tau2 -3.51 -2.89 -2.58
## phi1 6.70 4.71 3.86
cat("\nSerie No Estacionaria:\n")
##
## Serie No Estacionaria:
print(summary(adf_noest))
##
## ###############################################
## # Augmented Dickey-Fuller Test Unit Root Test #
## ###############################################
##
## Test regression drift
##
##
## Call:
## lm(formula = z.diff ~ z.lag.1 + 1 + z.diff.lag)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.04241 -0.69310 -0.01889 0.48903 2.61021
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -0.48695 0.22178 -2.196 0.0306 *
## z.lag.1 -0.13819 0.05618 -2.460 0.0157 *
## z.diff.lag -0.07947 0.10200 -0.779 0.4378
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.9798 on 95 degrees of freedom
## Multiple R-squared: 0.08057, Adjusted R-squared: 0.06121
## F-statistic: 4.162 on 2 and 95 DF, p-value: 0.0185
##
##
## Value of test-statistic is: -2.4597 3.025
##
## Critical values for test statistics:
## 1pct 5pct 10pct
## tau2 -3.51 -2.89 -2.58
## phi1 6.70 4.71 3.86
Cointegración en el enfoque de Soren Johansen
Propósito de la prueba
La prueba de Johansen determina si existe una relación de
cointegración entre múltiples series \(I(1)\), es decir, si existe una combinación
lineal estacionaria entre ellas.
Hipótesis de la prueba
Para el test de la traza:
\(H_0:\, r = r_0\) Existen \(r_0\) relaciones de cointegración
\(H_1:\, r > r_0\) Existen más de
\(r_0\) relaciones
Para el test del valor propio máximo: \(H_0:\, r = r_0\)
\(H_0:\, r = r_0+1\)
Sintaxis en R
knitr::include_graphics("2.jpeg")

Argumentos:
x: Matriz o data frame con las series
type: Tipo de prueba (“trace” o
“eigen”)
ecdet: Especificación del término
determinístico
K: Número de rezagos en el VAR
spec: Especificación del modelo (“longrun” o
“transitory”)
Estadístico de prueba
R genera dos estadísticos principales:
Lambda trace: \(\lambda_{trace} = -T \sum_{i=r+1}^{n}
\ln(1-\hat{\lambda}_i)\)
Lambda max: \(\lambda_{max} = -T
\ln(1-\hat{\lambda}_{r+1})\)
Criterio de decisión
Se comparan los valores críticos con los estadísticos:
Interpretación
Rechazo \(H_0\) para \(r=0\): Existe al menos una
relación de cointegración
Número de relaciones: El mayor \(r\) para el que se rechaza \(H_0\)
Ejemplo implementado
library(vars)
library(urca)
# Crear series cointegradas
set.seed(123)
n <- 100
e1 <- rnorm(n)
e2 <- rnorm(n)
y1 <- cumsum(e1)
y2 <- 0.8*y1 + e2 # y2 cointegrada con y1
# Dataset
dataset <- cbind(y1, y2)
# Prueba de Johansen
johansen_result <- ca.jo(dataset,
type = "trace",
ecdet = "const",
K = 2)
# Resultados
summary(johansen_result)
##
## ######################
## # Johansen-Procedure #
## ######################
##
## Test type: trace statistic , without linear trend and constant in cointegration
##
## Eigenvalues (lambda):
## [1] 4.045959e-01 2.751562e-02 1.085857e-18
##
## Values of teststatistic and critical values of test:
##
## test 10pct 5pct 1pct
## r <= 1 | 2.73 7.52 9.24 12.97
## r = 0 | 53.55 17.85 19.96 24.60
##
## Eigenvectors, normalised to first column:
## (These are the cointegration relations)
##
## y1.l2 y2.l2 constant
## y1.l2 1.00000000 1.00000000 1.0000000
## y2.l2 -1.27768243 -0.03527282 -0.2260186
## constant -0.08823617 -4.16585709 0.0577765
##
## Weights W:
## (This is the loading matrix)
##
## y1.l2 y2.l2 constant
## y1.d -0.1046364 -0.05367779 -1.238878e-17
## y2.d 0.8863038 -0.04677276 1.459928e-16
# Estimación del VECM si hay cointegración
if(johansen_result@teststat[1] > johansen_result@cval[1, "5pct"]) {
vecm <- cajorls(johansen_result, r = 1)
summary(vecm$rlm)
}
Causalidad en el sentido de Granger
Propósito de la prueba
Determina si una variable \(X\)
contiene información útil para predecir otra variable \(Y\), más allá de la información pasada de
\(Y\) misma.
Hipótesis de la prueba
\(H_0:\; X \text{ no causa Granger a }
Y\)
\(H_1:\; X \text{ causa Granger a }
Y\)
Fundamento: Se prueba si los coeficientes de los
rezagos de \(X\) son conjuntamente
significativos en la ecuación de \(Y\).
Sintaxis en R
knitr::include_graphics("3.jpeg")

Estadístico de prueba
Estadístico F: Para pruebas basadas en
MCO
Estadístico Wald: \(\chi^2\) para sistemas VAR
p-value: Probabilidad asociada al
estadístico
Criterio de decisión
En la salida:
Si p-value < 0.05 → Se rechaza \(H_0\)
Granger causality H0: X do not Granger-cause Y
Ejemplo implementado
library(vars)
library(tseries)
library(dplyr)
# Generar datos con causalidad - VERSIÓN CORREGIDA
set.seed(123)
n <- 100
# Método 1: Usar arima.sim correctamente
X <- as.numeric(arima.sim(model = list(ar = 0.7), n = n))
# Crear Y con rezagos manualmente
Y <- numeric(n)
for(i in 3:n) {
Y[i] <- 0.5 * X[i-1] + 0.3 * X[i-2] + rnorm(1)
}
# Método alternativo simple
set.seed(123)
X_alt <- cumsum(rnorm(n)) # Serie no estacionaria
Y_alt <- numeric(n)
for(i in 3:n) {
Y_alt[i] <- 0.8 * X_alt[i-1] + 0.4 * X_alt[i-2] + rnorm(1)
}
# método alternativo
X <- X_alt
Y <- Y_alt
# Crear dataset
data_causality <- na.omit(cbind(Y, X))
colnames(data_causality) <- c("Y", "X")
# Verificar las series
cat("Primeras observaciones:\n")
## Primeras observaciones:
print(head(data_causality))
## Y X
## [1,] 0.0000000 -0.5604756
## [2,] 0.0000000 -0.7906531
## [3,] -1.5671193 0.7680552
## [4,] 0.5550666 0.8385636
## [5,] 0.7313810 0.9678513
## [6,] 0.7621639 2.6829163
# Prueba de causalidad de Granger
var_model <- VAR(data_causality, p = 2)
# Causalidad de X hacia Y
causality_XY <- causality(var_model, cause = "X")
cat("\n=== Causalidad de X hacia Y ===\n")
##
## === Causalidad de X hacia Y ===
## $Granger
##
## Granger causality H0: X do not Granger-cause Y
##
## data: VAR object var_model
## F-Test = 67.041, df1 = 2, df2 = 186, p-value < 2.2e-16
##
##
## $Instant
##
## H0: No instantaneous causality between: X and Y
##
## data: VAR object var_model
## Chi-squared = 1.5464, df = 1, p-value = 0.2137
# Causalidad de Y hacia X (para verificar bidireccionalidad)
causality_YX <- causality(var_model, cause = "Y")
cat("\n=== Causalidad de Y hacia X ===\n")
##
## === Causalidad de Y hacia X ===
## $Granger
##
## Granger causality H0: Y do not Granger-cause X
##
## data: VAR object var_model
## F-Test = 0.75282, df1 = 2, df2 = 186, p-value = 0.4725
##
##
## $Instant
##
## H0: No instantaneous causality between: Y and X
##
## data: VAR object var_model
## Chi-squared = 1.5464, df = 1, p-value = 0.2137
# Prueba manual con lm - VERSIÓN CORREGIDA
data_df <- as.data.frame(data_causality)
# Crear rezagos manualmente
data_df$Y_lag1 <- c(NA, data_df$Y[-nrow(data_df)])
data_df$Y_lag2 <- c(NA, NA, data_df$Y[-c(nrow(data_df)-1, nrow(data_df))])
data_df$X_lag1 <- c(NA, data_df$X[-nrow(data_df)])
data_df$X_lag2 <- c(NA, NA, data_df$X[-c(nrow(data_df)-1, nrow(data_df))])
# Eliminar NAs
data_df_clean <- na.omit(data_df)
cat("\n=== Prueba Manual con LM ===\n")
##
## === Prueba Manual con LM ===
model_completo <- lm(Y ~ Y_lag1 + Y_lag2 + X_lag1 + X_lag2,
data = data_df_clean)
model_restringido <- lm(Y ~ Y_lag1 + Y_lag2,
data = data_df_clean)
anova_test <- anova(model_restringido, model_completo)
print(anova_test)
## Analysis of Variance Table
##
## Model 1: Y ~ Y_lag1 + Y_lag2
## Model 2: Y ~ Y_lag1 + Y_lag2 + X_lag1 + X_lag2
## Res.Df RSS Df Sum of Sq F Pr(>F)
## 1 95 219.431
## 2 93 89.866 2 129.56 67.041 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# Interpretación
cat("\n=== INTERPRETACIoN ===\n")
##
## === INTERPRETACIoN ===
if(anova_test$`Pr(>F)`[2] < 0.05) {
cat("Se rechaza H0: X NO causa Granger a Y\n")
cat("Conclusion: X SÍ causa Granger a Y (p =", anova_test$`Pr(>F)`[2], ")\n")
} else {
cat("No se rechaza H0: X NO causa Granger a Y\n")
cat("Conclusion: No hay evidencia de causalidad (p =", anova_test$`Pr(>F)`[2], ")\n")
}
## Se rechaza H0: X NO causa Granger a Y
## Conclusion: X SÍ causa Granger a Y (p = 9.374584e-19 )
Ejemplo Integrado Completo
# ANÁLISIS COMPLETO: COINTEGRACIÓN Y CAUSALIDAD
library(urca)
library(vars)
library(tseries)
# PASO 1: Generar series cointegradas con causalidad - SIN USAR LAG()
set.seed(123)
n <- 200
# Serie común no estacionaria
tendencia_comun <- cumsum(rnorm(n))
# Series cointegradas base
y1 <- tendencia_comun + rnorm(n, 0, 0.5)
y2_base <- 1.5 * tendencia_comun + rnorm(n, 0, 0.5)
# Agregar causalidad: y1 causa y2 con rezago MANUALMENTE
y2 <- numeric(n)
for(i in 3:n) {
y2[i] <- y2_base[i] + 0.3 * y1[i-1] + 0.2 * y1[i-2]
}
# Eliminar primeros 2 valores que tienen NA
y1_clean <- y1[3:n]
y2_clean <- y2[3:n]
# Crear dataset sin NAs
dataset <- cbind(y1 = y1_clean, y2 = y2_clean)
cat("Dimensión del dataset limpio:", dim(dataset), "\n")
## Dimensión del dataset limpio: 198 2
# PASO 2: Pruebas de raíz unitaria
cat("\n=== PRUEBAS DE RAÍZ UNITARIA ===\n")
##
## === PRUEBAS DE RAÍZ UNITARIA ===
# Para y1
adf_y1 <- ur.df(y1_clean, type = "drift", lags = 4)
cat("y1 - ADF Test:\n")
## y1 - ADF Test:
##
## ###############################################
## # Augmented Dickey-Fuller Test Unit Root Test #
## ###############################################
##
## Test regression drift
##
##
## Call:
## lm(formula = z.diff ~ z.lag.1 + 1 + z.diff.lag)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.5915 -0.7618 -0.0499 0.6301 3.3059
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.077404 0.098299 0.787 0.4320
## z.lag.1 -0.059125 0.030735 -1.924 0.0559 .
## z.diff.lag1 -0.171614 0.075290 -2.279 0.0238 *
## z.diff.lag2 -0.084702 0.076006 -1.114 0.2665
## z.diff.lag3 -0.033133 0.075550 -0.439 0.6615
## z.diff.lag4 0.004723 0.073461 0.064 0.9488
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1.133 on 187 degrees of freedom
## Multiple R-squared: 0.06594, Adjusted R-squared: 0.04097
## F-statistic: 2.64 on 5 and 187 DF, p-value: 0.02474
##
##
## Value of test-statistic is: -1.9237 1.9097
##
## Critical values for test statistics:
## 1pct 5pct 10pct
## tau2 -3.46 -2.88 -2.57
## phi1 6.52 4.63 3.81
# Para y2
adf_y2 <- ur.df(y2_clean, type = "drift", lags = 4)
cat("\ny2 - ADF Test:\n")
##
## y2 - ADF Test:
##
## ###############################################
## # Augmented Dickey-Fuller Test Unit Root Test #
## ###############################################
##
## Test regression drift
##
##
## Call:
## lm(formula = z.diff ~ z.lag.1 + 1 + z.diff.lag)
##
## Residuals:
## Min 1Q Median 3Q Max
## -4.1302 -0.9855 0.0810 1.0306 5.0046
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.12091 0.14162 0.854 0.3944
## z.lag.1 -0.04473 0.02252 -1.986 0.0485 *
## z.diff.lag1 -0.01599 0.07326 -0.218 0.8275
## z.diff.lag2 0.03736 0.07311 0.511 0.6100
## z.diff.lag3 0.05641 0.07339 0.769 0.4431
## z.diff.lag4 -0.01030 0.07381 -0.139 0.8892
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1.62 on 187 degrees of freedom
## Multiple R-squared: 0.02468, Adjusted R-squared: -0.001399
## F-statistic: 0.9464 on 5 and 187 DF, p-value: 0.4523
##
##
## Value of test-statistic is: -1.9864 2.0279
##
## Critical values for test statistics:
## 1pct 5pct 10pct
## tau2 -3.46 -2.88 -2.57
## phi1 6.52 4.63 3.81
# Interpretación ADF
cat("\n=== INTERPRETACIÓN ADF ===\n")
##
## === INTERPRETACIÓN ADF ===
cat("y1 - Estadístico:", adf_y1@teststat[1], "Valor crítico 5%:", adf_y1@cval[1, "5pct"], "\n")
## y1 - Estadístico: -1.923695 Valor crítico 5%: -2.88
cat("y2 - Estadístico:", adf_y2@teststat[1], "Valor crítico 5%:", adf_y2@cval[1, "5pct"], "\n")
## y2 - Estadístico: -1.986389 Valor crítico 5%: -2.88
if(adf_y1@teststat[1] > adf_y1@cval[1, "5pct"]) {
cat("y1: No se rechaza H0 - Serie NO estacionaria (I(1))\n")
} else {
cat("y1: Se rechaza H0 - Serie estacionaria (I(0))\n")
}
## y1: No se rechaza H0 - Serie NO estacionaria (I(1))
if(adf_y2@teststat[1] > adf_y2@cval[1, "5pct"]) {
cat("y2: No se rechaza H0 - Serie NO estacionaria (I(1))\n")
} else {
cat("y2: Se rechaza H0 - Serie estacionaria (I(0))\n")
}
## y2: No se rechaza H0 - Serie NO estacionaria (I(1))
# PASO 3: Prueba de cointegración (solo si ambas son I(1))
if(adf_y1@teststat[1] > adf_y1@cval[1, "5pct"] & adf_y2@teststat[1] > adf_y2@cval[1, "5pct"]) {
cat("\n=== PRUEBA DE COINTEGRACIÓN (JOHANSEN) ===\n")
johansen_test <- ca.jo(dataset, type = "trace", ecdet = "const", K = 2)
print(summary(johansen_test))
# Interpretación Johansen
cat("\n=== INTERPRETACIÓN JOHANSEN ===\n")
test_stats <- johansen_test@teststat
critical_vals <- johansen_test@cval[,"5pct"]
for(i in 1:length(test_stats)) {
cat("H0: r =", i-1, "- Estadístico:", test_stats[i], "Valor crítico 5%:", critical_vals[i])
if(test_stats[i] > critical_vals[i]) {
cat(" - RECHAZAR H0\n")
} else {
cat(" - NO RECHAZAR H0\n")
}
}
# PASO 4: Prueba de causalidad
cat("\n=== PRUEBA DE CAUSALIDAD DE GRANGER ===\n")
var_model <- VAR(dataset, p = 2, type = "const")
causality_y1y2 <- causality(var_model, cause = "y1")
causality_y2y1 <- causality(var_model, cause = "y2")
cat("Causalidad y1 -> y2:\n")
print(causality_y1y2)
cat("\nCausalidad y2 -> y1:\n")
print(causality_y2y1)
# PASO 5: Estimación VECM si hay cointegración
if(johansen_test@teststat[1] > johansen_test@cval[1, "5pct"]) {
cat("\n=== ESTIMACIÓN VECM ===\n")
vecm_model <- cajorls(johansen_test, r = 1)
print(summary(vecm_model$rlm))
# Coeficiente de corrección de error
cat("\nCoeficiente de corrección de error (velocidad de ajuste):\n")
cat("y1:", vecm_model$rlm$coefficients["ect1", "y1"], "\n")
cat("y2:", vecm_model$rlm$coefficients["ect1", "y2"], "\n")
}
} else {
cat("\nLas series no son ambas I(1). No se procede con cointegración.\n")
}
##
## === PRUEBA DE COINTEGRACIÓN (JOHANSEN) ===
##
## ######################
## # Johansen-Procedure #
## ######################
##
## Test type: trace statistic , without linear trend and constant in cointegration
##
## Eigenvalues (lambda):
## [1] 4.620315e-01 1.955453e-02 8.885731e-19
##
## Values of teststatistic and critical values of test:
##
## test 10pct 5pct 1pct
## r <= 1 | 3.87 7.52 9.24 12.97
## r = 0 | 125.38 17.85 19.96 24.60
##
## Eigenvectors, normalised to first column:
## (These are the cointegration relations)
##
## y1.l2 y2.l2 constant
## y1.l2 1.00000000 1.00000 1.00000000
## y2.l2 -0.50812747 -28.14021 -0.02014648
## constant 0.02949247 84.57748 -30.84038855
##
## Weights W:
## (This is the loading matrix)
##
## y1.l2 y2.l2 constant
## y1.d -0.8045618 0.0009769807 -1.386549e-17
## y2.d 0.8927746 0.0013874009 2.021149e-17
##
##
## === INTERPRETACIÓN JOHANSEN ===
## H0: r = 0 - Estadístico: 3.870656 Valor crítico 5%: 9.24 - NO RECHAZAR H0
## H0: r = 1 - Estadístico: 125.3819 Valor crítico 5%: 19.96 - RECHAZAR H0
##
## === PRUEBA DE CAUSALIDAD DE GRANGER ===
## Causalidad y1 -> y2:
## $Granger
##
## Granger causality H0: y1 do not Granger-cause y2
##
## data: VAR object var_model
## F-Test = 12.662, df1 = 2, df2 = 382, p-value = 4.739e-06
##
##
## $Instant
##
## H0: No instantaneous causality between: y1 and y2
##
## data: VAR object var_model
## Chi-squared = 80.711, df = 1, p-value < 2.2e-16
##
##
##
## Causalidad y2 -> y1:
## $Granger
##
## Granger causality H0: y2 do not Granger-cause y1
##
## data: VAR object var_model
## F-Test = 7.3103, df1 = 2, df2 = 382, p-value = 0.0007663
##
##
## $Instant
##
## H0: No instantaneous causality between: y2 and y1
##
## data: VAR object var_model
## Chi-squared = 80.711, df = 1, p-value < 2.2e-16