1 Introdução

A previsão de curto prazo do IPCA é de interesse não apenas do mercado financeiro, mas também e, principalmente, das autoridades monetárias. Nesta publicação, exploramos uma série de modelos com o objetivo de estimar a variação do IPCA para o mês seguinte.

Os modelos desenvolvidos utilizam apenas as variáveis IPCA e IPCA-15. Como o IPCA-15 é divulgado cerca de 15 dias antes do IPCA e representa uma prévia da inflação oficial, sua dinâmica conjunta com o IPCA pode capturar parte relevante da trajetória dos preços ao longo do mês — o que o torna um excelente candidato para modelos preditivos.

Inicialmente, estimamos diferentes modelos individuais. Em seguida, combinamos essas previsões por meio de métodos estatísticos — como média simples, regressão linear, variância mínima e LAD — de modo a obter previsões mais robustas. As estimações são acompanhadas por métricas de desempenho, e ao final, apresentamos a projeção pontual de inflação com base no melhor modelo identificado.

2 Pacotes e Funções Auxiliares

# Manipulação
library(dplyr)
library(tidyr)
library(lubridate)
library(purrr)

# Visualização
library(ggplot2)
library(scales)

# Modelagem
library(forecast)
library(quantreg)
library(MASS)

# Dados do Banco Central
library(rbcb)

# Métricas
rmse <- function(obs, pred) sqrt(mean((obs - pred)^2, na.rm = TRUE))
mae  <- function(obs, pred) mean(abs(obs - pred), na.rm = TRUE)

theme_base <- theme_minimal() + theme(legend.position = "bottom")

3 Aquisição e Preparação dos Dados

ipca   <- get_series(433,  start_date = "2004-01-01", end_date = "2025-05-31") %>% rename(data = date, ipca = 2)
ipca15 <- get_series(7478, start_date = "2004-01-01", end_date = "2025-06-30") %>% rename(data = date, ipca15 = 2)

base <- full_join(ipca, ipca15, by = "data") %>%
  arrange(data) %>%
  mutate(ipca_lag1 = lag(ipca)) %>%
  filter(data <= as.Date("2025-05-31")) %>%
  drop_na()

4 Estimação dos Modelos Individuais

Antes de recorrer a modelos combinados, estimamos quatro abordagens individuais para previsão do IPCA, todas explorando diferentes maneiras de incorporar o IPCA-15 e o próprio histórico do IPCA como variáveis explicativas:

-Modelo 1 — Média Ponderada: uma forma simples e intuitiva de previsão que considera 50% do IPCA-15 e 50% do valor defasado do IPCA. A suposição aqui é que a inflação do mês corrente pode ser interpretada como um ponto médio entre a prévia e o valor anterior.

\[ \widehat{IPCA}_t = 0{,}5 \cdot IPCA15_t + 0{,}5 \cdot IPCA_{t-1} \] -Modelo 2 — Regressão Linear I: modelo clássico de regressão múltipla onde o IPCA é explicado linearmente pelo IPCA-15 e pelo IPCA defasado. Essa abordagem permite identificar relações lineares sistemáticas entre as variáveis, ajustando coeficientes com base na série histórica.

\[ \widehat{IPCA}_t = \beta_0 + \beta_1 \cdot IPCA15_t + \beta_2 \cdot IPCA_{t-1} \] -Modelo 3 — ARIMAX: modelo autorregressivo integrado com média móvel e regressores exógenos (neste caso, o IPCA-15). Ele capta a estrutura temporal do IPCA ao longo do tempo enquanto incorpora o efeito contemporâneo do IPCA-15 na previsão.

\[ IPCA_t = \alpha + \sum_{i=1}^{p} \phi_i \cdot IPCA_{t-i} + \sum_{j=1}^{q} \theta_j \cdot \varepsilon_{t-j} + \gamma \cdot IPCA15_t + \varepsilon_t \] -Modelo 4 — Regressão Linear II: variante da regressão linear que substitui a defasagem do IPCA por um diferencial entre IPCA-15 e IPCA defasado, interpretado como uma proxy de aceleração ou desaceleração mensal da inflação. Essa estrutura busca capturar efeitos não lineares ou mudanças abruptas no comportamento dos preços.

