1. Simulando la data
La siguiente entrada muestra un ejemplo de como estimar un modelo de frecuencia mixta. Puntualmente simulamos una serie de consumo trimestral que queremos estimar en una regresión contra una serie de ventas mensuales. Como tal, la diferencia en el numero de observaciones limita la posibilidad de estimar directamente un modelo de regresión tradicional -aquí suponemos que las series son estacionarias, proceso obligatorio para estimar una regresión entre series temporales-. Todo el ejercicio se realiza en Package ‘midasr’ (Zemlys, 2022).
En primer lugar, simulamos la serie de consumo:
library(ggplot2)
library(forecast)
library(midasr)
# Definición de parámetros
set.seed(1234)
trend <- 0.5 # Tendencia de la serie
seasonality <- 0.2 # Estacionalidad trimestral
n <- 22*4 # Número de trimestres a simular (22 años)
consumo <- rnorm(n, mean = trend + seasonality * rep(1:4, length.out = n))
consumo_trimestral <- ts(consumo, frequency = 4, start = 2000)
Posteriormente
simulamos la serie de ventas, teniendo presente que el número de observaciones
de la variable mensual, debe coincidir con las necesarias para equiparar las
observaciones de mi serie en frecuencia más alta. Puntualmente, si tenemos una
serie trimestral de 10 años, entonces necesitaríamos 4*10 observaciones de mi
serie en menor frecuencia.
# Definición de parámetros
trend <- 0.8 # Tendencia de la serie
seasonality <- c(0.5, 0.3, 0.2) # Estacionalidad mensual (ejemplo: enero, febrero, marzo)
n2 <- (n/4)*12 # Número de meses a simular
ventas_mensuales <- numeric(n)
for (i in 1:n2) {
ventas_mensuales[i] <- rnorm(1, mean = trend + seasonality[(i - 1) %% length(seasonality) + 1])
}
2. Estimando el modelo midas
Ahora que hemos
simulado nuestras series, podemos estimar nuestro modelo en frecuencia mixta.
Primero utilizamos una ventana de datos para poder comparar los valores
proyectados con los valores observados. Luego usamos la función midas_r para estimar
el modelo en frecuencia mixta. Note aquí que la clase está en la función fmls
que realiza un collapse de la data en alta frecuencia para que este coincida en
el total de observaciones. Dentro de esta función se coloca la variable independiente,
el numero de rezagos a incluir, la cantidad de veces que esta contenida mi
serie de baja frecuencia en la de alta (trimestral y mensual 3; anual y mensual
12…)…
x_q <- window(ventas_mensuales, end = c(2019, 12))
y_c <- window(consumo_trimestral, end = c(2019, 4))
aa <- round(length(x_q)/length(y_c))
Start = 2000(4), End = 2019(4)
model: y_c ~ trend + fmls(x_q, 11, aa, nealmon)
(Intercept) trend x_q1 x_q2 x_q3
0.50057 0.01001 -0.12472 20.67112 -0.84271
x
[1] 1 2 3 4 5 6 7 8 9 10 11 12
X.0/m
[1,] 3
[2,] 6
[3,] 9
[4,] 12
X.0/m X.1/m
[1,] 3 2
[2,] 6 5
[3,] 9 8
[4,] 12 11
]
Ahora, solo témenos que considerar cuales son los valores futuros de las variables independientes. Esto con el fin de poder crear pronósticos condicionados.
##New trend values
n.valid <- 8
xn <- forecast::snaive(x_q,aa*n.valid)$mean
trendn <- length(y_c) + 1:n.valid
Finalmente, usamos la función forecast para obtener los valores predichos para mi variable independiente.
fh_midas_1
Qtr1 Qtr2 Qtr3 Qtr4
2020 1.213594 1.255759 1.216617 1.158818
2021 1.253628 1.295793 1.256651 1.198851
mls(y_c, 1:2, 1, "*") +
fmls(x_q, 12, aa, nealmon),
start = list(x_q = rep(0, 3)))
Start = 2001(3), End = 2019(4)
model: y_c ~ trend + mls(y_c, 1:2, 1, "*") + fmls(x_q, 18, aa, nealmon)
(Intercept) trend y_c1 y_c2 x_q1 x_q2 x_q3
0.531114 0.009247 0.105423 -0.017154 -0.214118 2.527028 -0.111902
fh_midas_2
Qtr1 Qtr2 Qtr3 Qtr4
2020 1.223314 1.274915 1.186098 1.196951
2021 1.278432 1.315320 1.226402 1.237496
fh_arima <- forecast::forecast(auto.arima(y_c, stepwise = FALSE))
obs_data <- window(consumo_trimestral, start = c(2020, 1))
y_obs = c(y_c, rep(NA, n.valid)),
f.midas1 = c(rep(NA, length(y_c)-1), tail(y_c,1), fh_midas_1$mean),
f.midas2 = c(rep(NA, length(y_c)-1), tail(y_c,1), fh_midas_2$mean),
fh_arima = c(rep(NA, length(y_c)-1), tail(y_c,1), fh_arima$mean),
obs = c(rep(NA, length(y_c)-1), tail(y_c,1), obs_data),
fecha = time(consumo_trimestral)
)
ggplot() +
geom_line(aes(fecha,y_obs,colour="Obs"), size=1) +
geom_line(aes(fecha, obs,colour="Obs1"),linetype = 2, size=1) +
geom_line(aes(fecha, f.midas1,colour="xMidas"),linetype = 3, size=1) +
geom_line(aes(fecha, f.midas2,colour="xArMidas"), linetype = 3, size=1) +
geom_line(aes(fecha, fh_arima,colour="Arima"),linetype = 3, size=1) +
theme_classic() +
scale_color_manual(name = "Serie", values = c("Obs" = "black", "Obs1" = "black", "xMidas" = "darkred", "xArMidas" = "darkblue", "Arima"="darkgreen")) +
theme(legend.position = "bottom")