Disclaimer: o presente documento trata de um exercício para fins didáticos realizado na disciplina de Econometria de Séries Temporais do Programa de Pós Graduação em Economia da UFPB. O código base para a criação do Shiny foi realizado pelo professor.
Como exercício, foi proposto utilizar alguma série temporal do Banco Central do Brasil (BC) para realizar o exercício de previsão da série temporal.
No último dia 6, o BC divulgou os resultados fiscais. No que compete a Dívida Líquida do Setor Público (DLSP), foi observado que essa atingiu 61,6% do PIB (R$ 6,7 trilhões) em março. Esse resultado representa uma elevação de 0,2 p.p do PIB no mês.
Ainda segundo o BC, tal resultado foi reflexo dos impactos dos juros nominais apropriados (aumento de 0,6 p.p.); do efeito do ajuste de paridade da dívida externa líquida (redução de 0,1 p.p.); e da variação do PIB nominal (redução de 0,2 p.p.).
Diante disso, é importante destacar também a definição do que é Dívida Líquida do Setor Público (DLSP). Dessa forma, temos:
Para a análise, serão utilizados duas séries temporais disponíveis no Sistema Gerenciador de Séries Temporais do BC, que são elas:
Dívida Líquida do Setor Público - Saldos em R$ milhões - Total - Governo Federal e Banco Central (código 4468); e
Dívida Líquida do Setor Público (% PIB) - Total - Governo Federal e Banco Central (código 4503).
A primeira série possui dados disponíveis a partir de janeiro de 1991 e a segunda série possui dados disponíveis a partir de dezembro de 2001.
Inicialmente, será realizada a limpeza do ambiente de trabalho do R e
em seguida será utilizada uma função para coletar as duas séries
temporais diretamente do BC por meio da API dos dados utilizando o
pacote httr.
# Limpando o R
rm(list=ls(all=TRUE))
#Pacote Necessários
library(shiny)
## Warning: package 'shiny' was built under R version 4.2.3
library(forecast)
## Warning: package 'forecast' was built under R version 4.2.3
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
library(httr)
## Warning: package 'httr' was built under R version 4.2.3
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.2.3
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.2.3
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(jsonlite)
## Warning: package 'jsonlite' was built under R version 4.2.3
##
## Attaching package: 'jsonlite'
## The following object is masked from 'package:shiny':
##
## validate
library(plotly)
## Warning: package 'plotly' was built under R version 4.2.3
##
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
##
## last_plot
## The following object is masked from 'package:httr':
##
## config
## The following object is masked from 'package:stats':
##
## filter
## The following object is masked from 'package:graphics':
##
## layout
library(knitr)
## Warning: package 'knitr' was built under R version 4.2.3
#DLSP %PIB
get_dlsp <- function() {
response <- GET("https://api.bcb.gov.br/dados/serie/bcdata.sgs.4503/dados?formato=json&dataInicial=01/01/2003")
data <- content(response, "parsed")
data <- as.data.frame(do.call(rbind, data))
data$datas <-seq(from = as.Date("2001-12-01"), by = "month", length.out = nrow(data))
data <- data[data$datas >= as.Date("2003-01-01"), ]
dlsp_pib <- ts(as.numeric(data$valor), start = c(2003, 1), frequency = 12)
return(dlsp_pib)
}
response <- GET("https://api.bcb.gov.br/dados/serie/bcdata.sgs.4503/dados?formato=json&dataInicial=01/01/2003")
data <- content(response, "parsed")
data <- as.data.frame(do.call(rbind, data))
data$datas <-seq(from = as.Date("2001-12-01"), by = "month", length.out = nrow(data))
data <- data[data$datas >= as.Date("2003-01-01"), ]
dlsp_pib <- ts(as.numeric(data$valor), start = c(2003, 1), frequency = 12)
#DLSP milhões (R$)
get_dlsp_mi <- function() {
response1 <- GET("https://api.bcb.gov.br/dados/serie/bcdata.sgs.4468/dados?formato=json&dataInicial=01/01/2003")
data1 <- content(response1, "parsed")
data1 <- as.data.frame(do.call(rbind, data1))
data1$datas1 <-seq(from = as.Date("1991-01-01"), by = "month", length.out = nrow(data1))
data1 <- data1[data1$datas1 >= as.Date("2003-01-01"), ]
dlsp_mi <- ts(as.numeric(data1$valor), start = c(2003, 1), frequency = 12)
return(dlsp_mi)
}
response1 <- GET("https://api.bcb.gov.br/dados/serie/bcdata.sgs.4468/dados?formato=json&dataInicial=01/01/2003")
data1 <- content(response1, "parsed")
data1 <- as.data.frame(do.call(rbind, data1))
data1$datas1 <-seq(from = as.Date("1991-01-01"), by = "month", length.out = nrow(data1))
data1 <- data1[data1$datas1 >= as.Date("2003-01-01"), ]
dlsp_mi <- ts(as.numeric(data1$valor), start = c(2003, 1), frequency = 12)
#Criando um dataframe único
df_combined <- as.data.frame(cbind(as.numeric(data$valor), as.numeric(data1$valor)))
df_combined <- df_combined %>%
rename(dlsppib = V1) %>%
rename(dlspmi = V2)
df_combined$datas <- seq(as.Date("2003-01-01"), by = "month", length.out = nrow(df_combined))
De posse dos dados, podemos realizar então, algumas análise iniciais.
# Gráfico interativo para a variável dlsppib
plot_dlsppib <- ggplot(df_combined, aes(x = datas, y = dlsppib)) +
geom_rect(
aes(xmin = as.Date("2008-01-01"), xmax = as.Date("2008-12-31"), ymin = -Inf, ymax = Inf),
fill = "gray90", alpha = 0.5, inherit.aes = FALSE
) +
geom_rect(
aes(xmin = as.Date("2014-01-01"), xmax = as.Date("2016-12-31"), ymin = -Inf, ymax = Inf),
fill = "gray90", alpha = 0.5, inherit.aes = FALSE
) +
geom_rect(
aes(xmin = as.Date("2020-01-01"), xmax = as.Date("2022-12-31"), ymin = -Inf, ymax = Inf),
fill = "gray90", alpha = 0.5, inherit.aes = FALSE
) +
geom_line(color = "blue", size = 1.5) +
labs(x = "Data", y = "% do PIB") +
ggtitle("Divida Liquida do Setor Publico (% do PIB)") +
theme_minimal() +
annotate("text", x = as.Date("2010-01-01"), y = -10, label = "*As áreas em cinza representam os períodos de crise.", size = 3, color = "lightblue")
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
print(plot_dlsppib)
A partir da análise gráfica da relação entre a dívida e o PIB, é possível observar então a trajetória de crescimento principalmente a partir da crise de 2015. Além disso, é possível observar também o crescimento da relação no período da pandemia (2020) e o crescimento a partir de 2023 também.
# Gráfico para a variável dlspmi
plot_dlspmi <- ggplot(df_combined, aes(x = datas, y = dlspmi)) +
geom_rect(
aes(xmin = as.Date("2008-01-01"), xmax = as.Date("2008-12-31"), ymin = -Inf, ymax = Inf),
fill = "gray90", alpha = 0.5, inherit.aes = FALSE
) +
geom_rect(
aes(xmin = as.Date("2014-01-01"), xmax = as.Date("2016-12-31"), ymin = -Inf, ymax = Inf),
fill = "gray90", alpha = 0.5, inherit.aes = FALSE
) +
geom_rect(
aes(xmin = as.Date("2020-01-01"), xmax = as.Date("2022-12-31"), ymin = -Inf, ymax = Inf),
fill = "gray90", alpha = 0.5, inherit.aes = FALSE
) +
geom_line(color = "red", size = 1.5) +
labs(x = "Data", y = "Divida Liquida do Setor Publico (R$)") +
ggtitle("Divida Liquida do Setor Publico (R$)") +
scale_y_continuous(labels = scales::comma_format()) +
theme_minimal() +
annotate("text", x = as.Date("2010-01-01"), y = -10, label = "*As áreas em cinza representam os períodos de crise.", size = 3, color = "lightblue")
print(plot_dlspmi)
Ao observar a variável em termos monetário, é possível observar também a trajetória crescente da dívida pública.
Na sequência, seria realizada a análise da ACF e da PACF para ambas as séries temporais analisadas.
# Calcular a ACF e PACF da série temporal
plot(acf(df_combined$dlsppib, lag.max = 20), main ="Funcao de Autocorrelacao da DLSP/PIB")
plot(pacf(df_combined$dlsppib, lag.max = 20), main ="Funcao de Autocorrelacao Parcial DLSP/PIB")
A partir da ACF, é possível observar então uma relação do resultado atual com os seus valores passados, tendo em vista a própria característica da série temporal.
# Calcular a ACF e PACF da série temporal
plot(acf(df_combined$dlspmi, lag.max = 20), main ="Funcao de Autocorrelacao da DLSP (R$)")
plot(pacf(df_combined$dlspmi, lag.max = 20), main ="Funcao de Autocorrelacao Parcial DLSP (R$)")
O comportamento ao analisar a série com seus valores em R$, o resultado é bem próximo de quando analisamos a relação dívida/PIB.
ts1 <- ts(as.numeric(df_combined$dlsppib), start = c(2003, 1), frequency = 12)
decom<- decompose(ts1, type = "multiplicative")
plot(decom, xlab = "Data")
ts2 <- ts(as.numeric(df_combined$dlspmi), start = c(2003, 1), frequency = 12)
decom2<- decompose(ts2, type = "multiplicative")
plot(decom2, xlab = "Data")
Agora, será realizado um aplicativo para a previsão das séries
temporais. Para isso, será utilizado o pacote shiny (mais
detalhes poderá ser acessado aqui).
O aplicativo terá duas opções, que serão elas:
O usuário poderá utilizar a função auto.arima para
selecionar de forma automática o melhor modelo de previsão; ou
Poderá selecionar a ordem que deseja para a previsão das séries temporais.
ATENÇÃO: ABAIXO, VOCÊ ENCONTRARÁ APENAS O CÓDIGO PARA A CRIAÇÃO DO APLICATIVO. COMO NÃO FICA DINÂMICO NO RPUBS, VOCÊ PODE UTILIZAR O APLICATIVO:
Difinindo o UI - Dívida/PIB
ui <- fluidPage(
titlePanel("Projecao da Divida Liquida do Setor Publico (DLSP) (% em relacao ao PIB)"),
sidebarLayout(
sidebarPanel(
selectInput("modelo", "Escolha o Modelo ARIMA:",
choices = c("auto.arima", "Arima")),
conditionalPanel(
condition = "input.modelo == 'Arima'",
numericInput("ordem_p", "Ordem (p) do Modelo ARIMA:", value = 1, min = 0, max = 10),
numericInput("ordem_d", "Ordem (d) do Modelo ARIMA:", value = 1, min = 0, max = 10),
numericInput("ordem_q", "Ordem (q) do Modelo ARIMA:", value = 1, min = 0, max = 10)
),
actionButton("ajustarButton", "Ajustar Modelo"),
sliderInput("periodosInput", "Número de períodos a projetar:",
min = 1, max = 24, value = 12)
),
mainPanel(
plotOutput("plot"),
textOutput("previsaoOutput")
)
)
)
Difinindo o Servidor - Dívida/PIB
server <- function(input, output) {
modelo_arima <- reactive({
req(input$ajustarButton)
dlsp_pib <- get_dlsp()
if (input$modelo == "auto.arima") {
auto.arima(dlsp_pib)
} else {
order <- c(input$ordem_p, input$ordem_d, input$ordem_q)
Arima(dlsp_pib, order = order)
}
})
output$plot <- renderPlot({
plot(forecast(modelo_arima(), h = input$periodosInput))
})
output$previsaoOutput <- renderText({
previsao <- forecast(modelo_arima(), h = input$periodosInput)
paste("Previsão para os próximos",
input$periodosInput, "períodos:", round(previsao$mean, 2))
})
}
Execução do Aplicativo Shiny - Dívida/PIB
shinyApp(ui = ui, server = server)
## PhantomJS not found. You can install it with webshot::install_phantomjs(). If it is installed, please make sure the phantomjs executable can be found via the PATH variable.
Difinindo o UI - Reais (R$)
ui1 <- fluidPage(
titlePanel("Projecao da Divida Liquida do Setor Publico (DLSP) em milhoes (R$)"),
sidebarLayout(
sidebarPanel(
selectInput("modelo", "Escolha o Modelo ARIMA:",
choices = c("auto.arima", "Arima")),
conditionalPanel(
condition = "input.modelo == 'Arima'",
numericInput("ordem_p", "Ordem (p) do Modelo ARIMA:", value = 1, min = 0, max = 10),
numericInput("ordem_d", "Ordem (d) do Modelo ARIMA:", value = 1, min = 0, max = 10),
numericInput("ordem_q", "Ordem (q) do Modelo ARIMA:", value = 1, min = 0, max = 10)
),
actionButton("ajustarButton", "Ajustar Modelo"),
sliderInput("periodosInput", "Número de períodos a projetar:",
min = 1, max = 24, value = 12)
),
mainPanel(
plotOutput("plot"),
textOutput("previsaoOutput")
)
)
)
Difinindo o Servidor - Dívida/PIB
server1 <- function(input, output) {
modelo_arima <- reactive({
req(input$ajustarButton)
dlsp_mi <- get_dlsp_mi()
if (input$modelo == "auto.arima") {
auto.arima(dlsp_mi)
} else {
order <- c(input$ordem_p, input$ordem_d, input$ordem_q)
Arima(dlsp_mi, order = order)
}
})
output$plot <- renderPlot({
plot(forecast(modelo_arima(), h = input$periodosInput))
})
output$previsaoOutput <- renderText({
previsao <- forecast(modelo_arima(), h = input$periodosInput)
paste("Previsão para os próximos",
input$periodosInput, "períodos:", round(previsao$mean, 2))
})
}
Execução do Aplicativo Shiny - Dívida/PIB
shinyApp(ui = ui1, server = server1)