Mostrando entradas con la etiqueta Métodos cuantitativos. Mostrar todas las entradas
Mostrando entradas con la etiqueta Métodos cuantitativos. Mostrar todas las entradas

14 sept 2025

Macroeconometría aplicada en R

 La macroeconomía moderna depende cada vez más de herramientas econométricas para analizar datos, evaluar políticas y construir pronósticos. Este curso de Macroeconometría aplicada en R surge con el objetivo de condensar, en un solo espacio, las metodologías más utilizadas en el análisis macroeconómico empírico, de manera práctica y accesible.

Se trata de un curso autocontenido y aplicado: no busca sustituir la formación formal en econometría o macroeconomía, pero sí ofrecer una caja de herramientas lista para usar en el trabajo diario con temas macroeconómicos.

Parte 1: Introducción

Clase 1.1. Elementos básicos de la macroeconometría aplicada.

Clase 1.2. Pronósticos, modelos y banca central.

Repaso 1. Introducción a R.

Repaso 2. Análisis exploratorio de series temporales en R.

Repaso 3. Nociones de econometría. 

Parte 2: Modelos univariados

Clase 2.1. Análisis univariado.

Clase 2.2. Fluctuaciones macroeconómicas.

Clase 2.3. Incertidumbre macroeconómica: introducción a modelos GARCH.

Clase 2.4. Extensiones de los modelos GARCH. (GJR-GARCH, eGARCH, Markov-GARCH)

Clase 2.5. Modelos lineales

Parte 3: Modelos de política

Clase 3.1. Vectores autoregresivos estructurales (SVAR): estrategia de identificación de corto plazo.

Clase 3.2. Extensiones de los modelos VAR: restricciones de largo plazo y de signos.

Clase 3.3. Modelos VEC (vectores de corrección de error).

Clase 3.4. GARCH multivariados

Parte 4: extensiones adicionales

Repaso 4. Econometría bayesiana

Clase 4.1. VAR bayesianos y modelos con coeficientes cambiantes

Clase 4.2. GMM y modelo espacio estado

Clase 4.3. Pronósticos de series macroeconómicas

Parte 5: Pronósticos

Clase 5.1. Pronósticos macroeconómicos

31 oct 2024

Evaluación de pronóstico en R: validación cruzada de modelos de series temporales

En el siguiente ejemplo se muestra una validación cruzada de series temporales en R. Necesita evaluar la capacidad de pronóstico de un modelo para elegir alguna alternativa en función de su rendimiento. Es decir, necesito verificar cual hubiese sido el pronóstico histórico de una serie temporal, por ejemplo con un modelo AR(1), para comparar con la precisión de otros modelos y decidir cual estrategia seguir en lo adelante. En este sentido, necesitaríamos realizar el ejercicio de proyección en distintos puntos temporales, para posteriormente recuperar los errores y comparar estas medidas de error entre distintos modelos.

 1.       Simulamos la serie temporal (en el caso de una base de datos, deberías importarlas en R).

 library(writexl)   # Exportar a Excel
library(readxl)
library(lubridate) # dates
library(tidyverse)
library(forecast)
library(timeSeries)
library(zoo)
 
# Importando datos ---------------
# ********************************************************************
# ********************************************************************
 
# Configuración inicial
set.seed(4)    # Asegura reproducibilidad
n <- 250       # Número de días (simulación de aproximadamente un año laboral)
mu <- 0        # Promedio del cambio diario (sin tendencia)
sigma <- 0.01  # Volatilidad diaria
 
# Generación de la caminata aleatoria
tipo_cambio <- cumsum(c(1, rnorm(n, mean = mu, sd = sigma)))  # Inicia en 100 y suma los cambios diarios
 
# Creación de un data.frame con fechas
fechas <- seq.Date(from = as.Date("2023-01-01"), by = "day", length.out = n + 1)
df <- data.frame(fecha = fechas, tipo_cambio = tipo_cambio)
 
# Gráfico de series temporales
library(ggplot2)
ggplot(df, aes(x = fecha, y = tipo_cambio)) +
  geom_line(color = "blue") +
  labs(title = "Simulación de Caminata Aleatoria del Tipo de Cambio",
       x = "Fecha",
       y = "Tipo de Cambio") +
  theme_minimal()
 