\[ \widehat{IPCA}_t = \beta_0 + \beta_1 \cdot IPCA15_t + \beta_2 \cdot (IPCA15_t - IPCA_{t-1}) \] Cada um desses modelos foi avaliado com base em métricas de erro fora da amostra — RMSE e MAE — cujos resultados são comparados na tabela a seguir.

# Modelo 1: Média Ponderada
base <- base %>%
  mutate(pred1 = 0.5 * ipca15 + 0.5 * ipca_lag1,
         erro1 = ipca - pred1)

# Modelo 2: Regressão Linear I
reg2 <- lm(ipca ~ ipca15 + ipca_lag1, data = base)
base <- base %>%
  mutate(pred2 = predict(reg2, newdata = base),
         erro2 = ipca - pred2)

# Modelo 3: ARIMAX
ts_ipca   <- ts(base$ipca,   start = c(year(min(base$data)), month(min(base$data))), frequency = 12)
ts_ipca15 <- ts(base$ipca15, start = c(year(min(base$data)), month(min(base$data))), frequency = 12)

modelo_arimax <- auto.arima(ts_ipca, xreg = ts_ipca15)
pred3 <- forecast(modelo_arimax, xreg = ts_ipca15)$mean
base <- base %>%
  mutate(pred3 = as.numeric(pred3),
         erro3 = ipca - pred3)

# Modelo 4: Regressão Linear II
base <- base %>%
  mutate(delta = ipca15 - ipca_lag1)

reg_delta <- lm(ipca ~ ipca15 + delta, data = base)
base <- base %>%
  mutate(pred4 = predict(reg_delta, newdata = base),
         erro4 = ipca - pred4)


avaliacao <- tibble(
  Modelo = c("Média Ponderada", "Regressão Linear I", "ARIMAX", "Regressão Linear II"),
  RMSE = c(
    rmse(base$ipca, base$pred1),
    rmse(base$ipca, base$pred2),
    rmse(base$ipca, base$pred3),
    rmse(base$ipca, base$pred4)
  ),
  MAE = c(
    mae(base$ipca, base$pred1),
    mae(base$ipca, base$pred2),
    mae(base$ipca, base$pred3),
    mae(base$ipca, base$pred4)
  )
)

print(avaliacao %>% arrange(RMSE))
## # A tibble: 4 × 3
##   Modelo               RMSE   MAE
##   <chr>               <dbl> <dbl>
## 1 Regressão Linear I  0.154 0.112
## 2 Regressão Linear II 0.154 0.112
## 3 ARIMAX              0.176 0.129
## 4 Média Ponderada     0.232 0.174

5 Combinação de Previsões

Após estimar os modelos individuais, aplicamos diferentes técnicas de combinação com o objetivo de obter previsões mais robustas, reduzindo o risco associado a dependência de um único modelo. As abordagens utilizadas são descritas a seguir:

\[ \widehat{IPCA}_t^{(media)} = \frac{1}{4} \left( \widehat{IPCA}_t^{(1)} + \widehat{IPCA}_t^{(2)} + \widehat{IPCA}_t^{(3)} + \widehat{IPCA}_t^{(4)} \right) \]

\[ IPCA_t = \alpha + \beta_1 \cdot \widehat{IPCA}_t^{(1)} + \beta_2 \cdot \widehat{IPCA}_t^{(2)} + \beta_3 \cdot \widehat{IPCA}_t^{(3)} + \varepsilon_t \]

\[ w = \frac{\Sigma^{-1} \cdot \mathbf{1}}{\mathbf{1}^\top \cdot \Sigma^{-1} \cdot \mathbf{1}} \]

onde \(\Sigma\) é a matriz de covariância dos erros de previsão. A combinação final é dada por:

\[ \widehat{IPCA}_t^{(VM)} = w_1 \cdot \widehat{IPCA}_t^{(1)} + w_2 \cdot \widehat{IPCA}_t^{(2)} + w_3 \cdot \widehat{IPCA}_t^{(3)} \] Cada técnica de combinação foi avaliada com base nas métricas RMSE e MAE, e os resultados são comparados à frente com os modelos individuais.

