Este relatório estima a Regra de Taylor com suavização (interest rate smoothing) para o Brasil no período 1999 T3 – 2025 T4. A equação de estimação é:
\[i_t = \alpha + \rho\,i_{t-1} + \gamma_\pi\,(\pi_t - \pi^*_t) + \gamma_y\,\tilde{y}_t + \varepsilon_t\]
com \(\alpha=(1-\rho)\,i^*\), \(\gamma_\pi=(1-\rho)\,\phi_\pi\) e \(\gamma_y=(1-\rho)\,\phi_y\). Após a estimação por MQO recuperamos os parâmetros estruturais \(\rho\), \(i^*\), \(\phi_\pi\) e \(\phi_y\).
Dados coletados da API do SGS/BCB via pacote
GetBCBData.
| Variável | Descrição | Série SGS |
|---|---|---|
| i_t | Selic over diária (% a.d.) | 11 |
| pi_t | IPCA acumulado 12 meses, mensal (% a.a.) | 13522 |
| Y_t | PIB — índice de volume encadeado, trim. | 22099 |
A meta \(\pi^*_t\) é construída manualmente a partir do histórico oficial do BCB.
ini <- as.Date("1999-01-01")
fim <- as.Date("2025-12-31")
df_raw <- gbcbd_get_series(
id = c(selic = 11, ipca12 = 13522, pib = 22099),
first.date = ini,
last.date = fim,
be.quiet = TRUE,
use.memoise = FALSE
)
selic_d <- df_raw |> filter(id.num == 11) |> select(date = ref.date, selic = value)
ipca12 <- df_raw |> filter(id.num == 13522) |> select(date = ref.date, ipca12 = value)
pib_raw <- df_raw |> filter(id.num == 22099) |> select(date = ref.date, pib = value)A série 11 está em % a.d. Anualizamos cada observação diária e depois tomamos a média aritmética simples das observações dentro do trimestre:
\[i^{\text{a.a.}}_d = \bigl[(1 + i^{\text{a.d.}}_d / 100)^{252} - 1\bigr]\times 100.\]
Valor do último mês de cada trimestre (março, junho, setembro, dezembro):
Série anual construída a partir do histórico oficial do CMN/BCB (https://www.bcb.gov.br/controleinflacao/historicometas).
Nota (2003–2004): usamos as metas ajustadas da Carta Aberta de 21/01/2003 (8,5% para 2003 e 5,5% para 2004), que foram as metas efetivamente perseguidas pelo BCB. As metas originais (4,0% e 3,75%) estão comentadas para robustez.
metas <- tibble::tribble(
~ano, ~pi_star,
1999, 8.00, 2000, 6.00, 2001, 4.00, 2002, 3.50,
2003, 8.50, # meta ajustada; original = 4.00
2004, 5.50, # meta ajustada; original = 3.75
2005, 4.50, 2006, 4.50, 2007, 4.50, 2008, 4.50,
2009, 4.50, 2010, 4.50, 2011, 4.50, 2012, 4.50,
2013, 4.50, 2014, 4.50, 2015, 4.50, 2016, 4.50,
2017, 4.50, 2018, 4.50, 2019, 4.25, 2020, 4.00,
2021, 3.75, 2022, 3.50, 2023, 3.25, 2024, 3.00,
2025, 3.00 # meta contínua — Decreto 12.079/2024
)O PIB trimestral é dessazonalizado (X-13ARIMA-SEATS via
seasonal; fallback por STL), tomamos o logaritmo e
aplicamos o filtro HP: \(\tilde{y}_t =
100\,(\ln Y_t - \ln Y^*_t)\).
pib_q <- pib_raw |>
mutate(tri = as.yearqtr(date)) |>
arrange(tri)
gdp_ts <- ts(pib_q$pib,
start = c(year(min(pib_q$date)), quarter(min(pib_q$date))),
frequency = 4)
gdp_sa <- tryCatch({
sa <- seasonal::seas(gdp_ts)
seasonal::final(sa)
}, error = function(e) {
message("X-13 indisponível — usando STL.")
st <- stl(log(gdp_ts), s.window = "periodic")
exp(log(gdp_ts) - st$time.series[, "seasonal"])
})
log_gdp <- log(as.numeric(gdp_sa))
hp <- mFilter::hpfilter(log_gdp, freq = 1600, type = "lambda")
hiato_vec <- 100 * (log_gdp - as.numeric(hp$trend))
hiato_tri <- tibble(tri = pib_q$tri, hiato = hiato_vec)base <- selic_tri |>
inner_join(ipca_tri, by = "tri") |>
inner_join(hiato_tri, by = "tri") |>
mutate(ano = as.integer(floor(as.numeric(tri)))) |>
left_join(metas, by = "ano") |>
mutate(desvio = pi - pi_star) |>
arrange(tri) |>
mutate(i_lag = lag(i)) |>
filter(tri >= as.yearqtr("1999 Q3"),
tri <= as.yearqtr("2025 Q4")) |>
drop_na(i, i_lag, desvio, hiato)
kb(head(base |> mutate(tri = as.character(tri)), 6),
cap = "Primeiras observações do painel (1999 T3 …).")| tri | i | pi | hiato | ano | pi_star | desvio | i_lag |
|---|---|---|---|---|---|---|---|
| 1999 Q3 | 19.89 | 6.25 | -0.32 | 1999 | 8 | -1.75 | 28.19 |
| 1999 Q4 | 18.95 | 8.94 | 0.00 | 1999 | 8 | 0.94 | 19.89 |
| 2000 Q1 | 18.88 | 6.92 | -0.01 | 2000 | 6 | 0.92 | 18.95 |
| 2000 Q2 | 18.39 | 6.51 | 0.99 | 2000 | 6 | 0.51 | 18.88 |
| 2000 Q3 | 16.64 | 7.77 | 1.75 | 2000 | 6 | 1.77 | 18.39 |
| 2000 Q4 | 16.43 | 5.97 | 2.10 | 2000 | 6 | -0.03 | 16.64 |
base |>
mutate(data = as.Date(tri)) |>
select(data, `Selic (i)` = i, `IPCA 12m` = pi, `Meta (π*)` = pi_star) |>
pivot_longer(-data, names_to = "série", values_to = "valor") |>
ggplot(aes(data, valor, colour = série)) +
geom_line(linewidth = 0.8) +
scale_x_date(date_breaks = "3 years", date_labels = "%Y") +
labs(x = NULL, y = "% a.a.", colour = NULL) +
theme(legend.position = "bottom")Selic, IPCA 12m e meta de inflação (% a.a.).
Episódios de afastamento da inflação em relação à meta. A inflação superou significativamente a meta em três grandes momentos: (i) 2002–2003 — crise de confiança pré-eleitoral e forte depreciação cambial (IPCA de 12,5% em 2002 e 9,3% em 2003); (ii) 2015–2016 — recessão e crise fiscal/política, com IPCA de 10,67% em 2015; e (iii) 2021–2022 — choque pós-pandemia de energia, câmbio e commodities (IPCA de 10,1% em 2021). Em cada episódio a Selic respondeu com elevação acentuada. O desvio negativo persistente de 2017–2018 e o vale de 2020 marcam as fases de afrouxamento.
vars <- base |> select(i, i_lag, pi, pi_star, desvio, hiato)
desc <- tibble(
Variável = c("i_t", "i_{t-1}", "pi_t", "pi*_t", "Desvio", "Hiato"),
Média = sapply(vars, mean, na.rm = TRUE),
`Desv.Pad.` = sapply(vars, sd, na.rm = TRUE),
Mínimo = sapply(vars, min, na.rm = TRUE),
Máximo = sapply(vars, max, na.rm = TRUE)
)
kb(desc, cap = "Estatísticas descritivas.")| Variável | Média | Desv.Pad. | Mínimo | Máximo |
|---|---|---|---|---|
| i_t | 12.43 | 4.96 | 1.90 | 26.24 |
| i_{t-1} | 12.55 | 5.18 | 1.90 | 28.19 |
| pi_t | 6.25 | 2.69 | 2.13 | 16.57 |
| pi*_t | 4.50 | 1.15 | 3.00 | 8.50 |
| Desvio | 1.75 | 2.39 | -1.96 | 9.03 |
| Hiato | 0.01 | 1.80 | -10.13 | 3.46 |
| i | i_lag | pi | pi_star | desvio | hiato | |
|---|---|---|---|---|---|---|
| i | 1.00 | 0.96 | 0.55 | 0.46 | 0.40 | -0.08 |
| i_lag | 0.96 | 1.00 | 0.43 | 0.55 | 0.22 | -0.14 |
| pi | 0.55 | 0.43 | 1.00 | 0.46 | 0.90 | -0.08 |
| pi_star | 0.46 | 0.55 | 0.46 | 1.00 | 0.04 | -0.12 |
| desvio | 0.40 | 0.22 | 0.90 | 0.04 | 1.00 | -0.04 |
| hiato | -0.08 | -0.14 | -0.08 | -0.12 | -0.04 | 1.00 |
modelsummary(
m_full,
coef_rename = c("(Intercept)" = "Constante (α)",
"i_lag" = "i(t-1) — ρ̂",
"desvio" = "π - π* — γ̂_π",
"hiato" = "Hiato ỹ — γ̂_y"),
gof_map = c("nobs","r.squared","adj.r.squared"),
stars = TRUE,
title = "Regra de Taylor — MQO, amostra completa (1999 T3 – 2025 T4)",
notes = "* p<0,1 ; ** p<0,05 ; *** p<0,01. Erros-padrão entre parênteses."
)| (1) | |
|---|---|
| + p < 0.1, * p < 0.05, ** p < 0.01, *** p < 0.001 | |
| * p<0,1 ; ** p<0,05 ; *** p<0,01. Erros-padrão entre parênteses. | |
| Constante (α) | 0.627* |
| (0.267) | |
| i(t-1) — ρ̂ | 0.882*** |
| (0.020) | |
| π - π* — γ̂_π | 0.415*** |
| (0.043) | |
| Hiato ỹ — γ̂_y | 0.169** |
| (0.057) | |
| Num.Obs. | 106 |
| R2 | 0.958 |
| R2 Adj. | 0.956 |
recuperar <- function(m) {
b <- coef(m)
rho <- unname(b["i_lag"])
c(rho = rho,
i_star = unname(b["(Intercept)"]) / (1 - rho),
phi_pi = unname(b["desvio"]) / (1 - rho),
phi_y = unname(b["hiato"]) / (1 - rho))
}
est <- recuperar(m_full)
kb(tibble(
Parâmetro = c("ρ (suavização)",
"i* (juro neutro, % a.a.)",
"φ_π (resposta à inflação)",
"φ_y (resposta ao hiato)"),
Estimativa = round(est, 3)
), cap = "Parâmetros estruturais recuperados.")| Parâmetro | Estimativa |
|---|---|
| ρ (suavização) | 0.88 |
| i* (juro neutro, % a.a.) | 5.32 |
| φ_π (resposta à inflação) | 3.52 |
| φ_y (resposta ao hiato) | 1.43 |
(a) Suavização — \(\hat\rho\). O coeficiente estimado é \(\hat\rho = 0.882\), grau elevado (forte suavização). Valores próximos a 1 indicam que o BCB ajusta a Selic de forma gradual e persistente: cada decisão incorpora forte inércia da taxa do trimestre anterior. Esse padrão é consistente com a literatura empírica de política monetária e reflete a preferência por trajetórias suaves que preservam previsibilidade e evitam volatilidade excessiva nos mercados financeiros.
(b) Princípio de Taylor — \(\hat\phi_\pi\). A resposta de longo prazo à inflação é \(\hat\phi_\pi = 3.519\), valor que satisfaz o Princípio de Taylor (\(\phi_\pi > 1\)). Quando \(\phi_\pi > 1\), o banco central eleva a taxa de juros real em resposta a desvios positivos da inflação — condição necessária para a estabilidade nominal e a ancoragem das expectativas. Um valor abaixo de 1 implicaria política monetária acomodatícia e potencialmente desestabilizadora.
(c) Resposta ao hiato — \(\hat\phi_y\). Estima-se \(\hat\phi_y = 1.434\), de sinal positivo — sinal esperado pela teoria e estatisticamente significante (p < 0,05). O sinal positivo é o previsto pelo modelo NK: o BCB tende a elevar os juros quando o produto está acima do potencial (hiato positivo), sinal de pressão de demanda. A magnitude modesta reflete o foco primário do regime de metas na inflação, não no nível de atividade.
(d) Taxa de juros neutra implícita — \(\hat i^*\). A taxa nominal neutra implícita é \(\hat i^* = 5.32\%\) a.a. Como a amostra cobre 1999–2025 — período que inclui anos com Selic acima de 20% — este valor tende a ser elevado sobre a janela completa. Estimativas em subperíodos mais recentes devem mostrar queda gradual, refletindo o processo de desinflação e redução do juro estrutural brasileiro.
base <- base |> mutate(i_hat = predict(m_full), gap = i - i_hat)
base |>
mutate(data = as.Date(tri)) |>
select(data, `Selic efetiva` = i, `Regra estimada` = i_hat) |>
pivot_longer(-data, names_to = "série", values_to = "valor") |>
ggplot(aes(data, valor, colour = série)) +
geom_line(linewidth = 0.8) +
scale_x_date(date_breaks = "3 years", date_labels = "%Y") +
labs(x = NULL, y = "% a.a.", colour = NULL) +
theme(legend.position = "bottom")Selic efetiva vs. taxa prescrita pela regra estimada (valores ajustados do modelo).
A diferença \(i_t - \hat\imath_t\)
(coluna gap) identifica subperíodos em que o BCB operou
acima (postura mais contracionista que o prescrito) ou
abaixo (mais expansionista). Em geral, episódios de
combate à inflação alta tendem a mostrar Selic acima da regra; fases de
afrouxamento agressivo (2012–2013 e 2020) costumam mostrar Selic abaixo.
Comente os subperíodos concretos que aparecerem no seu
gráfico.
base <- base |>
mutate(periodo = case_when(
tri >= as.yearqtr("1999 Q3") & tri <= as.yearqtr("2002 Q4") ~ "I (99-02)",
tri >= as.yearqtr("2003 Q1") & tri <= as.yearqtr("2010 Q4") ~ "II (03-10)",
tri >= as.yearqtr("2011 Q1") & tri <= as.yearqtr("2016 Q4") ~ "III (11-16)",
tri >= as.yearqtr("2017 Q1") & tri <= as.yearqtr("2024 Q4") ~ "IV (17-24)",
TRUE ~ NA_character_
))
m1 <- lm(i ~ i_lag + desvio + hiato, data = filter(base, periodo == "I (99-02)"))
m2 <- lm(i ~ i_lag + desvio + hiato, data = filter(base, periodo == "II (03-10)"))
m3 <- lm(i ~ i_lag + desvio + hiato, data = filter(base, periodo == "III (11-16)"))
m4 <- lm(i ~ i_lag + desvio + hiato, data = filter(base, periodo == "IV (17-24)"))modelsummary(
list("I (99-02)" = m1, "II (03-10)" = m2,
"III (11-16)" = m3, "IV (17-24)" = m4),
coef_rename = c("(Intercept)" = "Constante (α)",
"i_lag" = "i(t-1) (ρ)",
"desvio" = "π - π* (γ_π)",
"hiato" = "Hiato ỹ (γ_y)"),
gof_map = c("nobs","r.squared","adj.r.squared"),
stars = TRUE,
title = "Regra de Taylor por subperíodo (MQO)",
notes = "* p<0,1 ; ** p<0,05 ; *** p<0,01."
)| I (99-02) | II (03-10) | III (11-16) | IV (17-24) | |
|---|---|---|---|---|
| + p < 0.1, * p < 0.05, ** p < 0.01, *** p < 0.001 | ||||
| * p<0,1 ; ** p<0,05 ; *** p<0,01. | ||||
| Constante (α) | 11.689*** | 2.330** | -1.289 | -0.023 |
| (2.456) | (0.767) | (0.888) | (0.223) | |
| i(t-1) (ρ) | 0.317* | 0.784*** | 1.029*** | 0.940*** |
| (0.117) | (0.056) | (0.084) | (0.023) | |
| π - π* (γ_π) | 0.321* | 0.592*** | 0.379*** | 0.360*** |
| (0.127) | (0.108) | (0.094) | (0.033) | |
| Hiato ỹ (γ_y) | -0.524 | 0.349* | 0.289** | 0.063 |
| (0.333) | (0.130) | (0.084) | (0.045) | |
| Num.Obs. | 14 | 32 | 24 | 32 |
| R2 | 0.672 | 0.954 | 0.961 | 0.985 |
| R2 Adj. | 0.574 | 0.949 | 0.955 | 0.983 |
estr_sub <- t(sapply(list(`I`=m1,`II`=m2,`III`=m3,`IV`=m4), recuperar))
kb(as.data.frame(round(estr_sub, 3)),
cap = "Parâmetros estruturais por subperíodo.")| rho | i_star | phi_pi | phi_y | |
|---|---|---|---|---|
| I | 0.32 | 17.10 | 0.47 | -0.77 |
| II | 0.78 | 10.79 | 2.74 | 1.62 |
| III | 1.03 | 44.75 | -13.17 | -10.04 |
| IV | 0.94 | -0.38 | 6.02 | 1.04 |
Comparação entre subperíodos. Avalie na tabela acima: (i) se \(\hat\phi_\pi\) aumentou ao longo do tempo, indicando reação mais intensa à inflação e satisfação mais robusta do Princípio de Taylor — o que sinalizaria amadurecimento institucional do RMI; (ii) se \(\hat\phi_y\) ganhou relevância como estabilizador cíclico; e (iii) se o grau de suavização \(\hat\rho\) variou entre gestões do BCB.
Ressalva: os subperíodos I e III têm poucas observações (~14 e ~24 trimestres), o que amplia os erros-padrão. Os parâmetros estruturais — que dividem por \((1-\hat\rho)\) — podem ficar instáveis quando \(\hat\rho\) é grande.
Com a variável dependente defasada e possível autocorrelação dos resíduos, convém verificar erros-padrão HAC (Newey–West, \(\ell=4\)):
##
## t test of coefficients:
##
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.627365 0.409033 1.5338 0.1281805
## i_lag 0.882043 0.040037 22.0309 < 0.00000000000000022 ***
## desvio 0.415048 0.060921 6.8129 0.0000000006814 ***
## hiato 0.169110 0.049553 3.4127 0.0009235 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Se os erros HAC forem substancialmente maiores que os OLS padrão, a inferência clássica pode estar otimista — vale mencionar isso na discussão.
## Sessão R: 2026-06-03 16:03:37.731824
## R version 4.5.1 (2025-06-13 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 11 x64 (build 26200)
##
## Matrix products: default
## LAPACK version 3.12.1
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] lmtest_0.9-40 sandwich_3.1-1 kableExtra_1.4.0 knitr_1.50
## [5] modelsummary_2.6.0 mFilter_0.1-5 ggplot2_4.0.1 zoo_1.8-15
## [9] lubridate_1.9.4 tidyr_1.3.2 dplyr_1.2.1 GetBCBData_0.9.1
##
## loaded via a namespace (and not attached):
## [1] sass_0.4.10 generics_0.1.4 xml2_1.4.1
## [4] stringi_1.8.7 lattice_0.22-7 digest_0.6.38
## [7] magrittr_2.0.4 evaluate_1.0.5 grid_4.5.1
## [10] timechange_0.3.0 RColorBrewer_1.1-3 fastmap_1.2.0
## [13] jsonlite_2.0.0 backports_1.5.0 seasonal_1.10.0
## [16] purrr_1.2.0 viridisLite_0.4.2 scales_1.4.0
## [19] codetools_0.2-20 textshaping_1.0.4 jquerylib_0.1.4
## [22] cli_3.6.6 x13binary_1.1.61.2 rlang_1.2.0
## [25] performance_0.17.0 litedown_0.9 tinytable_0.16.0
## [28] withr_3.0.2 cachem_1.1.0 yaml_2.3.10
## [31] datawizard_1.3.1 tools_4.5.1 checkmate_2.3.4
## [34] bayestestR_0.18.1 vctrs_0.7.3 R6_2.6.1
## [37] lifecycle_1.0.5 stringr_1.6.0 insight_1.5.1
## [40] pkgconfig_2.0.3 pillar_1.11.1 bslib_0.9.0
## [43] gtable_0.3.6 glue_1.8.0 data.table_1.18.2.1
## [46] systemfonts_1.3.1 xfun_0.57 tibble_3.3.1
## [49] tidyselect_1.2.1 parameters_0.29.1 rstudioapi_0.17.1
## [52] farver_2.1.2 htmltools_0.5.8.1 tables_0.9.33
## [55] labeling_0.4.3 rmarkdown_2.30 svglite_2.2.2
## [58] compiler_4.5.1 S7_0.2.1