library(xts)
tipo_cambio_xts <- xts(tipo_cambio, order.by = fechas)

 
2.       Validación cruzada

En resumen, lo que se hace es definir una ventana de estimación y otra de validación (pronóstico). En este ejemplo son de 60 y 5 observaciones respectivamente. 60 observaciones serán usadas para estimar el modelo, mientras que 5 será la longitud de la ventana del pronóstico. De esta forma, en la primera iteración se va estimar los modelos con observaciones del 1:60 y otra ventana de pronóstico de la 61-65, luego 2:61 y 62:66, … y así respectivamente hasta recorrer toda la muestra. El documento de trabajo “Pronóstico del consumo privado en la República Dominicana” de Alejandro J. Balcácer y Nerys F. Ramírez, muestra en detalle esta estrategia.

 # Análisis de precisión. Error histórico ---------------

h.valid <- 5
horizonte <- paste0("h", 1:h.valid)
vent <- 60

Posteriormente, se genera un for para realizar este recorrido usando una serie. Primero se define el valor del ultimo dato observado en cada iteración del bucle (seq_for), este dato sirve de referencia para el resto de las ventanas. Además, se define un contador para el punto de inicio de la ventana de estimación (cont). Los puntos clave de esta secuencia son:

-          Indicar la secuencia con la posición de las observaciones que vamos a usar en cada punto de la serie temporal [obser in seq_for].

-          La serie temporal se segmenta en dos partes: la estimación (tipo_cambio_xts[cont:obser]) y la otra parte de pronósticos (tipo_cambio_xts[(obser+1):(obser+h.valid)]). Fíjese que la primera va desde el contador hasta obser, recuerde que obser es el valor final hasta donde irá la ventana de estimación y el valor que en el presente ejemplo sirve de referencia. Luego, la parte para evaluar las proyecciones se definen a partir de la última observación de la parte de estimación (obser+1):(obser+h.valid).

-          La tercera parte importante del bucle es incluir el modelo de pronóstico. Aquí debemos usar alguna estrategia para proyectar los periodos que nos resulten de interés. En este ejemplo son 5 observaciones, y se usa un modelo ar(1).

-          Finalmente, se crea un data.frame para guardar el pronóstico, el dato observado, los horizontes y el nombre del model. Además, se guarda cada data.frame en una lista creada anteriormente (data_Rbind). Primero se llaman todos los objetos que inician con “df_” (tener pendiente guardar cada nuevo modelo con ese nombre).  

 # Esto lo que hace, es que permite recorrer las ventanas
seq_for <- vent:(nrow(tipo_cambio_xts)-h.valid)
 
# OJO CORRER EL BULCE DESDE AQUI
cont <- 1
data_Rbind <- list() # Lista que guarda resultados
 
for (obser in seq_for){
  
  tc_train <- tipo_cambio_xts[(obser-vent+1):obser]
  tc_test <- tipo_cambio_xts[(obser+1):(obser+h.valid)]
 
  fecha_ciclo <- fechas[obser]
  fecha_hat <-  fechas[(obser+1):(obser+h.valid)]
 
ordena_data <- function(objetos,...){
  # objetos = lista de nombre de vectore
 
  # Iterar sobre los nombres de los objetos y cambiar los nombres de las columnas
  for (i in seq_along(objetos_df)) {
    xdf_name <- get(objetos_df[i])
    new_column_names <- c("fechaCiclo","fechaHat","horizonte","obs","pro","model")
    names(xdf_name) <- new_column_names
    assign(objetos_df[i], xdf_name)
  }
 
  lista_objetos <- lapply(objetos_df, get)
  df1_final <- dplyr::bind_rows(lista_objetos)
  return(df1_final)
}
    ### 1. ESTRATEGIA AR(1) . Ventana móvil ************************
 
    model_ar1 <- Arima(tipo_cambio_xts, order=c(1,0,0))
    ht_f_ar1 <- forecast::forecast(model_ar1, h=h.valid)$mean                 
   
    df_ar1 <- data.frame(fecha_ciclo, fecha_hat, horizonte,  #fechas
                         obsT=tc_test, # dato observado
                         proT=ht_f_ar1,
                         model="1.Ar(1)_móvil")
 
    ### 1. ESTRATEGIA AR(2,1) . Ventana móvil ************************
   
    model_ar21 <- Arima(tipo_cambio_xts, order=c(2,0,1))
    ht_f_ar21 <- forecast::forecast(model_ar21, h=h.valid)$mean                 
   
    df_ar21 <- data.frame(fecha_ciclo, fecha_hat, horizonte,  #fechas
                         obsT=tc_test, # dato observado
                         proT=ht_f_ar21,
                         model="2.Ar(21)_móvil")
   
### ******************************************************************
### ******************************************************************
objetos <- ls()
objetos_df <- objetos[grep("^df_", objetos)]
 
data_Rbind[[(obser-vent+1)]] <- ordena_data(objetos_df)
   
# Esto al final siempre       
cont <- cont+1  # cont y esto es equivalente (obser-vent+1):
}