# Média Simples
base <- base %>%
  mutate(pred_media = rowMeans(across(c(pred1, pred2, pred3, pred4))),
         erro_media = ipca - pred_media)

avaliacao <- avaliacao %>% add_row(
  Modelo = "Média Simples das Previsões",
  RMSE = rmse(base$ipca, base$pred_media),
  MAE = mae(base$ipca, base$pred_media)
)

# OLS
reg_ols <- lm(ipca ~ pred1 + pred2 + pred3, data = base)
base <- base %>%
  mutate(pred_ols = predict(reg_ols), erro_ols = ipca - pred_ols)

avaliacao <- avaliacao %>% add_row(
  Modelo = "Combinação por Regressão (OLS)",
  RMSE = rmse(base$ipca, base$pred_ols),
  MAE = mae(base$ipca, base$pred_ols)
)

# LAD
reg_lad <- rq(ipca ~ pred1 + pred2 + pred3, data = base, tau = 0.5)
base <- base %>%
  mutate(pred_lad = predict(reg_lad), erro_lad = ipca - pred_lad)

avaliacao <- avaliacao %>% add_row(
  Modelo = "Combinação Robusta (LAD)",
  RMSE = rmse(base$ipca, base$pred_lad),
  MAE = mae(base$ipca, base$pred_lad)
)

# Variância Mínima
residuos <- base[, c("erro1", "erro2", "erro3")]
cov_erro <- cov(residuos)
inv_cov <- solve(cov_erro)
um <- rep(1, ncol(cov_erro))
pesos_vm <- inv_cov %*% um / as.numeric(t(um) %*% inv_cov %*% um)

previsoes_mat <- as.matrix(base[, c("pred1", "pred2", "pred3")])
base <- base %>%
  mutate(pred_vm = as.numeric(previsoes_mat %*% pesos_vm),
         erro_vm = ipca - pred_vm)

avaliacao <- avaliacao %>% add_row(
  Modelo = "Combinação por Variância Mínima",
  RMSE = rmse(base$ipca, base$pred_vm),
  MAE = mae(base$ipca, base$pred_vm)
)

6 Avaliação Comparativa de Desempenho

Após estimar os modelos individuais e as combinações alternativas, realizamos uma avaliação quantitativa de desempenho com base nas métricas RMSE (Root Mean Squared Error) e MAE (Mean Absolute Error). Essas medidas mensuram, respectivamente, o erro quadrático médio e o erro absoluto médio entre as previsões geradas e os valores efetivamente observados do IPCA.

O objetivo desta etapa é identificar quais modelos, ou combinações de modelos, apresentam maior capacidade preditiva dentro da amostra. A ordenação dos resultados é feita com base no menor RMSE — quanto menor o valor, maior a acurácia da previsão.

A tabela abaixo resume as métricas obtidas por cada abordagem considerada:

avaliacao %>%
  arrange(RMSE)
## # A tibble: 8 × 3
##   Modelo                           RMSE   MAE
##   <chr>                           <dbl> <dbl>
## 1 Combinação por Regressão (OLS)  0.154 0.112
## 2 Combinação por Variância Mínima 0.154 0.112
## 3 Regressão Linear I              0.154 0.112
## 4 Regressão Linear II             0.154 0.112
## 5 Combinação Robusta (LAD)        0.154 0.111
## 6 Média Simples das Previsões     0.167 0.121
## 7 ARIMAX                          0.176 0.129
## 8 Média Ponderada                 0.232 0.174

7 Previsão Pontual do IPCA

Após a comparação entre os modelos individuais e suas combinações, identificamos que a abordagem com melhor desempenho preditivo foi a combinação robusta por regressão LAD (Least Absolute Deviations). Essa técnica, ao minimizar os desvios absolutos em vez dos quadráticos, oferece maior resistência a outliers e maior estabilidade em relação a distorções na série.

