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.
# 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")
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()
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
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 \]
Combinação Robusta (LAD): similar à abordagem OLS, mas utiliza regressão quantílica (mediana condicional) com \(\tau = 0{,}5\). Essa técnica é menos sensível a outliers e pode melhorar a previsão em situações com maior assimetria ou heterocedasticidade nos erros.
Combinação por Variância Mínima: considera os erros dos três primeiros modelos e busca a combinação linear com menor variância de previsão. Os pesos são calculados de forma ótima a partir da matriz de covariância dos resíduos:
\[ 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)
)
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
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
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
)