Luego de culminar, se utiliza una función propia para ordenar la data (ordena_data) y convertirla en un único data.frame con toda la data:

data_forecast_final
# A tibble: 1,870 × 6
   fechaCiclo fechaHat   horizonte   obs  proy model        
   <date>     <date>     <chr>     <dbl> <dbl> <chr>        
 1 2023-03-01 2023-03-02 h1        0.969 1.01  1.Ar(1)_móvil
 2 2023-03-01 2023-03-03 h2        0.981 1.01  1.Ar(1)_móvil
 3 2023-03-01 2023-03-04 h3        0.972 1.01  1.Ar(1)_móvil
 4 2023-03-01 2023-03-05 h4        0.978 1.00  1.Ar(1)_móvil
 5 2023-03-01 2023-03-06 h5        0.987 1.00  1.Ar(1)_móvil
 6 2023-03-01 2023-03-02 h1        0.969 1.01  1.Ar(21)_móvil
 7 2023-03-01 2023-03-03 h2        0.981 1.01  1.Ar(21)_móvil
 8 2023-03-01 2023-03-04 h3        0.972 1.01  1.Ar(21)_móvil
 9 2023-03-01 2023-03-05 h4        0.978 1.00  1.Ar(21)_móvil
10 2023-03-01 2023-03-06 h5        0.987 0.999 1.Ar(21)_móvil

 Con esta data, ahora se puede realizar cualquier análisis sobre los errores promedio, su evolución histórica o el comportamiento de estos errores condicionados a eventos económicos, por ejemplo, los errores durante el COVID o periodos de alta incertidumbre.

 # Cuadrando la base de los errores
# Crea la data final con todos los los dtos necesarios
data_forecast_final <- dplyr::bind_rows(data_Rbind) |> as_tibble()
names(data_forecast_final) <- c("fechaCiclo","fechaHat","horizonte","obs","proy","model")
 
# Errores total
# Total
data_forecast_final |>
  #dplyr:: filter(fechaCiclo > as.Date("2018-01-01"))  |>
  mutate(error=obs-proy) |>
  group_by(horizonte, model) |> # (horizonte, model, COVID)
  summarize(
    mae_e_abs = mean(abs(error), na.rm = TRUE),
  ) |>
  pivot_wider(names_from = horizonte, values_from = mae_e_abs) |>
  arrange(h1) |>
  dplyr::select(model,horizonte, everything())
 
`summarise()` has grouped output by 'horizonte'. You can override using the `.groups` argument.
# A tibble: 2 × 6
  model              h1     h2     h3     h4     h5
  <chr>           <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
1 1.Ar(21)_móvil 0.0479 0.0442 0.0405 0.0377 0.0350
2 1.Ar(1)_móvil  0.0483 0.0443 0.0409 0.0378 0.0353

28 oct 2024

Colocando etiquetas en gráficos en R usando labeller