Com base nesse modelo, foi gerada uma previsão pontual para o IPCA de junho de 2025. O valor do IPCA-15 de junho, disponível até a data da projeção, serviu como principal insumo contemporâneo. As previsões individuais dos três modelos base (média ponderada, regressão linear e ARIMAX) foram combinadas de forma robusta segundo os coeficientes estimados via LAD, resultando na previsão final.

A estimativa obtida representa, portanto, a melhor síntese da informação contida nos modelos construídos ao longo do estudo — e será destacada graficamente na próxima seção.

# Obtenção da última observação do IPCA-15
ipca15_jun <- ipca15 %>%
  filter(data == max(data)) %>%
  pull(ipca15)

# Último IPCA
ipca_maio <- tail(base$ipca, 1)

# Previsões individuais
pred1_jun <- 0.5 * ipca15_jun + 0.5 * ipca_maio
pred2_jun <- predict(reg2, newdata = tibble(ipca15 = ipca15_jun, ipca_lag1 = ipca_maio))
pred3_jun <- forecast(modelo_arimax, xreg = matrix(ipca15_jun, ncol = 1), h = 1)$mean

# Previsão combinada via LAD
pred_lad_jun <- coef(reg_lad)["(Intercept)"] +
                coef(reg_lad)["pred1"] * pred1_jun +
                coef(reg_lad)["pred2"] * pred2_jun +
                coef(reg_lad)["pred3"] * pred3_jun

# Resultado
round(pred_lad_jun,2)
##       Jun
## 2025 0.27

8 Plotagem da Previsão

Como se observa no gráfico abaixo, a previsão gerada pelo modelo LAD (Combinação Robusta) apresenta elevada aderência à trajetória histórica do IPCA. A série de preços observados é bem acompanhada pela linha de previsão, tanto em períodos de estabilidade quanto em momentos de maior volatilidade.

Destaca-se no gráfico a previsão pontual para junho de 2025. A estimativa foi construída com base nas previsões individuais combinadas segundo os coeficientes otimizados do modelo LAD.

O modelo LAD demonstrou superioridade nas métricas estatísticas (RMSE e MAE) em relação às demais abordagens, o que reforça sua escolha como estratégia final de previsão.

# 📌 Dados da previsão
data_jun <- max(ipca15$data)
previsao_final <- round(as.numeric(pred_lad_jun), 2)

# 📊 Organizando dados
dados_lad <- base %>% dplyr::select(data, ipca, pred_lad)
jun25 <- tibble(data = data_jun, ipca = NA, pred_lad = previsao_final)
dados_lad_plot <- bind_rows(dados_lad, jun25)

# 🎨 Gráfico
ggplot(dados_lad_plot, aes(x = data)) +
  geom_line(aes(y = ipca, color = "IPCA Observado"), linewidth = 1.1) +
  geom_line(aes(y = pred_lad, color = "Previsão"), linetype = "dashed", linewidth = 1.1) +
  geom_point(data = jun25, aes(y = pred_lad), size = 3, shape = 21,
             fill = "red", color = "white", stroke = 1.2) +
geom_text(
  data = jun25,
  aes(y = pred_lad + 0.04, label = format(previsao_final, nsmall = 2)),
  hjust = -0.12, vjust = 0.75, size = 4.2, fontface = "bold", color = "black"
) +
  scale_color_manual(values = c(
    "IPCA Observado" = "black",
    "Previsão" = "#D55E00"
  )) +
  scale_x_date(
    date_breaks = "3 years", date_labels = "%Y",
    limits = c(min(dados_lad$data), data_jun + 360)
  ) +
  labs(
    title = "IPCA Observado vs Previsão",
    subtitle = paste0("Previsão para ", format(data_jun, "%b/%y")),
    x = "Data", y = "IPCA mensal (%)", color = NULL
  ) +
  theme_base

ggsave(
  filename = "grafico_ipca_lad.png",
  plot = last_plot(),
  width = 8, height = 5.5, units = "in",
  dpi = 1200
)


ggsave(
  filename = file.path(tempdir(), "grafico_ipca_lad.pdf"),
  plot = last_plot(), width = 8, height = 5.5, units = "in", dpi = 1200
)