-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathVECandJohansen.r
389 lines (322 loc) · 16.1 KB
/
VECandJohansen.r
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
# __________________________________________________________________________
# ________ METODOLOGÍA DE JOHANSEN EN EL ANÁLISIS DE COINTEGRACIÓN ________
# __________________________ DE SERIES TEMPORALES __________________________
# __________________________________________________________________________
#
#
# 1. INTRODUCCIÓN
# La Metodología de Johansen es ampliamente utilizada en el análisis de series
# de tiempo cointegradas, es decir, series de tiempo que tienen una relación
# a largo plazo.
# Queremos determinar el orden de integración en las series y luego usar los
# criterios de información de un Modelo Vectorial Autorregresivo (VAR) para
# conocer el número de rezagos del Modelo de Corrección de Errores Vectorial
# (VECM).
# Después, determinaremos el número de relaciones de cointegración y estimaremos
# el VECM para analizar el vector de cointegración, que representa la relación
# a largo plazo entre las variables (podremos ver cómo se combinan las
# variables). De igual manera, podremos ver cómo cada variable se va ajustando
# hasta el equilibrio de largo plazo.
# Todo lo anterior permitirá que podamos hacer uso del modelo. Con el modelo
# obtenido podremos realizar análisis de impulso-respuesta (efectos en la
# variable i por choques de la variable j e i, a lo largo del tiempo), en
# donde, además de analizar los efectos por choques de las variables, veremos
# la dirección de la causalidad entre las variables, si las hay.
#
#
# --------- 2. SELECCIÓN DE LAS SERIES Y PREPARACIÓN DE LOS DATOS -----------
#
# 2.1. Selección de las series
# De acuerdo a la teoría cuantitativa del dinero, existe una relación directa
# entre la cantidad de dinero en circulación (oferta monetaria) y el nivel
# general de precios. Irving Fisher, quien propuso esta relación, la expresó
# matemáticamente de la forma MV=PQ, en donde M es cantidad de dinero, V
# velocidad del dinero, P nivel general de precios, y Q nivel de producción.
# Aplicaremos la Metodología de Johansen para analizar la relación de
# cointegración entre la cantidad de dinero en la economía (M2) y en nivel
# general de precios (IPC) para la economía estadounidense entre enero de 2000
# a enero de 2020.
# Si la teoría cuantitativa se cumple para este caso, veremos que ante aumentos
# de la cantidad de dinero, manteniendo las demás variables constantes, el
# nivel general de precio aumentará, y del mismo modo ante cambios negativos.
#
#
# 2.2. Preparación de los datos
#
# Limpiamos las variables de entorno
rm(list = ls())
# Librerías
packages <- c("vars", "urca", "ggplot2", "ggfortify", "gridExtra", "dplyr",
"tidyr", "readxl", "tsDyn", "VAR.etp", "lubridate")
install_packages <- function(packages) {
for (package in packages) {
if (!requireNamespace(package, quietly = TRUE)) {
install.packages(package)
}
}
}
install_packages(packages)
library_packages <- function(packages) {
for (package in packages) {
if (!requireNamespace(package, quietly = TRUE)) {
message("El paquete '", package, "' no está instalado.
Intentar con install.packages().")
} else {
library(package, character.only = TRUE)
}
}
}
library_packages(packages)
install.packages("urca")
library(urca)
# Cargar las series
path_file <- file.choose()
data <- read_excel(path_file)
# Adjuntar datos al entorno de trabajo
attach(data)
# Convertir datos a ts
money_supply <- ts(M2SL, start = c(2000, 1), frequency = 12)
price_index <- ts(CPIAUCSL, start = c(2000, 1), frequency = 12)
# ----- 3. PASO 1: DETERMINACIÓN DEL GRADO DE INTEGRACIÓN Y REZAGOS ------
#
# 3.1. Grado de integración
# Vamos a determinar el grado de integración necesario para que las series de
# tiempo sean estacionarias a largo plazo. Antes de hacer esto, veamos cómo
# se comportan las series en niveles (originales, sin diferenciación).
start_year <- min(year(data$DATE))
end_year <- max(year(data$DATE))
x11()
grid.arrange(
ggplot(data = money_supply, aes(x = DATE, y = M2SL)) +
geom_line(color = "#FF4040", size = 1) +
labs(title = paste0("Money supply EE.UU. ", "(", start_year,
" - ", end_year, ")"), x = "Fecha", y = "Billones de dólares"),
ggplot(data = price_index, aes(x = DATE, y = CPIAUCSL)) +
geom_line(color = "deepskyblue4", size = 1) +
labs(title = paste0("IPC EE.UU. ", "(", start_year, " - ", end_year, ")"),
x = "Fecha", y = "Índice"),
nrow = 1, ncol = 2
)
# Es evidente que las series no son estacionarias, pero vamos a realizar la
# prueba de raíz unitaria de Dickey-Fuller aumentado (ADF). Usaremos el
# criterio de información AIC. No usamos el BIC, aunque sea más parsimonioso,
# porque el AIC incluye más rezagos de las series diferenciadas. Si no se
# incluyen los suficientes rezagos, no se puede controlar la correlación en
# el error y la prueba no sería válida.
# La prueba cambia si incluimos o no constante, tendencia y la combinación de
# ambas, Así que realizamos varias pruebas.
# Las pruebas para analizar la significancia de la tendencia y de la deriva
# son pruebas de cola derecha, es decir, si el estadístico t se encuentra a
# derecha del valor crítico rechazamos la hipótesis nula de significacnia 0.
# Primero, las series en niveles, con y sin constante.
# Money supply con trend:
summary(ur.df(money_supply, lags = 6, selectlags = "AIC", type = "trend"))
# Money supply con constante:
summary(ur.df(money_supply, lags = 6, selectlags = "AIC", type = "drift"))
# Money supply sin constante y sin tenencia:
summary(ur.df(money_supply, lags = 6, selectlags = "AIC", type = "none"))
# En este caso, la tendencia resultó ser no significativa, mientras que la
# deriva sí lo es. En esa misma prueba de deriva verificamos estacionariedad
# con tau2, que nos dice que la serie en niveles no es estacionaria.
# IPC con trend
summary(ur.df(price_index, lags = 6, selectlags = "AIC", type = "trend"))
# IPC con constante:
summary(ur.df(price_index, lags = 6, selectlags = "AIC", type = "drift"))
# IPC supply sin constante y sin tenencia:
summary(ur.df(price_index, lags = 6, selectlags = "AIC", type = "none"))
# Del mismo modo que con la serie money_supply, la tendenica no es
# significativa y la deriva sí lo es. Además, en la prueba de significancia
# para la deriva, la serie resultó ser no estacionaria, de acuerdo al t
# estadístico para verificar estacionariedad, tau2.
# Ahora que sabemos que las series no son estacionarias, vamos a realizar la
# misma prueba para las series diferenciadas, incluyendo el parámetro
# de la deriva que es significativo.
summary(ur.df(diff(money_supply), lags = 6, selectlags = "AIC", type = "drift"))
summary(ur.df(diff(price_index), lags = 6, selectlags = "AIC", type = "drift"))
# Las series son integradas de orden 1, es decir que al realizarles una
# diferencia son estacionarias, requisito para realizar la prueba de
# cointegración de Johansen.
# 3.2. Determinamos el número de rezagos del VECM a través de un VAR en niveles
# Es importante la manera en la que tratamos a las variables (si son
# dependientes o independientes).
# Siguiendo las ideas de la Teoría Cuantitativa del dinero, vamos a tratar al
# nivel de precios como la variable explicada y a la oferta monetaria como
# la variable explicativa.
series_matrix <- cbind(price_index, money_supply)
# Considerando rezagos en las variables exógena y endógena:
VARselect(series_matrix, lag.max = 6, type = "both", season = NULL)
# De acuerdo a las pruebas HQ (Hannan-Quinn Criterion) y SC (Schwarz Criterion),
# el modelo más parsimonioso es un VAR(2)
# Considerando rezagos en la variable endógena (price_index):
VARselect(series_matrix, lag.max = 6, type = "const", season = NULL)
# De acuerdo a la prueba SC (Schwarz Criterion), el modelo más parsimonioso
# es un VAR(2)
# Sin considerar rezagos en ninguna variable:
VARselect(series_matrix, lag.max = 6, type = "none", season = NULL)
# De acuerdo a la prueba SC (Schwarz Criterion), el modelo más parsimonioso
# es un VAR(2)
# Ahora, vamos a ajustar el modelo vectorial autorregresivo (VAR) al
# conjunto de datos, con los rezagos que determinamos adecuados
# anteriormente:
summary(VAR(series_matrix, p = 2, type = "both", season = NULL))
# Aunque para un modelo la tendencia es significativa, para el otro no lo es,
# así que no la añadiremos al modelo VAR
# Ahora veamos la constante:
summary(VAR(series_matrix, p = 2, type = "const", season = NULL))
# Para las dos ecuaciones, la deriva no es significativa
# Entonces, nuestro VAR va a estar determinado por:
selected_var <- VAR(series_matrix, p = 2, type = "const", season = NULL)
# Analizaremos el comportamiento de los residuales; si no se comportan
# adecuadamente (hay autocorrelación serial), agregaremos más rezagos.
# Buscamos no rechazar la hipótesis de ausencia de serialidad en los
# residuos, la cual es un requisito para aplicar la metodología de Johansen.
residuals_75 <- serial.test(selected_var, lags.pt = 70, type = "PT.asymptotic")
residuals_75
residuals_30 <- serial.test(selected_var, lags.pt = 30, type = "PT.asymptotic")
residuals_30
residuals_20 <- serial.test(selected_var, lags.pt = 20, type = "PT.asymptotic")
residuals_20
residuals_10 <- serial.test(selected_var, lags.pt = 10, type = "PT.asymptotic")
residuals_10
# Para las cuatro opciones no rechazamos la hipótesis nula de no autocorrelación
# serial en los errores, así que continuamos con el proceso.
# Graficamos los residuales:
x11()
plot(residuals_20, names = "price_index")
plot(residuals_20, names = "money_supply")
# ------------- 4. PASO 2: DETERMINANDO EL RANGO DE LA MATRIZ PI ---------------
# 4.1. Johansen con constante fuera del vector de cointegración
# 4.1.1. Criterio del valor propio máximo
max_value_criterion_out <- ca.jo(series_matrix, ecdet = "none", type = "eigen",
K = 2, spec = "transitory", season = NULL)
summary(max_value_criterion_out)
# El resultado es un t estadístico de 17.41, contra un valor crítico de 14.90
# al 5%. El t estadístico cae en zona de rechazo: rechazamos que las relaciones
# de cointegración sean 0 y pasamos a la siguiente hipótesis nula: 1 relación
# de cointegración. Para este caso, el t estadístico es 3.27 y el valor crítico
# a 5% es 8.18. El estadístico cae en la zona de no rechazo, así que existe una
# relación de cointegración.
# Aunque estos valores son confiables, haremos uso del Criterio de la traza
# para estar seguros.
# H_0: r=0. Cola derecha
# 4.1.2. Criterio de la traza:
trace_criterion_out <- ca.jo(series_matrix, ecdet = "none", type = "trace",
K = 2, spec = "transitory", season = NULL)
summary(trace_criterion_out)
# Confirmamos una relación de cointegración.
# 4.2. Johansen con constante dentro del vector de cointegración
# 4.2.1. Criterio del valor propio
max_value_criterion_in <- ca.jo(series_matrix, ecdet = "const", type = "eigen",
K = 2, spec = "longrun", season = NULL)
summary(max_value_criterion_in)
# La prueba nos muestra que se rechaza la hipótesis nula de relaciones de
# cointegración = 0, por lo que hay >=1 relaciones de cointegración.
# 4.2.2. Criterio de la traza
trace_criterion_in <- ca.jo(series_matrix, ecdet = "const", type = "trace",
K = 2, spec = "longrun", season = NULL)
summary(trace_criterion_in)
# Confirmamos que hay al menos una relación de cointegración.
# 4.3. Determinando la tendencia lineal del modelo VEC
# Veremos si debemos incluir el modelo con constante en la relación de
# cointegración
lttest(max_value_criterion_out, r = 1)
lttest(max_value_criterion_in, r = 1)
# Tenemos resultados consistentes. La prueba sugiere no incluir el modelo
# con constante en la relación de cointegración.
# 4.4. Estimamos el modelo VEC con la constante fuera del vector de
# cointegración
vec_drift_out <- cajorls(max_value_criterion_out, r = 1)
vec_drift_out
# ------------- 5. PASO 3: ANÁLISIS DE LA MATRIZ BETA Y ALPHA ---------------
# El vector de cointegración normalizado:
coefB(vec_drift_out2)
# Coeficientes de velocidad de ajuste:
coefA(vec_drift_out2)
# -------------------- 5. PASO 4: VALIDANDO LOS SUPUESTOS -------------------
# Reparametrización de VEC como VAR en niveles
vec_to_var <- vec2var(max_value_criterion_out, r = 1)
vec_to_var
# 5.1. Validación de supuestos
# 5.1.1. Autocorrelación
autocorr75 <- serial.test(vec_to_var, lags.pt = 75, type = "PT.asymptotic")
autocorr75
autocorr30 <- serial.test(vec_to_var, lags.pt = 30, type = "PT.asymptotic")
autocorr30
autocorr20 <- serial.test(vec_to_var, lags.pt = 20, type = "PT.asymptotic")
autocorr20
autocorr10 <- serial.test(vec_to_var, lags.pt = 10, type = "PT.asymptotic")
autocorr10
# Para ningún nivel de retardos utilizados en la prueba se puede rechazar la
# hipótesis nula de no autocorrelación.
# Graficamos los residuales
x11()
plot(autocorr20, names = "price_index")
x11()
plot(autocorr20, names = "money_supply")
# 5.1.2. Homocedasticidad
arch.test(vec_to_var, lags.multi = 24, multivariate.only = TRUE)
arch.test(vec_to_var, lags.multi = 12, multivariate.only = TRUE)
# El valor p (0.1333) es mayor que el umbral de significancia comúnmente
# utilizado de 0.05. Esto sugiere que no hay suficiente evidencia para
# rechazar la hipótesis nula de homocedasticidad condicional en los residuos
# del modelo VAR. Pero al realizar la misma prueba para 12 rezagos, el valor
# p (1.119e-06) es extremadamente pequeño, lo que indica una evidencia fuerte
# en contra de la hipótesis nula de homocedasticidad condicional en los
# residuos del modelo VAR.
# 5.1.3. Normalidad
normality.test(vec_to_var)
# En este caso, el valor p (< 2.2e-16) es extremadamente pequeño, lo que indica
# una evidencia fuerte en contra de la hipótesis nula de normalidad en los
# residuos del modelo VAR.
# 5.2. Pronóstico
x11()
predict(vec_to_var, n.ahead = 12)
plot(predict(vec_to_var, n.ahead = 12))
# 5.2.1. Función impulso-respuesta (FIR)
impulso_respuesta <- function(var, impulso, respuesta, pasos_adelante,
ortog, int_conf, titulo){
# Cálculo de la FIR
total_pasos_futuros <- length(pasos_adelante) - 1
FIR <- fir(var, impulse = impulso, response = respuesta,
n.ahead = total_pasos_futuros, ortho = ortog, ci = int_conf)
FIR_data_frame <- data.frame(FIR$fir, FIR$Lower, FIR$Upper, pasos_adelante)
# Gráfica
graph <- ggplot(data = FIR_data_frame,
aes(x = pasos_adelante, y = FIR_data_frame[, 1],
ymin = FIR_data_frame[, 2], ymax = FIR_data_frame[, 3])) +
geom_hline(yintercept = 0, color = "red") +
geom_ribbon(fill = "grey", alpha = 0.2) +
geom_line() +
theme_light() +
ggtitle(titulo) +
ylab("") +
xlab("pasos adelante") +
theme(plot.title = element_text(size = 11, hjust = 0.5),
axis.title.y = element_text(size = 11))
return(graph)
}
# Definimos el número de pasos adelante
pasos_adelante <- 0:18
# FIR de las variables del sistema ante distintos choques exógenos.
v1_v1 <- impulso_respuesta(vec_to_var, "price_index", "price_index",
pasos_adelante = pasos_adelante,
ortog = TRUE, int_conf = 0.95,
titulo =
"Impulso de price_index - respuesta de price_index")
v1_v2 <- impulso_respuesta(vec_to_var, "price_index", "money_supply",
pasos_adelante = pasos_adelante,
ortog = TRUE, int_conf = 0.95,
titulo =
"Impulso de price_index - respuesta de money_supply")
v2_v1 <- impulso_respuesta(vec_to_var, "money_supply", "price_index",
pasos_adelante = pasos_adelante,
ortog = TRUE, int_conf = 0.95,
titulo =
"Impulso de money_supply - respuesta de price_index")
v2_v2 <- impulso_respuesta(vec_to_var, "money_supply", "money_supply",
pasos_adelante = pasos_adelante,
ortog = TRUE, int_conf = 0.95,
titulo =
"Impulso de money_supply - respuesta de money_supply")
# Mostrar las gráficas en una matriz de 2x2
grid.arrange(v1_v1, v1_v2, v2_v1, v2_v2, ncol = 2)