En ocasiones estamos interesados en representar series con distintas escalas, por ejemplo: el precio del petróleo, la inflación y el crecimiento económico. Lo que suele ser frecuente cuando describimos múltiples series temporales al inicio de una investigación o presentación. Estas series, suelen calcularse a partir de distintas transformaciones y necesitar distintas etiquetas. En la siguiente entrada presentamos un ejemplo breve.

## carga los paquetes relevantes
packages = c("dplyr", "readxl", "writexl", "tseries", "forecast", "fastDummies", "lubridate", "cowplot","ggfortify","ggplot2","ggpubr","hrbrthemes","gghighlight","tidyverse","readr")
 
data_mes <- read_excel("data_embi.xlsx")
data_mes
# A tibble: 213 × 11
   fecha                 wti   vix ind_pro_usa r_inter ipc_rd ipc_sub_rd imae_rd tcn_venta
   <dttm>              <dbl> <dbl>       <dbl>   <dbl>  <dbl>      <dbl>   <dbl>     <dbl>
 1 2007-01-01 00:00:00  54.8  11.0        99.8    9.32   58.1       62.5    94.0      33.9
 2 2007-02-01 00:00:00  59.3  11.2       101.     9.15   58.3       62.5    96.9      33.5
 
data_t_mes <- data_mes  |>
  as_tibble(p_inter = 1/(1+r_inter)) |>
  mutate() |>
  mutate(across(wti:all_com, ~(log(.))),
         across(wti:all_com, ~((.-dplyr::lag(.,1))*100), .names= "dln{.col}"),
         across(wti:all_com, ~((.-dplyr::lag(.,12))*100), .names= "d12{.col}")) |>
  ungroup() |>
  na.omit()

Luego de importar nuestra data, realizamos distintas transformaciones: (1) en logaritmo, (2) la variación mensual y (3) la variación interanual. Luego, creamos un vector donde se indique el nombre de la variable y la etiqueta de la misma. El nombre se usará para elegir las variables de la base de datos, mientras que las etiquetas van a presentar una descripción sobre la variable que deseamos representar en nuestra gráfica.


# Selección y etiquetas de variables
variable_labels <- c(
  wti = "Petróleo",
  vix = "VIX",
  d12all_com = "Materias primas",
  d12ind_pro_usa = "Act. Ind. Ext. (% anual)",
  r_inter = "Tasa interbancaria",
  d12ipc_rd = "Inflación (% anual)",
  d12imae_rd = "Imae (% anual)",
  #d12lnimae_rd = "Exportaciones (% anual)",
  d12tcn_venta = "Depreciación anual",
  embi = "EMBI"
)

Finalmente, dentro de la función facet_wrap usamos el argumento labeller para indicar al programar la etiqueta que deseamos colocar.

# Definir los datos de ejemplo
fechas_recesion <- data.frame(
  inicio = as.POSIXct(c("2007-12-01", "2013-01-01",  "2020-03-01")),
  fin = as.POSIXct(c("2009-06-01", "2013-12-31", "2020-08-01"))
)
 
grafico_mes_sup <- data_t_mes |>
  mutate(fecha=as.POSIXct(fecha)) |>
  dplyr::select(fecha,names(variable_labels)) |> 
  pivot_longer(cols = -c(fecha), names_to = "Variable", values_to = "Valor") |>
  arrange(Variable) |>
  group_by(Variable) |>
  ggplot() +
  geom_line(aes(x = fecha, y = Valor), size=0.8)  +
  geom_rect(data = fechas_recesion, aes(xmin = inicio, xmax = fin, ymin = -Inf, ymax = Inf), fill = "gray", alpha = 0.2) +
  facet_wrap(~Variable, scales='free', ncol = 3, labeller = labeller(Variable = variable_labels)) +
  theme_classic() + xlab(NULL)  + ylab(NULL) +
  theme(legend.position = "bottom",
        axis.ticks = element_line(colour = "grey70", size = 0.2),
        strip.background = element_blank(),
        title=NULL, 
        legend.title = element_blank(),
        text = element_text(size = 12),
        legend.direction = "horizontal",
        axis.text=element_text(size=11),
        axis.title.x = element_text(size = 12),
        axis.title.y = element_text(size = 12),
        legend.text = element_text(size=12),
        strip.text = element_text(size = 12),
        legend.background = element_rect(fill='transparent'))

7 ago 2024

Simulación, calibración y estimación: ejemplos en AR(1) en R

 Las palabras simular, estimar, calibrar e identificar, aparecen de forma recurrente en la economía aplicada. Estas representan una extensión de la forma de pensar y el desarrollo de aplicaciones teóricas.  Es frecuente que la identificación y calibración se tomen como sub conjuntos de la estimación. Suponga observamos una serie y(t), sobre la que suponemos sigue un proceso ar(1). Por ejemplo:

 y(t)=phi_1* y(t-1)+ e(t)  e(t)~N(0,sigma)

Podemos a partir de ciertos supuestos simular una serie que cumpla con estas características, con el objetivo de estudiar sus propiedades o su comportamiento bajo ciertas modificaciones. Un caso distinto es intentar recuperar los coeficientes phi_1 y sigma de un AR(1), aquí entra la estimación, que permite obtenerlos a partir de algún procedimiento estadístico como el de Mínimo Cuadrados Ordinarios (MCO) o máxima verosimilitud (mle). Mientras que la calibración, también pretende recuperar los coeficientes del modelo, pero a partir de suposiciones o conocimientos previos, buscando que el valor calibrado permita obtener una variable y*(t) parecida al valor observado. 

 1.       Simular

 En la siguiente entrada se simula en R un autoregresivo ar(1):

 y(t)=0.8* y(t-1)+ e(t)  e(t)~N(0,1)

 Se muestra que la simulación de series temporales, y entre calibrar y estimar un modelo. “Simular datos implica generar una serie temporal sintética a partir de un modelo AR(1) con parámetros conocidos” (ChatGPT, 2024).

 # Cargar las librerías necesarias

library(ggplot2)
library(dplyr)
library(tidyr)
library(stats4)
 
# Simular ---------------------
# Parámetros del modelo AR(1)
phi <- 0.8
sigma <- 1
n <- 100
 
# Simular la serie temporal
set.seed(2)
y <- numeric(n)
y[1] <- rnorm(1, mean = 0, sd = sigma)
 
for (t in 2:n) {
  y[t] <-  phi * y[t-1] + rnorm(1, mean = 0, sd = sigma)
}
 
# Crear una secuencia de fechas
fechas <- seq.Date(from = as.Date("2000-01-01"), by = "days", length.out = n)
 
# Crear un data frame con la serie temporal simulada
data <- data.frame(fecha = fechas, y = y)
 
ggplot(data, aes(fechas, y)) +
  geom_line() +
  theme_minimal()

2.       Calibrar

“Calibrar un modelo implica ajustar los parámetros del modelo basándose en conocimientos previos o estimaciones empíricas sin realizar un proceso formal de estimación. Es una forma de "ajustar" el modelo para que sea razonable para la situación específica. La calibración se refiere ajustar los parámetros del modelo basándose en conocimientos previos o estimaciones empíricas sin un proceso formal de estimación. Utiliza datos observados pero no sigue un método estadístico forma” (ChatGPT, 2024).

En la práctica, consiste en seleccionar un conjunto de parámetros de preferencia a partir de las referencias disponibles en la teoría económica, con la intención de que los modelos imiten alguna característica histórica de los datos (Hoover, 1995). Es decir, “La calibración se realiza con mayor frecuencia probando distintos valores para los parámetros hasta que el modelo logre predicciones con la menor desviación posible de los datos o reproduzca otras características empíricas” (Stackexchange, 2020). Los modelos calibrados son una herramienta importante de la investigación económica, esta herramienta ha surgido como evolución y extensión de la capacidad de los economistas para teorizar (Cooley, 1997).

# Serie temporal observada (ejemplo)
y_obs <- y
 
# Calibración: Asumir un valor razonable para phi
phi_calibrado <- 0.8
 
phi_calibrado <- 0.8
y_calibrado <- numeric(n)
y_calibrado[1] <- y[1]
 
for (t in 2:n) {
  y_calibrado[t] <- phi_calibrado * y_calibrado[t-1] + rnorm(1, mean = 0, sd = sigma)
}
 
data$y_calibrado <- y_calibrado
 
ggplot(data) +
  geom_line(aes(fechas, y, color = "Obs")) +
  geom_line(aes(fechas, y_calibrado, color = "Calibrado")) +
  theme_minimal()

 

Algunas recomendaciones identificadas en la literatura:

 ·         No justificar el uso solo porque otros autores lo han utilizado (Cooley, 1997).

 3.       Estimar

 La estimación toma los datos como dados y los utilizan para determinar los parámetros del modelo a partir de un estadístico (que es una función de la muestra), buscando que este sea insesgado, consistente y eficiente. En este procedimiento, el valor de un estadístico se utiliza para estimar un parámetro, por tanto, la estimación “utiliza métodos estadísticos formales (como MLE) para determinar los parámetros del modelo a partir de los datos observados. Es un enfoque más riguroso que la calibración y proporciona estimaciones con propiedades estadísticas deseables” (ChatGPT, 2024). En otras palabras, se utiliza un procedimiento estadístico formal para la estimación de los coeficientes del modelo.

 # Estimación usando MLE
library(stats4)
 
# Log-verosimilitud de un modelo AR(1)
logLik_AR1 <- function(phi, sigma) {
  n <- length(y_obs)
  eps <- numeric(n)
  eps[1] <- y_obs[1] # inicializamos el primer error
 
  for (t in 2:n) {
    eps[t] <- y_obs[t] - phi * y_obs[t-1]
  }
 
  logLik <- -0.5 * n * log(2 * pi * sigma^2) - sum(eps^2) / (2 * sigma^2)
  return(logLik)
}
 
# Función de verosimilitud negativa para optimización
negLogLik_AR1 <- function(phi, sigma) {
  -logLik_AR1(phi, sigma)
}
 
# Optimizar para encontrar los parámetros MLE
mle_fit <- mle(negLogLik_AR1, start = list(phi = 0.5, sigma = 1))
 
# Resultados de la estimación
summary(mle_fit)
 
Maximum likelihood estimation
 
Call:
mle(minuslogl = negLogLik_AR1, start = list(phi = 0.5, sigma = 1))
 
Coefficients:
       Estimate Std. Error
phi   0.7218984 0.06979479
sigma 1.1476188 0.08114858
 
-2 log L: 311.3256

# -------------------------------------------------------------------------------------
# Obtener los parámetros estimados
phi_estimado <- coef(mle_fit)["phi"]
sigma_estimado <- coef(mle_fit)["sigma"]
 
# Generar la serie temporal con los parámetros estimados
y_estimado <- numeric(n)
y_estimado[1] <- y[1]
 
for (t in 2:n) {
  y_estimado[t] <- phi_estimado * y_estimado[t-1] + rnorm(1, mean = 0, sd = sigma_estimado)
}
 
data$y_estimado <- y_estimado
 
# Graficar los datos simulados, calibrados y estimados
data_long <- data %>%
  pivot_longer(cols = c(y, y_calibrado, y_estimado), names_to = "serie", values_to = "valor")
 
ggplot(data_long, aes(x = fecha, y = valor, color = serie)) +
  geom_line(size = 0.7) +
  theme_minimal() +
  labs(title = "Simulación, Calibración y Estimación de un Modelo AR(1)",
       x = "Fecha", y = "Valor",
       color = "Serie") +
scale_color_manual(values = c("y" = "black", "y_calibrado" = "green", "y_estimado" = "red")) +
  theme(plot.title = element_text(hjust = 0.5),
        legend.position = "bottom")

Bibliography

Cooley, T. (1997). Calibrated Models. University of Rochester.

Hoover, K. (1995). Facts and artifacts: calibration and the empirical assessment of real-business-cycle models. Oxford Economic Papers 47 (1), 24-44.

 

Estimación del modelo HP mediante máxima verosimilitud

El filtro de Hodrick–Prescott (HP) se utiliza ampliamente para descomponer una serie macroeconómica en un componente cíclico y transitorio. ...