Introdução

O pacote tidyverseserá utilzado ao longo deste tutorial. Vamos carregá-lo.

library(tidyverse)

Arquivos Locais

Um arquivo .CSV (comma-separated values) é um arquivo de texto delimitado, que geralmente usa uma vírgula para separar valores. Este tipo de arquivo armazena dados tabulares (números e texto) em texto simples. Cada linha do arquivo é um registro de dados. Cada registro consiste em um ou mais campos, separados pelo delimitador. CSV é um formato comum de troca de dados que é amplamente apoiado por aplicações de negócios e científicos. R facilita a exportação e importação de dados em formato CSV.

Exportar dados para um arquivo csv

data("mtcars")                          # carrega os dados mtcars
write.csv(mtcars, file = 'mtcars.csv')  # exporta para o arquivo

Importar dados de um arquivo CSV

x <- read.csv('mtcars.csv')             # lê o arquivo
head(x)                                 # visualiza os primeiros registros
class(x)                                # foi criado um data frame
## [1] "data.frame"

Arquivos Remotos

Alguns provedores de dados oferecem dados em formato csv em seu site. O site da STOXX, um provedor de índices financeiros, é um deles. Abra este link para o Índice EURO STOXX 50. A guia Data -> Historical Data fornece alguns arquivos de código aberto para preços históricos. Clicando em EUR Price abrirá este link. A função ‘read.csv()’ pode ler este arquivo diretamente da internet.

# read.csv é bastante flexível. Digite ?read.csv para conhecer todos os argumentos da função
x <- read.csv('https://www.stoxx.com/document/Indices/Current/HistoricalData/h_3msx5e.txt', sep = ';') 
head(x)
rownames(x) <- as.Date(x[, 1], format = '%d.%m.%Y') # designa nomes para as linhas (registros)
x[,c(1, ncol(x))] <- NULL                           # elimina a primeira e a última colunas
head(x)                                             # visualiza os primeiros registros

Alguns pacotes do R para acesso a dados

Fontes de dados nacionais

Fontes de dados internacionais

  • quantmod: Framework para modelagem em finanças quantitativas.
  • Quandl: Um marketplace para dados financeiros, econômicos e alternativos mundiais..
  • tidyquant: O mundo financeiro no tidyverse.

Exemplos de uso

library(quantmod)
getSymbols("^DJI", src = "yahoo", from = "2005-01-01")
## [1] "^DJI"
Cl(DJI) %>% autoplot()

getSymbols(c("GOOG", "AAPL"), src = "yahoo", from = "2010-08-01")
## [1] "GOOG" "AAPL"
autoplot(merge(GOOG = Cl(GOOG), AAPL = Cl(AAPL))) + 
  facet_free()

quantmod

O pacote quantmod provê a função getSymbols(), que é muito conveniente para baixar dados financeiros diretamente da web, importando os dados como um objeto xts. O objeto xts é importado para o ambiente, não é necessário atribuir a uma variável, quando o parâmetro auto.assign = TRUE (o padrão, atualmente).

getSymbols() trabalha com uma grande variedade de fontes (src) de dados:

  • Yahoo Finance: ações, fundos, commodities, e outros ativos de diversos países.
  • FRED: indicadores econômicos.
  • OANDA: moedas.
  • Tiigo: ações do mercado americano.
  • Alpha Vantage: ações, moedas, cripto-moedas e moedas digitais.
  • Fontes privadas: MySQL, SQLite, RData, CSV.
# instale o pacote
# install.packages('quantmod')

# carregue o pacote na memória
library(quantmod)

Para ações, o sítio yahoo é bastante utilizado. Os símbolos podem ser encontrados aqui.

# baixe os dados do Google 
x <- getSymbols(Symbols = 'GOOG', src = 'yahoo', auto.assign = FALSE)   
head(x)
##            GOOG.Open GOOG.High GOOG.Low GOOG.Close GOOG.Volume GOOG.Adjusted
## 2014-03-27  566.4451  566.4451 551.4064   556.9312       13087      556.9312
## 2014-03-28  559.7136  564.8794 557.1406   558.4570       41115      558.4570
## 2014-03-31  565.3381  565.4478 555.4054   555.4453       10801      555.4453
## 2014-04-01  557.1805  566.8939 557.1805   565.6074        7953      565.6074
## 2014-04-02  579.1702  603.1743 560.6510   565.4478      147099      565.4478
## 2014-04-03  568.2900  585.6723 562.5857   568.1804     5101495      568.1804
autoplot(x$GOOG.Close)

# Ações brasileiras

x <- getSymbols("ITUB4.SA", src = 'yahoo', auto.assign = FALSE)
head(x)
##            ITUB4.SA.Open ITUB4.SA.High ITUB4.SA.Low ITUB4.SA.Close
## 2007-01-02      12.78270      13.05756     12.75124       12.96152
## 2007-01-03      12.89695      13.11386     12.80423       13.03935
## 2007-01-04      12.96484      13.06584     12.85721       12.91516
## 2007-01-05      12.90688      13.00458     12.41843       12.41843
## 2007-01-08      12.53267      12.68666     12.46644       12.68666
## 2007-01-09      12.63368      12.76117     12.01773       12.41511
##            ITUB4.SA.Volume ITUB4.SA.Adjusted
## 2007-01-02         8882767          8.065495
## 2007-01-03        10951870          8.113920
## 2007-01-04         9636486          8.036639
## 2007-01-05        12768525          7.727535
## 2007-01-08        13024596          7.894456
## 2007-01-09        15680730          7.725479
autoplot(x$ITUB4.SA.Close)

Visualizando ações com o pacote CandleStickPattern

getSymbols("ITUB4.SA", from = "2020-01-02" , to = "2020-12-18")
## [1] "ITUB4.SA"
#devtools::install_github("kochiuyu/CandleStickPattern")
library(CandleStickPattern)
candleChart(ITUB4.SA, theme = 'white')

Importando índices

Os símbolos dos índices têm prefixo ^: ^BVSP, ^DJI etc.

getSymbols("^BVSP") # IBOVESPA
## [1] "^BVSP"
tail(BVSP, 3)
##            BVSP.Open BVSP.High BVSP.Low BVSP.Close BVSP.Volume BVSP.Adjusted
## 2021-12-08  107558.0  108521.0 107309.0   108096.0    13166800      108096.0
## 2021-12-09        NA        NA       NA         NA          NA            NA
## 2021-12-10  106296.3  108274.9 106296.3   107758.3           0      107758.3
chartSeries(BVSP, 
            type = "candlesticks", 
            theme = "white",
            subset = "201801/", 
            name = "IBOVESPA")

chartSeries(BVSP, 
            type = "bars", 
            theme = "black", 
            subset = "201801/",
            major.ticks = "months", 
            name = "IBOVESPA", 
            TA = NULL)

Para moedas e metais, pode-se utilizar o sítio oanda. Os símbolos são os códigos ISO dos ativos, separados por /. Os códigos ISO podem ser encontrados aqui.

# baixe os dados históricos da taxa de câmbio euro/dolar
x <- getSymbols(Symbols = 'EUR/USD', src = 'oanda', auto.assign = FALSE)   
tail(x)
##             EUR.USD
## 2021-12-05 1.131056
## 2021-12-06 1.128812
## 2021-12-07 1.126840
## 2021-12-08 1.130844
## 2021-12-09 1.131228
## 2021-12-10 1.129820
autoplot(x)

Para séries econômicas mundiais, a fonte FRED pode ser utilizada. Os símbolos podem ser encontrados aqui.

# baixe a série do PIB do Japão
x <- getSymbols(Symbols = 'JPNNGDP', src = 'FRED', auto.assign = FALSE)   
tail(x)
##             JPNNGDP
## 2020-04-01 511942.7
## 2020-07-01 538207.3
## 2020-10-01 547634.4
## 2021-01-01 543529.5
## 2021-04-01 543806.6
## 2021-07-01 538151.0

Uma característica bastante interessante do pacote quantmod é o conjunto de funções que fornecem diretamente séries de retornos a partir das séries de preços. Veja o exemplo a seguir, que compara os retornos semanais aritméticos com os compostos (contínuos):

r_arit <- quantmod::weeklyReturn(BVSP, type = 'arithmetic')
r_log <- quantmod::weeklyReturn(BVSP, type = 'log')

g1 <- autoplot(r_arit) +
  labs(x = '', y = 'retornos aritméticos')
g2 <- autoplot(r_log) +
  labs(x = 'data', y = 'retornos contínuos')
gridExtra::grid.arrange(g1, g2, nrow = 2)

# a diferença entre os dois tipos de retorno

diferenca <- r_arit - r_log
summary(diferenca$weekly.returns)
##      Index            weekly.returns     
##  Min.   :2007-01-05   Min.   :3.000e-09  
##  1st Qu.:2010-09-29   1st Qu.:4.094e-05  
##  Median :2014-06-23   Median :2.117e-04  
##  Mean   :2014-06-23   Mean   :6.430e-04  
##  3rd Qu.:2018-03-17   3rd Qu.:5.961e-04  
##  Max.   :2021-12-10   Max.   :2.316e-02
autoplot(r_arit - r_log, ylim = c(0, 0.03))

# Plotando os dois tipos de retorno em um só gráfico
library(ggfortify)
autoplot(cbind(r_arit, r_log), 
         facets = FALSE)

BETS

O pacote BETS permite acesso ao repositório de dados da Fundação Getúlio Vargas (FGV), que inclui bases de dados do BCB, IBGE e o Instituto Brasileiro de Economia da FGV (FGV/ IBRE).

Vamos utilizar o pacote para baixar dados de desemprego no Brasil. O primeiro passo é procurar o número de identificação da série com a função BETSsearch:

library(BETS) 
library(dplyr) 
library(knitr)

# procure a identificação
df.res <- BETSsearch('unemployment', view = FALSE) 

# Verificando o resultado
df.res %>%
  kable() %>%
  kableExtra::kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
code description unit periodicity start last_value source
24369 Unemployment rate - PNADC % M 01/03/2012 mar/2018 IBGE

Com o argumento view = FALSE, a função retorna um dataframe com os resultados. Há várias séries sobre desemprego disponíveis. Vamos acessar a série divulgada pelo PNAD/ IBGE, cujo número de identificação é 24369.

# seleciona a identificação
id <- 24369 

# datas de início e término da série 
inicio = '2010-01-01' 
fim = as.character(Sys.Date()) 

# obtem os dados 
df.BETS <- BETSget(code = id, 
                   data.frame = TRUE, 
                   from = inicio, 
                   to = fim)

glimpse(df.BETS)
## Rows: 115
## Columns: 2
## $ date  <date> 2012-03-01, 2012-04-01, 2012-05-01, 2012-06-01, 2012-07-01, 201~
## $ value <dbl> 8.0, 7.8, 7.7, 7.6, 7.5, 7.4, 7.1, 7.0, 6.8, 6.9, 7.3, 7.8, 8.1,~

A saída de BETSget é um dataframe com duas colunas. Podemos verificar o comportamento do índice de desemprego importado com uma figura:

p <- ggplot(df.BETS, aes(x = date, y = value)) + 
  geom_line() + 
  labs(y = 'Taxa de Desemprego', 
       x = 'Data',
       title = 'Desemprego no Brasil',
       subtitle = paste0(format(as.Date(inicio), '%d de %B de %Y'), ' a ', format(as.Date(fim), '%d de %B de %Y')),
       caption = 'Dados do PNAD/IBGE')

print(p)

Quandl

O pacote Quandl entrega uma API RESTful para acesso a diversas fontes de dados gratuitas e privadas (premium) obtidas no site do quandl.

Além do R, possui bibliotecas para diversas linguagens, como Python, Excel, Ruby.

Vamos obter os dados do PIB dos EUA. Os dados são importados do FRED - Federal Reserve Economic Data.

library(Quandl)
gdp <- Quandl("FRED/GDP")
glimpse(gdp)
## Rows: 299
## Columns: 2
## $ Date  <date> 2021-07-01, 2021-04-01, 2021-01-01, 2020-10-01, 2020-07-01, 202~
## $ Value <dbl> 23187.04, 22740.96, 22038.23, 21477.60, 21138.57, 19477.44, 2148~

A função Quandl traz várias facilidades:

args(Quandl)
## function (code, type = c("raw", "ts", "zoo", "xts", "timeSeries"), 
##     transform = c("", "diff", "rdiff", "normalize", "cumul", 
##         "rdiff_from"), collapse = c("", "daily", "weekly", "monthly", 
##         "quarterly", "annual"), order = c("desc", "asc"), meta = FALSE, 
##     force_irregular = FALSE, ...) 
## NULL

A documentação da função detalha a funcionalidade de cada parãmetro. Digna de de nota é a facilidade de transformação dos dados durante a importação, como mostra a seguinte figura.

tidyquant

O pacote tidyquant foi desenvolvido para integrar os pacotes QFA (quantmod, xts e TTR) e o tidyverse. Vamos apresentar o pacote por meio de alguns exemplos.

Comecemos com um exemplo de visualização das médias móveis (MM) de 15 dias e 50 dias das ações da Magazine Luiza S.A. (MGLU3.SA). De acordo com a Investopedia, a média móvel é…

Um indicador amplamente utilizado na análise técnica que ajuda a suavizar a ação dos preços, filtrando o “ruído” de flutuações aleatórias de preços. Uma média móvel (MA) é um indicador de tendência ou atraso porque é baseado em preços passados. Os dois MAs básicos e comumente usados são a média móvel simples (SMA), que é a média simples de um ativo ao longo de um número definido de períodos de tempo, e a média móvel exponencial (EMA), que dá maior peso aos preços mais recentes. As aplicações mais comuns dos MAs são identificar a direção da tendência e determinar níveis de suporte e resistência. Embora os MAs sejam úteis o suficiente por conta própria, eles também formam a base para outros indicadores, como a MACD (Moving Average Convergence Divergence ).

De particular interesse é o crossover, ou cruzamento de MM, o ponto em que uma tendência começa a emergir, que pode ser usado como sinal de compra ou venda.

Carrega o pacote e obtem os dados do último ano

library(tidyquant)
ontem <- lubridate::today() - 1
inicio <- as.character(ontem - 365)

MGLU <- tq_get("MGLU3.SA", 
               get = "stock.prices", 
               from = inicio,
               to = as.character(ontem)) %>% 
        na.omit()
MGLU
str(MGLU)
## tibble [246 x 8] (S3: tbl_df/tbl/data.frame)
##  $ symbol  : chr [1:246] "MGLU3.SA" "MGLU3.SA" "MGLU3.SA" "MGLU3.SA" ...
##  $ date    : Date[1:246], format: "2020-12-10" "2020-12-11" ...
##  $ open    : num [1:246] 24.1 23.1 23 24 24.5 ...
##  $ high    : num [1:246] 24.2 23.5 24.2 24.8 25 ...
##  $ low     : num [1:246] 23.2 22.7 22.9 23.6 24.2 ...
##  $ close   : num [1:246] 23.4 23 24 24.6 25 ...
##  $ volume  : num [1:246] 33674300 38144400 43300500 39496800 41309900 ...
##  $ adjusted: num [1:246] 23.4 22.9 24 24.6 24.9 ...

Os dados estão prontos para serem trabalhados com o pacote tidyverse.

Algumas funções do pacote

Desejamos obter as médias móveis de 15 dias e 50 dias, utilizando a função SMA() do pacote TTR. Para usar qualquer uma dessas funções no tidyverse, temos algumas opções, com prós e contras:

  • dplyr::mutate(): Usado para adicionar uma única coluna a um conjunto de dados. Só é capaz de adicionar uma única coluna a um tibble. Para SMA(), isso funciona porque uma única coluna é gerada. Para outras funções, como BBands() e MACD, várias colunas são geradas, e falham com mutate().

  • tidyquant::tq_mutate(): Usado para adicionar colunas únicas ou múltiplas a um conjunto de dados. Usa a notação quantmod OHLC. A saída gerada deve ter o mesmo número de linhas que o dataframe de entrada (caso contrário, os dados não podem ser juntados). Como várias colunas podem ser devolvidas, funciona com BBands() e MACD().

  • tidyquant::tq_transform(): Usado para retornar um novo conjunto de dados apenas com a saída (não retorna o dataframe de entrada). Usa notação OHLC. É a opção mais flexível.

  • tidyquant::tq_mutate_xy(): O mesmo que tq_mutate(), mas funciona usando até duas entradas de coluna em vez da notação OHLC.

  • tidyquant::tq_transform_xy(): O mesmo que tq_transform(), mas funciona usando até duas colunas.

Utilizaremos no exemplo tq_mutate(). Veremos, também, um exemplo de emprego de tq_mutate_xy().

tq_mutate para adicionar médias móveis

tq_mutate() tem dois argumentos primários: select e mutate_fun:

  • select: as colunas a serem utilizadas pela função especificada em mutate_fun.

  • mutate_fun: utiliza qualquer função quantmod, xts ou TTR listada em tq_mutate_fun_options() (veremos abaixo as funções compatíveis). mutation_fun realiza o trabalho. Quaisquer parâmetros adicionais passados via na função tq_mutate() vão para mutation_fun.

Parte da lista de opções de tq_mutate():

tq_mutate_fun_options() %>% 
    str() # str() para minimizar a saída. Remova str() para ver tudo.
## List of 5
##  $ zoo                 : chr [1:14] "rollapply" "rollapplyr" "rollmax" "rollmax.default" ...
##  $ xts                 : chr [1:27] "apply.daily" "apply.monthly" "apply.quarterly" "apply.weekly" ...
##  $ quantmod            : chr [1:25] "allReturns" "annualReturn" "ClCl" "dailyReturn" ...
##  $ TTR                 : chr [1:63] "adjRatios" "ADX" "ALMA" "aroon" ...
##  $ PerformanceAnalytics: chr [1:7] "Return.annualized" "Return.annualized.excess" "Return.clean" "Return.cumulative" ...

Um exemplo com SMA() do pacote TTR.

A função, TTR::SMA(x, n = 10, ...) aceita x, um vetor de preços ou volumes e n, uma série de períodos para a média móvel. Para a média móvel simples de 15 dias, passaríamos um conjunto de preços, “close” ou “adjusted” e n = 15 para 15 dias. Definimos o parâmetro mutate_fun = SMA e passamos n = 15 como argumento adicional.

Como mostrado abaixo, utilizamos o pipe (%>%) para enviar os preços das ações do Magazine Luiza para tq_mutate(select = close, mutate_fun = SMA, n = 15), que cria uma coluna adicional com a média móvel simples dos preços de fechamento

MGLU %>%
    tq_mutate(select = close, mutate_fun = SMA, n = 15) 

Vamos adicionar a MM de 50 dias.

MGLU %>%
    tq_mutate(select = close, mutate_fun = SMA, n = 15, col_rename = 'SMA.15') %>%
    tq_mutate(select = close, mutate_fun = SMA, n = 50) %>%
    rename(SMA.50 = SMA)  # uma alternativa para renomear a coluna, com dplyr

A função tq_mutate_xy()

Nem todas as funções quantmod, xts e TTR funcionam com a notação OHLC. Algumas dessas funções recebem duas entradas primárias. Um exemplo disso é a função Delt do pacote quantmod. A sintaxe de função é Delt(x1, x2 = NULL, k = 0, type = c("arithmetic", "log")), que tem dois argumentos: x1 e x2. Nessas situações é necessário usar a variante tq_mutate_xy(), que aceita x (obrigatório) e y (opcional). Para a função Delt, x = x1 e y = x2.

Para a função SMA(), o argumento y não é necessário, mas podemos usar a variante XY para realizar a mesma tarefa que a variante OHLC. A operação é a mesma, exceto que, em vez de select = close nós substituímos por x = close (o nome da coluna sendo passada para a função de mutação).

MGLU %>%
    tq_mutate_xy(x = close, mutate_fun = SMA, n = 15) %>%
    rename(SMA.15 = SMA) %>%
    tq_mutate_xy(x = close, mutate_fun = SMA, n = 50) %>%
    rename(SMA.50 = SMA) 

De volta ao exemplo

Podemos utilizar qualquer das opções apresentadas para obter as MMs simples.

MGLU <- MGLU %>%
    tq_mutate(select = close, mutate_fun = SMA, n = 15) %>%
    rename(SMA.15 = SMA) %>%
    tq_mutate(select = close, mutate_fun = SMA, n = 50) %>%
    rename(SMA.50 = SMA) 

Visualizando as médias móveis

Para adequar o formato dos dados para o emprego do pacote ggplot2, precisamos utilizar a função gatherdo pacote tidyr. Esta função é antiga, e os desenvolvedores do pacote sugerem que passemos a utilizar a função pivot_longer(), que é mais fácil de usar e, segundo garantem, mais rápida. Vamos ver os dois modos.

# Usando gather()
MGLU %>%
    select(date, close, SMA.15, SMA.50) %>%
    gather(key = tipo, value = preco, close:SMA.50) 
# Usando pivot_longer
MGLU %>%
    select(date, close, SMA.15, SMA.50) %>%
    pivot_longer(cols = close:SMA.50, names_to = 'tipo', values_to = 'preco')
cores <- c("black", "blue", "red")
MGLU %>%
    select(date, close, SMA.15, SMA.50) %>%
    pivot_longer(cols = close:SMA.50, names_to = 'tipo', values_to = 'preco') %>%
    ggplot(aes(x = date, y = preco, col = tipo)) +
    geom_line() +
    scale_colour_manual(values = cores) + 
    theme(legend.position = "bottom") +
    ggtitle("Médias Móveis Simples com tidyquant - Magazine Luiza") +
    xlab("") + 
    ylab("Preço")

Este exemplo mostra superficialmente o poder do pacote tidyquant. Consulte a vignette para uma descrição detalhada de cada uma das características do pacote.

Pacotes do professor Marcelo Perlin

GetQuandlData

Quandl é uma plataforma abrangente que fornece acesso a uma série de dados gratuitos e pagos. Vários bancos centrais e instituições de pesquisa fornecem informações econômicas e financeiras gratuitas nesta plataforma. É altamente recomendável navegar pelas tabelas disponíveis no site da Quandl.

Em R, o pacote Quandl (Raymond McTaggart, Gergely Daroczi e Clement Leung 2019) é oferecido pela empresa e está disponível no CRAN. O pacote GetQuandlData é uma alternativa melhor, sendo mais amigável ao usuário.

O primeiro e obrigatório passo no uso do pacote é cadastrar um usuário no site da Quandl. Logo depois, vá para as configurações da conta e clique em API KEY. Esta página deve mostrar um código, como, por exemplo, Asv8Ac7zuZzJSCGxynfG. Copie-o para a área de transferência (ctrl + c) e, em R, defina um objeto de caractere contendo o conteúdo copiado da seguinte forma:

minha_api_key <- 'A3n8Ac7z12zJSCGacbfG'  # fake - obtenha sua própria API Key 

De posse de sua chave, vá para o site da Quandl e use a pesquisa para procurar o símbolo da série de seu interesse. Como exemplo, usaremos dados para preços de ouro em dólares americanos, com um código Quandl equivalente a WGC/GOLD_DAILY_USD. Observe que a estrutura de um código Quandl é sempre a mesma, com o nome do banco de dados principal em primeiro lugar, e o nome da tabela após, separados por uma barra para a frente (/). Por exemplo, as reservas internacionais diárias brasileiras (conceito liquidez) podem ser obtidas com o símbolo BCB/13982, da base de dados do Banco Central do Brasil.

Utilize sua chave (API key) e o símbolo Quandl com a função get_Quandl_series para baixar os dados de 01 de janeiro de 1980 ao dia anterior mais próximo (também conhecido como ontem).

library(GetQuandlData)

# defina símbolo e datas
meu_simbolo <- c('Ouro vs USD' = 'WGC/GOLD_DAILY_USD')
inicio <- as.Date('1980-01-01')  # note o formato internacional da data
fim <- Sys.Date()-1 # ontem

# obtenha os dados
df_ouro <- get_Quandl_series(id_in = meu_simbolo,
                             api_key = minha_api_key, 
                             first_date = inicio,
                             last_date = fim)

# verifique
glimpse(df_ouro)
## Rows: 10,489
## Columns: 4
## $ series_name <chr> "Ouro vs USD", "Ouro vs USD", "Ouro vs USD", "Ouro vs USD"~
## $ ref_date    <date> 2020-03-13, 2020-03-12, 2020-03-11, 2020-03-10, 2020-03-0~
## $ value       <dbl> 1562.80, 1570.70, 1653.75, 1655.70, 1672.50, 1683.65, 1659~
## $ id_quandl   <chr> "WGC/GOLD_DAILY_USD", "WGC/GOLD_DAILY_USD", "WGC/GOLD_DAIL~

Para verificar, vamos traçar os preços do Ouro em USD ao longo do tempo. Usaremos o pacote ggplot2 para criar a figura.

# gráfico do ouro com ggplot2
p <- ggplot(df_ouro, aes(x = ref_date, y = value)) + 
  geom_line(col = 'darkblue') + 
  labs(y = 'Preços (USD)', 
       x = '',
       title = 'Preços do Ouro',
       subtitle = paste0(format(inicio, '%d de %B de %Y'), ' a ', format(fim, '%d de %B de %Y')),
       caption = 'Dados do Quandl')

print(p)

Quando a economia desacelera, como aconteceu em 2020 devido à pandemia da Covid-19, investidores começam a procurar por investimentos que protejam suas carteiras. É o caso do ouro, uma commodity que pode ser interessante para diversificar o portfólio. O valor do ouro é influenciado por três fatores que, por sua vez, são influenciados pelo momento econômico. São eles:

  • Cotação do dólar: como o preço do ouro é definido em dólar, as oscilações da moeda americana exercem influência no valor do metal.

  • Inflação: quando a inflação aumenta, a procura por investimentos seguros e moedas mais estáveis também cresce.

  • Cenário econômico: eventos políticos e econômicos, crises e turbulências causam estresse no câmbio. Por consequência, o preço do ouro também sofre variadas oscilações.

Por isso, é comum que o ouro seja lembrado por investidores em situações de volatilidade e crise no mercado, seja ele interno ou externo. Isso não signifca, entretanto, que investir na commodity é uma opção para todos os investidores.

O preço do ouro ficou bastante estável entre 1980 e 2000. Uma possível explicação é a maior demanda por ativos mais seguros, como o ouro, após a crise financeira de 2009. No entanto, o ouro nunca foi um investimento eficiente a longo prazo. Para mostrar isso, vamos calcular seu retorno anual composto de janeiro de 1980 à data final:

# ordena as linhas pela data
df_ouro <- df_ouro %>%
           arrange(ref_date)

df_ouro <- df_ouro[order(df_ouro$ref_date),]

# calcula o retorno
ret_total <- (last(df_ouro$value) / first(df_ouro$value)) - 1
anos_totais <- as.numeric(max(df_ouro$ref_date) -
                          min(df_ouro$ref_date) )/365

ret_comp_por_ano <- (1 + ret_total)^(1/anos_totais) - 1

print(ret_comp_por_ano)
## [1] 0.02813032

Encontramos o resultado de que os preços do ouro em USD cresceram a uma taxa igual a 2.813% ao ano. Este resultado não é bom. Como comparação, a inflação anual para os EUA no mesmo período é de 3,18%. Isso significa que, ao comprar ouro em 1980, o investidor recebeu menos que a inflação como retorno nominal, resultando na perda do poder aquisitivo.

yfR

O pacote yfR do professor Marcelo S. Perlin é construído com base nas funções do pacote quantmod e facilita bastante a obtenção e organização de dados financeiros. Ele permite a obtenção de dados diários de preços e volume negociados para ações em larga escala, utilizando a fonte Yahoo Finance. É importante lembrar que os preços do Yahoo Finance não são ajustados a dividendos, apenas para desdobramentos das ações. Isso significa que, ao olhar séries de preços longas, existe um viés de retorno para baixo.

Alguns benefícios do pacote:

  • Limpeza e organização

  • Controle de erros de importação

  • Comparação de datas a um benchmark

  • Uso de sistema local de cache (pedidos repetidos de dados são importados localmente)

  • Computação paralela: Usuários podem usar todos os núcleos (processadores) para pedir dados

  • Acesso a tickers em índices de mercado

  • Flexibilidade de formato de saída: longo (empilhado) ou wide (indexado por colunas)

Exemplo 1

Utilizaremos a função yfR::yf_get() para obter as ações que compõem o índice da BOVESPA e os dados de preços.

Obtendo os dados.

library(yfR)
library(tidyverse)

inicio <- '2010-01-01' 
fim <- Sys.Date() - 1 # Ontem - Sys.Date() é o término padrão
ibov.tickers <- c('^BVSP', paste0(yf_index_composition("IBOV")[['ticker']], '.SA'))

df.precos <- yf_get(ibov.tickers,
                    first_date = inicio,
                    last_date = fim, 
                    freq_data = "yearly",
                    be_quiet = TRUE
)

Calcula os retornos médios anuais da ações e do índice.

tab.acoes <- df.precos %>%
    na.omit() %>%
    group_by(ticker) %>%
    summarise(ret.medio = mean(ret_adjusted_prices),
              dp.ret = sd(ret_adjusted_prices)) %>%
    mutate(ticker = stringr::str_replace_all(ticker, '.SA', '') ) 

tab.indice.mercado <- tab.acoes %>%
               filter(ticker == "^BVSP")

tab.acoes <- tab.acoes %>%
               filter(ticker != "^BVSP")

Exemplo

Agora, baixamos dados referentes a quatro ações nos 60 dias anteriores. Os tickers de cada ação podem ser encontrados nos próprios sites do Yahoo Finance. Note que é necessário adicionar o texto .SA a cada um deles. Isso vale para qualquer ação brasileira.

library(BatchGetSymbols) 
library(dplyr) 

# seleciona as ações 
minhas_acoes <- c('PETR4.SA', 'BRKM5.SA', 'GGBR4.SA', 'ITUB4.SA') 

# seleciona as datas e os outros parâmetros da função
inicio <- Sys.Date() - 60 
fim <- Sys.Date() 

thresh.bad.data <- 0.95 # seleciona o limite percentual para dados ruins
bench.ticker <- '^BVSP' # selecione ibovespa 
cache.folder <- 'Dados/BGS_Cache' # seleciona o diretório para o cache

l.saida <- BatchGetSymbols(tickers = minhas_acoes, 
                          first.date = inicio, 
                          last.date = fim, 
                          bench.ticker = bench.ticker, 
                          thresh.bad.data = thresh.bad.data, 
                          cache.folder = cache.folder)

A saída da função BatchGetSymbols é uma lista contendo dois elementos: um dataframe com o resultado do processo e outro dataframe com os dados das ações.

O primeiro dataframe (df.control) mostra o status do download de cada ação e o número de observaçãoes de cada uma.

print(l.saida$df.control)
## # A tibble: 4 x 6
##   ticker   src   download.status total.obs perc.benchmark.dates threshold.decis~
##   <chr>    <chr> <chr>               <int>                <dbl> <chr>           
## 1 PETR4.SA yahoo OK                     41                    1 KEEP            
## 2 BRKM5.SA yahoo OK                     41                    1 KEEP            
## 3 GGBR4.SA yahoo OK                     41                    1 KEEP            
## 4 ITUB4.SA yahoo OK                     41                    1 KEEP

Os dados financeiros estão contidos no elemento df.tickers de l.saida:

glimpse(l.saida$df.tickers)
## Rows: 164
## Columns: 10
## $ price.open          <dbl> 29.17, 29.86, 29.80, 29.40, 29.24, 28.27, 27.86, 2~
## $ price.high          <dbl> 29.70, 30.22, 29.84, 29.64, 29.32, 28.80, 28.18, 2~
## $ price.low           <dbl> 29.08, 29.50, 29.51, 28.99, 27.86, 27.95, 26.92, 2~
## $ price.close         <dbl> 29.63, 29.68, 29.60, 29.45, 28.01, 28.50, 27.45, 2~
## $ volume              <dbl> 55605400, 76172700, 72479900, 68971300, 111484000,~
## $ price.adjusted      <dbl> 26.37622, 26.42073, 26.34951, 26.21599, 24.93412, ~
## $ ref.date            <date> 2021-10-13, 2021-10-14, 2021-10-15, 2021-10-18, 2~
## $ ticker              <chr> "PETR4.SA", "PETR4.SA", "PETR4.SA", "PETR4.SA", "P~
## $ ret.adjusted.prices <dbl> NA, 0.0016875049, -0.0026954215, -0.0050675697, -0~
## $ ret.closing.prices  <dbl> NA, 0.0016875127, -0.0026954178, -0.0050675338, -0~

Os dados sobre preços, retornos e volumes estão prontos para serem utilizados em nossas análises.

GetBCDData

Este pacote acessa dados econômicos do SGS/BCB (Banco Central Brasileiro) de forma eficiente, utilizando a API oficial do Sistema de Séries Temporais do Banco Central.

Alguns benefícios:

  • Uso de um sistema de cache local para acelerar solicitações repetidas de dados

  • Computação paralela: usuários podem utilizar todos os núcleos da máquina ao buscar um grande lote de séries temporais

  • Escolha do formato da saída: longo (orientado a linhas, dados empilhados) ou amplo (orientado a colunas)

  • Tratamento interno de erros. Mesmo que a série solicitada não exista, a função ainda retornará todos os resultados

Primeiro exemplo: taxa SELIC

library(GetBCBData)

meu_id <- c('Taxa SELIC' = 11)
inicio <- '1990-01-01'
fim <- Sys.Date()

df_bcb <- gbcbd_get_series(meu_id,
                           first.date = inicio, 
                           last.date = fim)

glimpse(df_bcb)
## Rows: 8,010
## Columns: 4
## $ ref.date    <date> 1989-12-29, 1990-01-02, 1990-01-03, 1990-01-04, 1990-01-0~
## $ value       <dbl> 2.793452, 2.679178, 2.677644, 2.272630, 2.275452, 2.276932~
## $ id.num      <dbl> 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11~
## $ series.name <chr> "Taxa SELIC", "Taxa SELIC", "Taxa SELIC", "Taxa SELIC", "T~
summary(df_bcb)
##     ref.date              value             id.num   series.name       
##  Min.   :1989-12-29   Min.   :0.00000   Min.   :11   Length:8010       
##  1st Qu.:1998-01-06   1st Qu.:0.04020   1st Qu.:11   Class :character  
##  Median :2005-12-27   Median :0.05814   Median :11   Mode  :character  
##  Mean   :2005-12-27   Mean   :0.21419   Mean   :11                     
##  3rd Qu.:2013-12-16   3rd Qu.:0.09096   3rd Qu.:11                     
##  Max.   :2021-12-10   Max.   :3.62600   Max.   :11
p <- ggplot(df_bcb, aes(x = ref.date, y = value)) +   
  geom_line(col = 'darkred') + 
  labs(title = 'Taxa SELIC',
       x = '', 
       y = 'Taxa') + 
  scale_y_continuous(labels = scales::percent)
p

SELIC e CDI

meu_id <- c('Taxa SELIC' = 11,
            'CDI' = 12)

inicio <- '2000-01-01'
fim <- Sys.Date()

df_bcb <- gbcbd_get_series(meu_id, 
                           first.date = inicio, 
                           last.date = fim)

glimpse(df_bcb)
## Rows: 11,023
## Columns: 4
## $ ref.date    <date> 1999-12-31, 2000-01-03, 2000-01-04, 2000-01-05, 2000-01-0~
## $ value       <dbl> 0.069186, 0.069186, 0.069186, 0.069220, 0.069286, 0.069286~
## $ id.num      <dbl> 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11~
## $ series.name <chr> "Taxa SELIC", "Taxa SELIC", "Taxa SELIC", "Taxa SELIC", "T~
summary(df_bcb)
##     ref.date              value              id.num     series.name       
##  Min.   :1999-12-31   Min.   :0.007469   Min.   :11.0   Length:11023      
##  1st Qu.:2005-06-23   1st Qu.:0.032213   1st Qu.:11.0   Class :character  
##  Median :2010-12-21   Median :0.044556   Median :11.0   Mode  :character  
##  Mean   :2010-12-19   Mean   :0.045266   Mean   :11.5                     
##  3rd Qu.:2016-06-14   3rd Qu.:0.059308   3rd Qu.:12.0                     
##  Max.   :2021-12-10   Max.   :0.092855   Max.   :12.0
p <- ggplot(df_bcb, aes(x = ref.date, 
                        y = value, 
                        colour = series.name)) +
    geom_line() +
    labs(y = 'Taxa', 
         x = 'Data',
         title = 'SELIC e CDI',
         subtitle = paste0(format(as.Date(inicio), '%d de %B de %Y'), ' a ', format(as.Date(fim), '%d de %B de %Y')),
         caption = 'Dados do BCB',
         colour = 'Série') +
    scale_y_continuous(labels = scales::percent) 
  
p

Nota-se que os valores das duas séries são extremamente parecidos.

GetTDData

Diariamente títulos públicos federais são negociados no Tesouro Direto (mercado secundário).

Este pacote importa dados de preços e yields (retornos) de títulos públicos negociados no Tesouro Direto, com o benefício de agregar e organizar os dados das planilhas. Isso inclui títulos do tipo LFT, LTN, NTN-C, NTN-B, NTN-B Principal e NTN-F. O usuário apenas necessita indicar o nome dos ativos de renda fixa e as datas de maturidade desejadas.

Exemplo 1: LTN 010121

Como exemplo, vamos baixar dados de um título prefixado do tipo LTN com vencimento em 2021-01-01. Esse é o tipo de contrato de dívida mais simples que o governo brasileiro emite, não pagando nenhum cupom durante sua validade e, na data de vencimento, retorna R$1.000,00 ao comprador.

library(GetTDData)

codigo <- 'LTN'   # LFT, LTN, NTN-C, NTN-B, NTN-B Principal, NTN-F 
maturidade <- '010121'  # Data como um string (ddmmyy)

minha_flag <- download.TD.data(asset.codes = codigo)
## 
## Downloading html page (attempt = 1|10)
## Downloading file TD Files/LTN_2021.xls (1-20) Downloading...
## Downloading file TD Files/LTN_2020.xls (2-20) Found file in folder, skipping it.
## Downloading file TD Files/LTN_2019.xls (3-20) Found file in folder, skipping it.
## Downloading file TD Files/LTN_2018.xls (4-20) Found file in folder, skipping it.
## Downloading file TD Files/LTN_2017.xls (5-20) Found file in folder, skipping it.
## Downloading file TD Files/LTN_2016.xls (6-20) Found file in folder, skipping it.
## Downloading file TD Files/LTN_2015.xls (7-20) Found file in folder, skipping it.
## Downloading file TD Files/LTN_2014.xls (8-20) Found file in folder, skipping it.
## Downloading file TD Files/LTN_2013.xls (9-20) Found file in folder, skipping it.
## Downloading file TD Files/LTN_2012.xls (10-20) Found file in folder, skipping it.
## Downloading file TD Files/LTN_2011.xls (11-20) Found file in folder, skipping it.
## Downloading file TD Files/LTN_2010.xls (12-20) Found file in folder, skipping it.
## Downloading file TD Files/LTN_2009.xls (13-20) Found file in folder, skipping it.
## Downloading file TD Files/LTN_2008.xls (14-20) Found file in folder, skipping it.
## Downloading file TD Files/LTN_2007.xls (15-20) Found file in folder, skipping it.
## Downloading file TD Files/LTN_2006.xls (16-20) Found file in folder, skipping it.
## Downloading file TD Files/LTN_2005.xls (17-20) Found file in folder, skipping it.
## Downloading file TD Files/LTN_2004.xls (18-20) Found file in folder, skipping it.
## Downloading file TD Files/LTN_2003.xls (19-20) Found file in folder, skipping it.
## Downloading file TD Files/LTN_2002.xls (20-20) Found file in folder, skipping it.
df_TD <- read.TD.files(asset.codes = codigo, 
                       maturity = maturidade)
## 
## Reading xls data and saving to data.frame
##  Reading File = TD Files/LTN_2002.xls
##     Cant find maturities in file  TD Files/LTN_2002.xls
##  Reading File = TD Files/LTN_2003.xls
##     Cant find maturities in file  TD Files/LTN_2003.xls
##  Reading File = TD Files/LTN_2004.xls
##     Cant find maturities in file  TD Files/LTN_2004.xls
##  Reading File = TD Files/LTN_2005.xls
##     Cant find maturities in file  TD Files/LTN_2005.xls
##  Reading File = TD Files/LTN_2006.xls
##     Cant find maturities in file  TD Files/LTN_2006.xls
##  Reading File = TD Files/LTN_2007.xls
##     Cant find maturities in file  TD Files/LTN_2007.xls
##  Reading File = TD Files/LTN_2008.xls
##     Cant find maturities in file  TD Files/LTN_2008.xls
##  Reading File = TD Files/LTN_2009.xls
##     Cant find maturities in file  TD Files/LTN_2009.xls
##  Reading File = TD Files/LTN_2010.xls
##     Cant find maturities in file  TD Files/LTN_2010.xls
##  Reading File = TD Files/LTN_2011.xls
##     Cant find maturities in file  TD Files/LTN_2011.xls
##  Reading File = TD Files/LTN_2012.xls
##     Cant find maturities in file  TD Files/LTN_2012.xls
##  Reading File = TD Files/LTN_2013.xls
##     Cant find maturities in file  TD Files/LTN_2013.xls
##  Reading File = TD Files/LTN_2014.xls
##     Cant find maturities in file  TD Files/LTN_2014.xls
##  Reading File = TD Files/LTN_2015.xls
##     Reading Sheet LTN 010121
##  Reading File = TD Files/LTN_2016.xls
##     Reading Sheet LTN 010121
##  Reading File = TD Files/LTN_2017.xls
##     Reading Sheet LTN 010121
##  Reading File = TD Files/LTN_2018.xls
##     Reading Sheet LTN 010121
##  Reading File = TD Files/LTN_2019.xls
##     Reading Sheet LTN 010121
##  Reading File = TD Files/LTN_2020.xls
##     Reading Sheet LTN 010121
##  Reading File = TD Files/LTN_2021.xls
##     Cant find maturities in file  TD Files/LTN_2021.xls
# verifica o dataframe
# informações sobre data de referência, yield (retorno), preço e dia de maturidade
dplyr::glimpse(df_TD)
## Rows: 1,439
## Columns: 5
## $ ref.date   <date> 2015-03-10, 2015-03-11, 2015-03-12, 2015-03-13, 2015-03-16~
## $ yield.bid  <dbl> 0.1324, 0.1310, 0.1304, 0.1354, 0.1335, 0.1336, 0.1302, 0.1~
## $ price.bid  <dbl> 487.04, 490.78, 492.53, 480.37, 485.28, 485.27, 493.99, 498~
## $ asset.code <chr> "LTN 010121", "LTN 010121", "LTN 010121", "LTN 010121", "LT~
## $ matur.date <date> 2021-01-01, 2021-01-01, 2021-01-01, 2021-01-01, 2021-01-01~
p1 <- ggplot(data = df_TD, aes(x = as.Date(ref.date), y = price.bid, color = codigo)) + 
  geom_line() + 
  scale_x_date() + 
  labs(title = '', 
       x = 'Data', 
       y = 'Preços')

p2 <- ggplot(data = df_TD, aes(x = as.Date(ref.date), y = yield.bid, color = codigo)) + 
   geom_line() + 
   scale_x_date() + 
   labs(title = '', x = 'Data', y = 'Retornos' ) + 
   scale_y_continuous(labels = scales::percent)

par(mfrow = c(2,1))  # gráfico em duas linhas e uma coluna
p1; p2

par(mfrow = c(1,1))  # retorna ao padrão gráfico

Como esperado de um título de dívida pré-fixado, os preços possuem uma tendência positiva. Este papel valerá exatamente R$1.000,00 na sua data de maturidade, em primeiro de janeiro de 2021.

Em contrapartida, os retornos do título estão em tendência de queda. Este resultado é esperado, pois a taxa SELIC está num nível muito baixo.

Exemplo 2: Diversas LTNs

As funções do pacote GetTDData também funcionam com vários argumentos para os parâmetros asset.codes e maturity. Suponhamos que desejamos visualizar todos os preços de todos os prazos disponíveis para títulos do tipo LTN a partir de 2010. Tudo o que precisamos fazer é adicionar o valor NULL ao argumento maturity e filtrar as datas:

codigo <- 'LTN'  # identificador do ativo
maturidades <- NULL  # todas as maturidades

minha_flag <- download.TD.data(asset.codes = codigo,
                               do.clean.up = FALSE)

# lê os dados e remove as datas anteriores a 2010
df_TD <- read.TD.files(asset.codes = codigo, maturity = maturidades) %>% 
            filter(ref.date >= as.Date('2010-01-01'))
p1 <- ggplot(data = df_TD, 
            aes(x = as.Date(ref.date), y = price.bid, color = asset.code)) + 
  geom_line() + scale_x_date() + labs(title = '', x = 'Datas', y = 'Preços' )

print(p1)

p2 <- ggplot(data = df_TD, aes(x = as.Date(ref.date), y = yield.bid, color = codigo)) + 
  geom_line() + 
  scale_x_date() + 
  labs(title = '', x = 'Data', y = 'Yields' ) + 
  scale_y_continuous(labels = scales::percent) 

print(p2)

Note como todos contratos do tipo LTN terminam com valor R$ 1.000,00 em sua data de expiração e possuem uma dinâmica com tendência de crescimento de preço aproximadamente linear ao longo do tempo.

Exemplo 3: Curva de juros

É possivel acessar a curva de juros atual do sistema financeiro brasileiro diretamente do site da Anbima. Para isso, basta utilizar a função get.yield.curve:

# obtem a curva de juros (yield curve)
df.juros <- get.yield.curve() 

# verifica o resultado 
dplyr:: glimpse(df.juros)
## Rows: 99
## Columns: 5
## $ n.biz.days   <dbl> 252, 378, 504, 630, 756, 882, 1008, 1134, 1260, 1386, 151~
## $ type         <chr> "real_return", "real_return", "real_return", "real_return~
## $ value        <dbl> 5.5161, 5.4333, 5.2473, 5.1022, 5.0062, 4.9469, 4.9126, 4~
## $ ref.date     <date> 2022-08-19, 2022-12-23, 2023-04-28, 2023-09-01, 2024-01-~
## $ current.date <date> 2021-12-10, 2021-12-10, 2021-12-10, 2021-12-10, 2021-12-~

Os dados incluem a curva de juros nominal, de juros real e da inflação. Vamos visualizar os dados:

p <- ggplot(df.juros, aes(x = ref.date, y = value)) + 
       geom_point() +   
       geom_line() +
       labs(y = 'Juros', 
            x = 'Data',
            title = 'Curva de Juros Corrente no Brasil',
            subtitle = format(Sys.Date(), '%d de %B de %Y'),
            caption = 'Dados da Anbima') +
       facet_wrap(~ type, scales = 'free') 

p

Esse código pode ser rodado a cada dia, mostrando a curva de juros atualizada.

GetDFPData

Este pacote (desenvolvido em 2017) provê uma interface aberta para todas as demonstrações financeiras distribuídas pela B3 e pela CVM nos sistemas DFP, FRE e FCA.

Os dados disponíveis são:

  • DFP - Demostrativos Financeiros Padronizados (annual financial reports)

  • FRE - Formulário de Referência (annual corporate events)

  • FCA - Formulário de Cadastro (annual registration information)

Exemplo: dados da AMBEV

library(GetDFPData)

df.info <- gdfpd.get.info.companies(type.data = 'companies')
## 
## Reading info file from github
## Found 49063 lines for 525 companies  [Actives =  524  Inactives =  1 ]
## Last file update:  2020-04-17
## Caching RDATA into tempdir()
glimpse(df.info)
## Rows: 525
## Columns: 16
## $ name.company         <chr> "521 PARTICIPAÇOES S.A. - EM LIQUIDAÇÃO EXTRAJUDI~
## $ id.company           <int> 16330, 16284, 24732, 21725, 18970, 22179, 23442, ~
## $ cnpj                 <dbl> 1.547749e+12, 1.851771e+12, 3.190798e+13, 1.03450~
## $ date.registration    <date> 1997-07-11, 1997-05-30, 2019-06-03, 2009-06-24, ~
## $ date.constitution    <date> 1996-07-30, 1997-04-02, 2018-08-22, 2008-08-18, ~
## $ city                 <chr> "RIO DE JANEIRO", "RIO DE JANEIRO", "SÃO PAULO", ~
## $ estate               <chr> "RJ", "RJ", "SP", "SP", "SP", "RJ", "SP", NA, "SP~
## $ situation            <chr> "ATIVO", "ATIVO", "ATIVO", "ATIVO", "ATIVO", "ATI~
## $ situation.operations <chr> "LIQUIDAÇÃO EXTRAJUDICIAL", "FASE OPERACIONAL", "~
## $ listing.segment      <chr> NA, "Tradicional", NA, "Tradicional", "Corporate ~
## $ main.sector          <chr> NA, "Outros", NA, "Saúde", "Utilidade Pública", "~
## $ sub.sector           <chr> NA, "Outros", NA, "Serv.Méd.Hospit..Análises e Di~
## $ segment              <chr> NA, "Outros", NA, "Serv.Méd.Hospit..Análises e Di~
## $ tickers              <chr> NA, "QVQP3B", NA, "ADHM3", "TIET11;TIET3;TIET4", ~
## $ first.date           <date> 2009-12-31, 2009-12-31, 2017-12-31, 2009-12-31, ~
## $ last.date            <date> 2019-12-31, 2019-12-31, 2019-12-31, 2018-12-31, ~

As empresas no banco de dados podem ser identificadas pelo seu nome oficial ou identificação numérica da CVM. A função gdfpd.search.company() permite que o usuário procure o nome oficial da empresa.

gdfpd.search.company('ambev')
## 
## Reading info file from github
## Found 49063 lines for 525 companies  [Actives =  524  Inactives =  1 ]
## Last file update:  2020-04-17
## Caching RDATA into tempdir()
## 
## Found 1 companies:
## AMBEV S.A. | situation = ATIVO | first date = 2012-12-31 | last date - 2019-12-31
## [1] "AMBEV S.A."

Usamos a função principal do pacote, gdfpd.GetDFPData, para baixar informações.

# opções
nome.companhias <- 'AMBEV S.A.'
inicio <- '2017-12-31'
fim  <- Sys.Date()

# baixa os dados
df.relatorios <- gdfpd.GetDFPData(name.companies = nome.companhias,
                                  first.date = inicio,
                                  last.date = fim)
## Found cache file. Loading data..
## 
## Downloading data for 1 companies
## First Date: 2017-12-31
## Laste Date: 2021-12-11
## Inflation index: dollar
## 
## Downloading inflation data
##  Caching inflation RDATA into tempdir()  Done
## 
## Inputs looking good! Starting download of files:
## 
## AMBEV S.A.
##  Available periods: 2017-12-31   2018-12-31  2019-12-31
## 
## 
## Processing 23264 - AMBEV S.A.
##  Finding info from Bovespa
##      Found BOV cache file
##  Processing 23264 - AMBEV S.A. | date 2017-12-31
##      Acessing DFP data | Found DFP cache file
##      Acessing FRE data | Found FRE cache file
##      Acessing FCA data | Found FCA cache file
##  Processing 23264 - AMBEV S.A. | date 2018-12-31
##      Acessing DFP data | Found DFP cache file
##      Acessing FRE data | Found FRE cache file
##      Acessing FCA data | Found FCA cache file
##  Processing 23264 - AMBEV S.A. | date 2019-12-31
##      Acessing DFP data | Found DFP cache file
##      Acessing FRE data | No FRE file available..
##      Acessing FCA data | No FCA file available..
glimpse(df.relatorios)
## Rows: 1
## Columns: 46
## $ company.name                     <chr> "AMBEV S.A."
## $ company.code                     <int> 23264
## $ cnpj                             <chr> "07526557000100"
## $ date.company.constitution        <date> 2005-07-08
## $ date.cvm.registration            <date> 2013-10-30
## $ company.tickers                  <chr> "ABEV3"
## $ min.date                         <date> 2017-12-31
## $ max.date                         <date> 2019-12-31
## $ n.periods                        <int> 3
## $ company.segment                  <chr> "Tradicional"
## $ current.stockholders             <list> [<data.frame[6 x 6]>]
## $ current.stock.composition        <list> [<data.frame[3 x 4]>]
## $ history.files                    <list> [<data.frame[1 x 2]>]
## $ fr.assets                        <list> [<data.frame[46 x 6]>]
## $ fr.liabilities                   <list> [<data.frame[75 x 6]>]
## $ fr.income                        <list> [<data.frame[78 x 6]>]
## $ fr.cashflow                      <list> [<data.frame[90 x 6]>]
## $ fr.value                         <list> [<data.frame[78 x 6]>]
## $ fr.assets.consolidated           <list> [<data.frame[45 x 6]>]
## $ fr.liabilities.consolidated      <list> [<data.frame[78 x 6]>]
## $ fr.income.consolidated           <list> [<data.frame[84 x 6]>]
## $ fr.cashflow.consolidated         <list> [<data.frame[82 x 6]>]
## $ fr.value.consolidated            <list> [<data.frame[78 x 6]>]
## $ fr.auditing.report               <list> [<data.frame[3 x 6]>]
## $ history.dividends                <list> [<data.frame[25 x 12]>]
## $ history.stockholders             <list> [<data.frame[12 x 15]>]
## $ history.capital.issues           <list> [<data.frame[4 x 6]>]
## $ history.mkt.value                <list> [<data.frame[2 x 6]>]
## $ history.capital.increases        <list> [<data.frame[12 x 9]>]
## $ history.capital.reductions       <list> [<data.frame[0 x 0]>]
## $ history.stock.repurchases        <list> [<data.frame[2 x 13]>]
## $ history.other.stock.events       <list> [<data.frame[0 x 0]>]
## $ history.compensation             <list> [<data.frame[2 x 19]>]
## $ history.compensation.summary     <list> [<data.frame[6 x 10]>]
## $ history.transactions.related     <list> [<data.frame[106 x 14]>]
## $ history.debt.composition         <list> [<data.frame[13 x 10]>]
## $ history.governance.listings      <list> [<data.frame[2 x 5]>]
## $ history.board.composition        <list> [<data.frame[59 x 19]>]
## $ history.committee.composition    <list> [<data.frame[15 x 19]>]
## $ history.family.relations         <list> [<data.frame[2 x 11]>]
## $ history.family.related.companies <list> [<data.frame[40 x 12]>]
## $ history.auditing                 <list> [<data.frame[8 x 11]>]
## $ history.responsible.docs         <list> [<data.frame[4 x 6]>]
## $ history.stocks.details           <list> [<data.frame[2 x 13]>]
## $ history.dividends.details        <list> [<data.frame[2 x 8]>]
## $ history.intangible               <list> [<data.frame[120 x 7]>]

df.relatorios$fr.assets[[1]] contem o balanço patrimonial da empresa.

AMBEV.BP <- df.relatorios$fr.assets[[1]]

glimpse(AMBEV.BP)
## Rows: 46
## Columns: 6
## $ name.company       <chr> "AMBEV S.A.", "AMBEV S.A.", "AMBEV S.A.", "AMBEV S.~
## $ ref.date           <date> 2017-12-31, 2017-12-31, 2017-12-31, 2017-12-31, 20~
## $ acc.number         <chr> "1", "1.01", "1.01.01", "1.01.02", "1.01.03", "1.01~
## $ acc.desc           <chr> "Ativo Total", "Ativo Circulante", "Caixa e Equival~
## $ acc.value          <dbl> 91568737, 11272513, 2017034, 631637, 3055953, 21072~
## $ acc.value.infl.adj <dbl> 27686018.32, 3408270.24, 609854.87, 190976.90, 9239~

GetDFPData2

Devido, principalmente, à instabilidade do website da B3 e ao longo tempo de processamento, Perlin decidiu separar o pacote GetDFPData. Os novos pacotes trabalham diretamente com o site ftp da CVM, que se mostra bastante confiável e de rápido acesso. Por exemplo, é possível baixar 10 anos de dados financeiros de todas as companhias em menos de 10 minutos.

O pacote GetDFPData2 (anteriormente chamado GetCVMData) não é compatível com GetDFPData, utilizando o site ftp da CVM e é dedicado a baixar apenas relatórios financeiros anuais e trimestrais.

Agora, a instalação do pacote pode ser feita diretamente do CRAN.

# hoje ainda não está no CRAN
install.packages('GetDFPData2')

Uma aplicação shiny – interface web – também está disponível.

Exemplo:

library(GetDFPData2)

# informações sobre as empresas
df_info <- get_info_companies(tempdir())
df_info 
search_company('grendene')

# baixando dados DFP
l_dfp <- get_dfp_data(companies_cvm_codes = 19615, 
                      use_memoise = FALSE,
                      clean_data = TRUE,
                      type_docs = c('DRE'), 
                      type_format = 'con',
                      first_year = 2020, 
                      last_year = 2021)

glimpse(l_dfp)
## List of 1
##  $ DF Consolidado - Demonstração do Resultado: tibble [32 x 16] (S3: tbl_df/tbl/data.frame)
##   ..$ CNPJ_CIA    : chr [1:32] "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" ...
##   ..$ CD_CVM      : num [1:32] 19615 19615 19615 19615 19615 ...
##   ..$ DT_REFER    : Date[1:32], format: "2020-12-31" "2020-12-31" ...
##   ..$ DT_INI_EXERC: Date[1:32], format: "2020-01-01" "2020-01-01" ...
##   ..$ DT_FIM_EXERC: Date[1:32], format: "2020-12-31" "2020-12-31" ...
##   ..$ DENOM_CIA   : chr [1:32] "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." ...
##   ..$ VERSAO      : num [1:32] 1 1 1 1 1 1 1 1 1 1 ...
##   ..$ GRUPO_DFP   : chr [1:32] "DF Consolidado - Demonstração do Resultado" "DF Consolidado - Demonstração do Resultado" "DF Consolidado - Demonstração do Resultado" "DF Consolidado - Demonstração do Resultado" ...
##   ..$ MOEDA       : chr [1:32] "REAL" "REAL" "REAL" "REAL" ...
##   ..$ ESCALA_MOEDA: chr [1:32] "MIL" "MIL" "MIL" "MIL" ...
##   ..$ ORDEM_EXERC : chr [1:32] "ÚLTIMO" "ÚLTIMO" "ÚLTIMO" "ÚLTIMO" ...
##   ..$ CD_CONTA    : chr [1:32] "3.01" "3.02" "3.03" "3.04" ...
##   ..$ DS_CONTA    : chr [1:32] "Receita de Venda de Bens e/ou Serviços" "Custo dos Bens e/ou Serviços Vendidos" "Resultado Bruto" "Despesas/Receitas Operacionais" ...
##   ..$ VL_CONTA    : num [1:32] 1896785 -1022330 874455 -573256 -431846 ...
##   ..$ COLUNA_DF   : logi [1:32] NA NA NA NA NA NA ...
##   ..$ source_file : chr [1:32] "dfp_cia_aberta_DRE_con_2020.csv" "dfp_cia_aberta_DRE_con_2020.csv" "dfp_cia_aberta_DRE_con_2020.csv" "dfp_cia_aberta_DRE_con_2020.csv" ...
dre_anual <- l_dfp$`DF Consolidado - Demonstração do Resultado`
head(dre_anual, 10)

GetFREData

GetFREData também utiliza o site ftp da CVM e importa apenas dados do sistema FRE.

A instalação do pacote deve ser feita diretamente do github de Perlin.

# hoje ainda não está no CRAN
devtools::install_github('msperlin/GetFREData')

Exemplo:

library(GetFREData)

search_company('grendene')
l_fre <- get_fre_data(companies_cvm_codes = 19615,
                      fre_to_read = 'last',
                      first_year = 2018,
                      last_year = 2020)

glimpse(l_fre)
## List of 21
##  $ df_stockholders            :'data.frame': 30 obs. of  18 variables:
##   ..$ CNPJ_CIA               : chr [1:30] "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" ...
##   ..$ DENOM_CIA              : chr [1:30] "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." ...
##   ..$ DT_REFER               : Date[1:30], format: "2018-01-01" "2018-01-01" ...
##   ..$ CD_CVM                 : num [1:30] 19615 19615 19615 19615 19615 ...
##   ..$ ID_DOC                 : num [1:30] 83396 83396 83396 83396 83396 ...
##   ..$ VERSAO                 : num [1:30] 16 16 16 16 16 16 16 16 16 16 ...
##   ..$ type.register          : chr [1:30] "Acionista" "Acionista" "Acionista" "Acionista" ...
##   ..$ id.person              : chr [1:30] "37071813833   " "09867597087   " "09864784072   " "68595743053   " ...
##   ..$ id.nationality         : chr [1:30] "Brasileira" "Brasileiro" "Brasileiro" "Brasileiro" ...
##   ..$ id.state               : chr [1:30] "São Paulo" "Rio Grande do Sul" "Rio Grande do Sul" "Rio Grande do Sul" ...
##   ..$ id.country             : logi [1:30] NA NA NA NA NA NA ...
##   ..$ name.stockholder       : chr [1:30] "Gabriella de Camargo Bartelle" "Alexandre Grendene Bartelle" "Pedro Grendene Bartelle" "Pedro Bartelle" ...
##   ..$ type.stockholder       : chr [1:30] "Fisica" "Fisica" "Fisica" "Fisica" ...
##   ..$ qtd.ord.shares         : chr [1:30] "28912677" "371651807" "125312376" "36465597" ...
##   ..$ perc.ord.shares        : chr [1:30] "3.200000" "41.200000" "13.890000" "4.040000" ...
##   ..$ qtd.pref.shares        : chr [1:30] "0" "0" "0" "0" ...
##   ..$ perc.pref.shares       : chr [1:30] "0.000000" "0.000000" "0.000000" "0.000000" ...
##   ..$ controlling.stockholder: logi [1:30] TRUE TRUE TRUE TRUE TRUE TRUE ...
##  $ df_capital                 :'data.frame': 6 obs. of  9 variables:
##   ..$ CNPJ_CIA   : chr [1:6] "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" ...
##   ..$ DENOM_CIA  : chr [1:6] "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." ...
##   ..$ DT_REFER   : Date[1:6], format: "2018-01-01" "2018-01-01" ...
##   ..$ CD_CVM     : num [1:6] 19615 19615 19615 19615 19615 ...
##   ..$ ID_DOC     : num [1:6] 83396 83396 94693 94693 103471 ...
##   ..$ VERSAO     : num [1:6] 16 16 18 18 11 11
##   ..$ stock.type : chr [1:6] "ON" "PN" "ON" "PN" ...
##   ..$ stock.class: chr [1:6] "0" "0" "0" "0" ...
##   ..$ qtd.issued : num [1:6] 9.02e+08 0.00 9.02e+08 0.00 9.02e+08 ...
##  $ df_stock_values            :'data.frame': 6 obs. of  13 variables:
##   ..$ CNPJ_CIA              : chr [1:6] "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" ...
##   ..$ DENOM_CIA             : chr [1:6] "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." ...
##   ..$ DT_REFER              : Date[1:6], format: "2018-01-01" "2018-01-01" ...
##   ..$ CD_CVM                : num [1:6] 19615 19615 19615 19615 19615 ...
##   ..$ ID_DOC                : num [1:6] 83396 83396 94693 94693 103471 ...
##   ..$ VERSAO                : num [1:6] 16 16 18 18 11 11
##   ..$ stock.class           : chr [1:6] "0" "0" "0" "0" ...
##   ..$ stock.type            : chr [1:6] "ON" "PN" "ON" "PN" ...
##   ..$ max.price             : num [1:6] 28.8 0 8.24 0 12.65 ...
##   ..$ min.price             : num [1:6] 25.32 0 6.59 0 7.94 ...
##   ..$ avg.price             : num [1:6] 26.7 0 7.6 0 10.5 ...
##   ..$ flag.missing.avg.price: logi [1:6] FALSE NA FALSE NA FALSE NA
##   ..$ qtd.issued            : num [1:6] 9.02e+08 0.00 9.02e+08 0.00 9.02e+08 ...
##  $ df_mkt_value               :'data.frame': 3 obs. of  9 variables:
##   ..$ CNPJ_CIA     : chr [1:3] "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60"
##   ..$ DENOM_CIA    : chr [1:3] "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A."
##   ..$ DT_REFER     : Date[1:3], format: "2018-01-01" "2019-01-01" ...
##   ..$ CD_CVM       : num [1:3] 19615 19615 19615
##   ..$ ID_DOC       : num [1:3] 83396 94693 103471
##   ..$ VERSAO       : num [1:3] 16 18 11
##   ..$ mkt.avg.value: num [1:3] 2.41e+10 6.86e+09 9.44e+09
##   ..$ mkt.min.value: num [1:3] 2.28e+10 5.95e+09 7.16e+09
##   ..$ mkt.max.value: num [1:3] 2.60e+10 7.43e+09 1.14e+10
##  $ df_increase_capital        :'data.frame': 0 obs. of  0 variables
##  $ df_capital_reduction       :'data.frame': 0 obs. of  0 variables
##  $ df_compensation            :'data.frame': 3 obs. of  22 variables:
##   ..$ CNPJ_CIA                          : chr [1:3] "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60"
##   ..$ DENOM_CIA                         : chr [1:3] "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A."
##   ..$ DT_REFER                          : Date[1:3], format: "2018-01-01" "2019-01-01" ...
##   ..$ CD_CVM                            : num [1:3] 19615 19615 19615
##   ..$ ID_DOC                            : num [1:3] 83396 94693 103471
##   ..$ VERSAO                            : num [1:3] 16 18 11
##   ..$ level.remuneration                : chr [1:3] "Management Council" "Management Council" "Management Council"
##   ..$ qtd.members                       : num [1:3] 6 6 6
##   ..$ qtd.remunerated.members           : num [1:3] 6 6 6
##   ..$ total.value.remuneration          : num [1:3] 1116000 1146000 1188000
##   ..$ fixed.salary                      : num [1:3] 1116000 1146000 1188000
##   ..$ fixed.benefits                    : num [1:3] 0 0 0
##   ..$ fixed.participations              : num [1:3] 0 0 0
##   ..$ fixed.others                      : num [1:3] 0 0 0
##   ..$ variable.bonus                    : num [1:3] 0 0 0
##   ..$ variable.results.participation    : num [1:3] 0 0 0
##   ..$ variable.meetings.participation   : num [1:3] 0 0 0
##   ..$ variable.commissions.participation: num [1:3] 0 0 0
##   ..$ variable.others                   : num [1:3] 0 0 0
##   ..$ post.job.compensation             : num [1:3] 0 0 0
##   ..$ ceasing.job.compensation          : num [1:3] 0 0 0
##   ..$ stocks.options.benefits           : num [1:3] 0 0 0
##  $ df_compensation_summary    :'data.frame': 9 obs. of  13 variables:
##   ..$ CNPJ_CIA               : chr [1:9] "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" ...
##   ..$ DENOM_CIA              : chr [1:9] "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." ...
##   ..$ DT_REFER               : Date[1:9], format: "2018-01-01" "2018-01-01" ...
##   ..$ CD_CVM                 : num [1:9] 19615 19615 19615 19615 19615 ...
##   ..$ ID_DOC                 : num [1:9] 83396 83396 83396 94693 94693 ...
##   ..$ VERSAO                 : num [1:9] 16 16 16 18 18 18 11 11 11
##   ..$ level.remuneration     : chr [1:9] "Management Council" "Statutory Directors" "Fiscal Council" "Management Council" ...
##   ..$ qtd.members            : num [1:9] 6 3 3 6 3 3 6 3 3
##   ..$ qtd.remunerated.members: num [1:9] 6 3 3 6 3 3 6 3 3
##   ..$ max.remuneration       : num [1:9] 186000 2748408 142500 191000 2876477 ...
##   ..$ mean.remuneration      : num [1:9] 186000 2050482 142500 191000 2134281 ...
##   ..$ min.remuneration       : num [1:9] 186000 1423997 142500 191000 1468768 ...
##   ..$ observations           : logi [1:9] NA NA NA NA NA NA ...
##  $ df_transactions_related    :'data.frame': 127 obs. of  17 variables:
##   ..$ CNPJ_CIA                      : chr [1:127] "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" ...
##   ..$ DENOM_CIA                     : chr [1:127] "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." ...
##   ..$ DT_REFER                      : Date[1:127], format: "2018-01-01" "2018-01-01" ...
##   ..$ CD_CVM                        : num [1:127] 19615 19615 19615 19615 19615 ...
##   ..$ ID_DOC                        : num [1:127] 83396 83396 83396 83396 83396 ...
##   ..$ VERSAO                        : num [1:127] 16 16 16 16 16 16 16 16 16 16 ...
##   ..$ id.transaction                : chr [1:127] "2403" "2404" "2405" "2406" ...
##   ..$ name.related.part             : chr [1:127] "Mailson da Nóbrega Consultoria S/C Ltda" "Vulcabras|Azaleia Argentina S.A." "Mailson da Nóbrega Consultoria S/C Ltda" "Grendene USA, Inc" ...
##   ..$ date.transaction              : Date[1:127], format: "2016-12-31" "2015-12-31" ...
##   ..$ description.related.part      : chr [1:127] "Empresa pertencente a membro do Conselho de Administração" "Empresa controlada por acionista da Grendene S.A." "Empresa pertencente a membro do Conselho de Administração" "Empresa controlada" ...
##   ..$ description.transaction       : chr [1:127] "Assessoria na área econômica financeira" "Cliente - venda de insumos" "Assessoria na área econômica financeira" "Cliente - venda de calçados para abastecimento do mercado onde a mesma está sediada" ...
##   ..$ value.transaction             : chr [1:127] "72000.00" "306000.00" "72000.00" "14641000.00" ...
##   ..$ description.guarantees        : chr [1:127] "Não aplicável" "Não aplicável" "Não aplicável" "Não aplicável" ...
##   ..$ description.transaction.period: chr [1:127] "Prazo indeterminado" "Prazo indeterminado" "Prazo indeterminado" "Prazo indeterminado" ...
##   ..$ description.rescision         : chr [1:127] "Encerramento das atividades" "Encerramento das atividades" "Encerramento das atividades" "Encerramento das atividades" ...
##   ..$ interest.rate                 : num [1:127] 0 0 0 0 0 0 0 0 0 0 ...
##   ..$ value.balance                 : chr [1:127] "R$0,00" "R$0,00" "R$0,00" "R$9.311.000,00" ...
##  $ df_other_events            :'data.frame': 3 obs. of  12 variables:
##   ..$ CNPJ_CIA              : chr [1:3] "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60"
##   ..$ DENOM_CIA             : chr [1:3] "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A."
##   ..$ DT_REFER              : Date[1:3], format: "2018-01-01" "2019-01-01" ...
##   ..$ CD_CVM                : num [1:3] 19615 19615 19615
##   ..$ ID_DOC                : num [1:3] 83396 94693 103471
##   ..$ VERSAO                : num [1:3] 16 18 11
##   ..$ approval.date         : Date[1:3], format: "2018-04-23" "2018-04-23" ...
##   ..$ type.event            : chr [1:3] "Desdobramento" "Desdobramento" "Desdobramento"
##   ..$ qtd.ord.shares.before : num [1:3] 3.01e+08 3.01e+08 3.01e+08
##   ..$ qtd.ord.shares.after  : num [1:3] 9.02e+08 9.02e+08 9.02e+08
##   ..$ qtd.pref.shares.before: num [1:3] 0 0 0
##   ..$ qtd.pref.shares.after : num [1:3] 0 0 0
##  $ df_stock_repurchases       :'data.frame': 12 obs. of  16 variables:
##   ..$ CNPJ_CIA                     : chr [1:12] "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" ...
##   ..$ DENOM_CIA                    : chr [1:12] "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." ...
##   ..$ DT_REFER                     : Date[1:12], format: "2018-01-01" "2018-01-01" ...
##   ..$ CD_CVM                       : num [1:12] 19615 19615 19615 19615 19615 ...
##   ..$ ID_DOC                       : num [1:12] 83396 83396 83396 83396 94693 ...
##   ..$ VERSAO                       : num [1:12] 16 16 16 16 18 18 18 18 11 11 ...
##   ..$ date.decision                : Date[1:12], format: "2017-07-27" "2016-02-25" ...
##   ..$ date.start.repurchase        : Date[1:12], format: "2017-08-25" "2016-02-26" ...
##   ..$ date.end.repurchase          : Date[1:12], format: "2019-02-21" "2017-08-24" ...
##   ..$ available.capital.repurchase : num [1:12] 14563536 16117227 17000000 19072706 29188481 ...
##   ..$ type.stock                   : chr [1:12] "Ordinária" "Ordinária" "Ordinária" "Ordinária" ...
##   ..$ qtd.stocks.repurchased       : num [1:12] 1312343 547841 0 487096 130000 ...
##   ..$ qtd.stocks.predicted         : num [1:12] 2.0e+06 1.5e+06 1.5e+06 1.5e+06 6.0e+06 2.0e+06 1.5e+06 1.5e+06 2.5e+07 6.0e+06 ...
##   ..$ average.price                : num [1:12] 26.78 17.96 0 14.38 7.36 ...
##   ..$ percent.stock.float.purchased: num [1:12] 65.6 36.5 0 32.47 2.17 ...
##   ..$ percent.stock.float.predicted: chr [1:12] "2.380000" "1.820000" "1.910000" "1.950000" ...
##  $ df_debt_composition        :'data.frame': 6 obs. of  13 variables:
##   ..$ CNPJ_CIA               : chr [1:6] "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" ...
##   ..$ DENOM_CIA              : chr [1:6] "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." ...
##   ..$ DT_REFER               : Date[1:6], format: "2018-01-01" "2018-01-01" ...
##   ..$ CD_CVM                 : num [1:6] 19615 19615 19615 19615 19615 ...
##   ..$ ID_DOC                 : num [1:6] 83396 83396 94693 94693 103471 ...
##   ..$ VERSAO                 : num [1:6] 16 16 18 18 11 11
##   ..$ type.debt              : chr [1:6] "Empréstimo" "Financiamento" "Empréstimo" "Financiamento" ...
##   ..$ type.debt.guarantee    : chr [1:6] "Garantia Real" "Quirografárias" "Garantia Real" "Quirografárias" ...
##   ..$ debt.value.under.1.year: num [1:6] 1.08e+07 3.11e+08 1.07e+07 3.56e+08 1.04e+07 ...
##   ..$ debt.value.1.to.3.years: num [1:6] 31389447 2412999 20681054 6930075 10340527 ...
##   ..$ debt.value.3.to.5.years: num [1:6] 0 2522127 0 1194397 0 ...
##   ..$ debt.value.more.5.years: num [1:6] 0 0 0 0 0 0
##   ..$ debt.total             : num [1:6] 4.22e+07 3.16e+08 3.14e+07 3.64e+08 2.07e+07 ...
##  $ df_board_composition       :'data.frame': 47 obs. of  22 variables:
##   ..$ CNPJ_CIA                : chr [1:47] "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" ...
##   ..$ DENOM_CIA               : chr [1:47] "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." ...
##   ..$ DT_REFER                : Date[1:47], format: "2018-01-01" "2018-01-01" ...
##   ..$ CD_CVM                  : num [1:47] 19615 19615 19615 19615 19615 ...
##   ..$ ID_DOC                  : num [1:47] 83396 83396 83396 83396 83396 ...
##   ..$ VERSAO                  : num [1:47] 16 16 16 16 16 16 16 16 16 16 ...
##   ..$ person.name             : chr [1:47] "Gelson Luis Rostirolla" "Rudimar Dall Onder" "Francisco Olinto Velo Schmitt" "Alexandre Grendene Bartelle" ...
##   ..$ person.cpf              : num [1:47] 1.48e+10 2.55e+10 2.64e+10 9.87e+09 4.30e+09 ...
##   ..$ person.profession       : chr [1:47] "Administrador de Empresas" "Engenheiro Mecânico" "Engenheiro Elétrico" "Industrial" ...
##   ..$ person.cv               : chr [1:47] "Formação: Administração de Empresas (1977) e Ciências Contábeis (1979) pela UNOESC – Universidade do Oeste Cata"| __truncated__ "Formação: Engenharia Mecânica (1981) pela Universidade de Caxias do SUL (UCS). Iniciou suas atividades na Compa"| __truncated__ "Formação: Engenharia Elétrica pela Universidade Federal do Rio Grande do Sul em 1978; Especialização e Mestrado"| __truncated__ "Fundador da Companhia e Presidente do Conselho de Administração desde 18 de agosto de 2004. \n\nFormação: Bacha"| __truncated__ ...
##   ..$ person.dob              : Date[1:47], format: "1953-02-14" "1956-08-14" ...
##   ..$ code.type.board         : chr [1:47] "1" "1" "1" "2" ...
##   ..$ desc.type.board         : chr [1:47] "Director" "Director" "Director" "Management Council" ...
##   ..$ desc.type.board2        : logi [1:47] NA NA NA NA NA NA ...
##   ..$ code.type.job           : chr [1:47] "11" "10" "12" "20" ...
##   ..$ desc.job                : chr [1:47] "Não ocupa outras funções no emissor." "Não ocupa outras funções no emissor." "Diretor Administrativo Financeiro" "Presidente do comitê de gestão do programa de stock option." ...
##   ..$ date.election           : Date[1:47], format: "2019-02-14" "2019-02-14" ...
##   ..$ date.effective          : Date[1:47], format: "2019-02-14" "2019-02-14" ...
##   ..$ mandate.duration        : chr [1:47] "3 anos" "3 anos" "3 anos" "2 anos" ...
##   ..$ ellected.by.controller  : logi [1:47] TRUE TRUE TRUE TRUE TRUE TRUE ...
##   ..$ qtd.consecutive.mandates: num [1:47] 6 6 5 8 8 8 8 8 7 9 ...
##   ..$ percentage.participation: num [1:47] 0 0 0 100 100 100 100 100 100 0 ...
##  $ df_committee_composition   :'data.frame': 30 obs. of  22 variables:
##   ..$ CNPJ_CIA                : chr [1:30] "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" ...
##   ..$ DENOM_CIA               : chr [1:30] "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." ...
##   ..$ DT_REFER                : Date[1:30], format: "2018-01-01" "2018-01-01" ...
##   ..$ CD_CVM                  : num [1:30] 19615 19615 19615 19615 19615 ...
##   ..$ ID_DOC                  : num [1:30] 83396 83396 83396 94693 94693 ...
##   ..$ VERSAO                  : num [1:30] 16 16 16 18 18 18 18 18 18 18 ...
##   ..$ person.name             : chr [1:30] "Alexandre Grendene Bartelle" "Pedro Grendene Bartelle" "Renato Ochman" "Pedro Grendene Bartelle" ...
##   ..$ person.cpf              : num [1:30] 9.87e+09 9.86e+09 3.76e+10 9.86e+09 9.86e+09 ...
##   ..$ person.profession       : chr [1:30] "Industrial" "Industrial" "Advogado" "Industrial" ...
##   ..$ person.cv               : chr [1:30] "Fundador da Companhia e Presidente do Conselho de Administração desde 18 de agosto de 2004. \n\nFormação: Bacha"| __truncated__ "Fundador da Companhia. Vice-Presidente do Conselho de Administração desde 18 de agosto de 2004. \n\nFormação: B"| __truncated__ "Membro do Conselho de Administração desde 18 de agosto de 2004. \n\nFormação: Advogado, Bacharel em Direito pel"| __truncated__ NA ...
##   ..$ person.dob              : Date[1:30], format: "1950-01-23" "1950-01-23" ...
##   ..$ code.type.committee     : chr [1:30] "9" "9" "9" "9" ...
##   ..$ desc.type.committee     : chr [1:30] "Other Committee" "Other Committee" "Other Committee" "Other Committee" ...
##   ..$ code.type.job           : chr [1:30] "1" "3" "3" "3" ...
##   ..$ desc.committee          : chr [1:30] "Gestão do Programa de Stock Option" "Gestão do Programa de Stock Option" "Gestão do Programa de Stock Option" "Gestão do Programa de Stock Option" ...
##   ..$ desc.job                : chr [1:30] "Presidente do Conselho de Administração" "Vice presidente do Conselho de Administração" "Membro do Conselho de Administração" "Vice presidente do Conselho de Administração e membro do Comitê de Investimentos" ...
##   ..$ date.election           : Date[1:30], format: "2015-02-12" "2015-02-12" ...
##   ..$ date.effective          : Date[1:30], format: "2015-02-12" "2015-02-12" ...
##   ..$ mandate.duration        : chr [1:30] "indeterminado" "Indeterminado" "Indeterminado" "Indeterminado" ...
##   ..$ qtd.consecutive.mandates: num [1:30] 1 1 1 1 1 1 1 1 1 1 ...
##   ..$ percentage.participation: num [1:30] 100 100 100 100 100 100 100 100 100 100 ...
##   ..$ other.committes         : chr [1:30] "Gestão do Programa de Stock Option" "Gestão do Programa de Stock Option" "Gestão do Programa de Stock Option" "Gestão do Programa de Stock Option" ...
##  $ df_family_relations        :'data.frame': 20 obs. of  14 variables:
##   ..$ CNPJ_CIA           : chr [1:20] "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" ...
##   ..$ DENOM_CIA          : chr [1:20] "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." ...
##   ..$ DT_REFER           : Date[1:20], format: "2018-01-01" "2018-01-01" ...
##   ..$ CD_CVM             : num [1:20] 19615 19615 19615 19615 19615 ...
##   ..$ ID_DOC             : num [1:20] 83396 83396 83396 83396 83396 ...
##   ..$ VERSAO             : num [1:20] 16 16 16 16 16 16 16 16 18 18 ...
##   ..$ person.name        : chr [1:20] "Pedro Grendene Bartelle" "Pedro Grendene Bartelle" "Alexandre Grendene Bartelle" "Alexandre Grendene Bartelle" ...
##   ..$ person.cpf         : num [1:20] 9.86e+09 9.86e+09 9.87e+09 9.87e+09 9.86e+09 ...
##   ..$ person.job         : chr [1:20] "Vice Presidente do Conselho de Administração" "Diretor Vice Presidente" "Presidente do Conselho de Administração" "Diretor Presidente" ...
##   ..$ related.person.name: chr [1:20] "Alexandre Grendene Bartelle" "Alexandre Grendene Bartelle" "Pedro Grendene Bartelle" "Pedro Grendene Bartelle" ...
##   ..$ related.person.cpf : num [1:20] 9.87e+09 9.87e+09 9.86e+09 9.86e+09 6.86e+10 ...
##   ..$ related.person.job : chr [1:20] "Presidente do Conselho de Administração" "Diretor Presidente" "Vice Presidente do Conselho de Administração" "Diretor Vice Presidente" ...
##   ..$ code.relationship  : chr [1:20] "2" "2" "2" "2" ...
##   ..$ desc.relationship  : chr [1:20] "Irmão ou Irmã (1º grau por consangüinidade)" "Irmão ou Irmã (1º grau por consangüinidade)" "Irmão ou Irmã (1º grau por consangüinidade)" "Irmão ou Irmã (1º grau por consangüinidade)" ...
##  $ df_family_related_companies:'data.frame': 54 obs. of  15 variables:
##   ..$ CNPJ_CIA            : chr [1:54] "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" ...
##   ..$ DENOM_CIA           : chr [1:54] "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." ...
##   ..$ DT_REFER            : Date[1:54], format: "2018-01-01" "2018-01-01" ...
##   ..$ CD_CVM              : num [1:54] 19615 19615 19615 19615 19615 ...
##   ..$ ID_DOC              : num [1:54] 83396 83396 83396 83396 83396 ...
##   ..$ VERSAO              : num [1:54] 16 16 16 16 16 16 16 16 16 16 ...
##   ..$ person.name         : chr [1:54] "Pedro Grendene Bartelle" "Pedro Grendene Bartelle" "Pedro Grendene Bartelle" "Maílson Ferreira da Nóbrega" ...
##   ..$ person.cpf          : num [1:54] 9.86e+09 9.86e+09 9.86e+09 4.30e+09 3.76e+10 ...
##   ..$ person.job          : chr [1:54] "Vice-Presidente do Conselho de Administração" "Vice-Presidente do Conselho de Administração" "Vice-Presidente do Conselho de Administração" "Conselheiro de Administração" ...
##   ..$ type.related.person : chr [1:54] "Cliente" "Fornecedor" "Cliente" "Fornecedor" ...
##   ..$ type.relationship   : chr [1:54] "Controle" "Controle" "Controle" "Controle" ...
##   ..$ observations        : chr [1:54] "Venda de insumos e matrizes utilizados na produção de calçados - prazo médio de recebimento 32 dias." "Compra de serviços referente comissões - Prazo médio de pagamentos 11 dias" "Venda de matrizes utilizadas na produção de calçados - Prazo médio de recebimento 33 dias." "Assessoria" ...
##   ..$ related.company.name: chr [1:54] "Vulcabras|Azaleia - CE, Calçados e Artigos Esportivos S.A." "Vulcabras|Azaleia - CE, Calçados e Artigos Esportivos S.A." "Vulcabras|Azaleia - BA, Calçados e Artigos Esportivos S.A." "Mailson da Nóbrega Consultoria S/C Ltda" ...
##   ..$ related.company.cnpj: num [1:54] 9.54e+11 9.54e+11 7.34e+11 1.58e+12 6.24e+13 ...
##   ..$ related.company.job : chr [1:54] "Acionista controlador" "Acionista controlados" "Acionista controlador" "Sócio proprietário" ...
##  $ df_auditing                :'data.frame': 5 obs. of  14 variables:
##   ..$ CNPJ_CIA                  : chr [1:5] "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" ...
##   ..$ DENOM_CIA                 : chr [1:5] "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." ...
##   ..$ DT_REFER                  : Date[1:5], format: "2018-01-01" "2018-01-01" ...
##   ..$ CD_CVM                    : num [1:5] 19615 19615 19615 19615 19615
##   ..$ ID_DOC                    : num [1:5] 83396 83396 94693 94693 103471
##   ..$ VERSAO                    : num [1:5] 16 16 18 18 11
##   ..$ auditor.name              : chr [1:5] "PRICEWATERHOUSECOOPERS AUDITORES INDEPENDENTES (PWC)" "Ernst & Young Auditores Independentes S/S" "PRICEWATERHOUSECOOPERS AUDITORES INDEPENDENTES (PWC)" "Ernst & Young Auditores Independentes S/S" ...
##   ..$ auditor.cnpj              : chr [1:5] "61562112000635" "61366936000206" "61562112000635" "61366936001105" ...
##   ..$ contract.first.date       : Date[1:5], format: "2012-01-01" "2017-01-01" ...
##   ..$ contract.last.date        : Date[1:5], format: "2016-12-31" NA ...
##   ..$ description.contract      : chr [1:5] "Revisão dos ITR's (Controladora e Consolidado) e auditoria anual de balanço da Controladora e Consolidado." "Revisão dos ITR's (controladora e Consolidado) e auditoria anual de balanço da Controladora e Consolidado." "Revisão dos ITR's (Controladora e Consolidado) e auditoria anual de balanço da Controladora e Consolidado." "Revisão dos ITR's (controladora e Consolidado) e auditoria anual de balanço da Controladora e Consolidado." ...
##   ..$ compensation              : chr [1:5] "No exercício social encerrado em 31/12/2016 o montante total da remuneração dos auditores independentes foi R$4"| __truncated__ "Para o exercício encerrado em 31/12/2017 - R$409,2 mil, referente a serviços de auditoria prestados e R$131,1 m"| __truncated__ "No exercício social encerrado em 31/12/2016 o montante total da remuneração dos auditores independentes foi R$4"| __truncated__ "Para o exercício encerrado em 31/12/2017 - R$409,2 mil, referente a serviços de auditoria prestados e R$131,1 m"| __truncated__ ...
##   ..$ justification.substitution: chr [1:5] "Substituição em cumprimento à Instrução da Comissão de Valores Mobiliários nº 308/99 (art.31), que determina a "| __truncated__ NA "Substituição em cumprimento à Instrução da Comissão de Valores Mobiliários nº 308/99 (art.31), que determina a "| __truncated__ NA ...
##   ..$ reason.discordance        : chr [1:5] "Não houve discordância" NA "Não houve discordância" NA ...
##  $ df_responsible_docs        :'data.frame': 6 obs. of  9 variables:
##   ..$ CNPJ_CIA   : chr [1:6] "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" ...
##   ..$ DENOM_CIA  : chr [1:6] "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." ...
##   ..$ DT_REFER   : Date[1:6], format: "2018-01-01" "2018-01-01" ...
##   ..$ CD_CVM     : num [1:6] 19615 19615 19615 19615 19615 ...
##   ..$ ID_DOC     : num [1:6] 83396 83396 94693 94693 103471 ...
##   ..$ VERSAO     : num [1:6] 16 16 18 18 11 11
##   ..$ person.cod : chr [1:6] "66" "67" "38" "39" ...
##   ..$ person.name: chr [1:6] "Rudimar Dall Onder" "Francisco Olinto Velo Schmitt" "Rudimar Dall Onder" "Alceu Demartini de Albuquerque" ...
##   ..$ person.job : chr [1:6] "Diretor Presidente" "Diretor de Relações com Investidores" "Diretor Presidente" "Diretor de Relações com Investidores" ...
##  $ df_stocks_details          :'data.frame': 3 obs. of  16 variables:
##   ..$ CNPJ_CIA           : chr [1:3] "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60"
##   ..$ DENOM_CIA          : chr [1:3] "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A."
##   ..$ DT_REFER           : Date[1:3], format: "2018-01-01" "2019-01-01" ...
##   ..$ CD_CVM             : num [1:3] 19615 19615 19615
##   ..$ ID_DOC             : num [1:3] 83396 94693 103471
##   ..$ VERSAO             : num [1:3] 16 18 11
##   ..$ type.stock.id      : chr [1:3] "1" "1" "1"
##   ..$ type.stock.text    : chr [1:3] "Ordinária" "Ordinária" "Ordinária"
##   ..$ tag.along          : num [1:3] 100 100 100
##   ..$ preferential.code  : chr [1:3] "0" "0" "0"
##   ..$ preferential.text  : logi [1:3] NA NA NA
##   ..$ dividend.text      : chr [1:3] "Conforme o Estatuto Social da Companhia, art.32, os acionistas fazem jus a dividendo obrigatório anual equivale"| __truncated__ "Conforme o Estatuto Social da Companhia, art.32, os acionistas fazem jus a dividendo obrigatório anual equivale"| __truncated__ "Conforme o Estatuto Social da Companhia, art.32, os acionistas fazem jus a dividendo obrigatório anual equivale"| __truncated__
##   ..$ flag.voting.rights : chr [1:3] "1" "1" "1"
##   ..$ flag.voting.text   : chr [1:3] "Pleno" "Pleno" "Pleno"
##   ..$ flag.conversibility: chr [1:3] "Não" "Não" "Não"
##   ..$ other.info.text    : chr [1:3] "Não existem características relevantes adicionais." "Não existem características relevantes adicionais." "Não existem características relevantes adicionais."
##  $ df_dividends_details       :'data.frame': 3 obs. of  11 variables:
##   ..$ CNPJ_CIA            : chr [1:3] "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60"
##   ..$ DENOM_CIA           : chr [1:3] "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A."
##   ..$ DT_REFER            : Date[1:3], format: "2018-01-01" "2019-01-01" ...
##   ..$ CD_CVM              : num [1:3] 19615 19615 19615
##   ..$ ID_DOC              : num [1:3] 83396 94693 103471
##   ..$ VERSAO              : num [1:3] 16 18 11
##   ..$ net.profit          : num [1:3] 6.61e+08 5.86e+08 4.95e+08
##   ..$ distributed.dividend: num [1:3] 3.78e+08 3.15e+08 2.76e+08
##   ..$ retained.profit     : num [1:3] 2.74e+08 2.70e+08 2.19e+08
##   ..$ payout              : num [1:3] 57.2 53.8 55.7
##   ..$ div.yeild.on.equity : num [1:3] 22.6 18.2 14.3
##  $ df_intangible_details      :'data.frame': 38 obs. of  10 variables:
##   ..$ CNPJ_CIA   : chr [1:38] "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" "89.850.341/0001-60" ...
##   ..$ DENOM_CIA  : chr [1:38] "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." "GRENDENE S.A." ...
##   ..$ DT_REFER   : Date[1:38], format: "2018-01-01" "2018-01-01" ...
##   ..$ CD_CVM     : num [1:38] 19615 19615 19615 19615 19615 ...
##   ..$ ID_DOC     : num [1:38] 83396 83396 83396 83396 83396 ...
##   ..$ VERSAO     : num [1:38] 16 16 16 16 16 16 16 16 16 16 ...
##   ..$ id         : num [1:38] 1111 1112 1113 1114 1115 ...
##   ..$ id.type    : num [1:38] 2 2 2 2 2 2 2 2 2 2 ...
##   ..$ patent.desc: chr [1:38] "Zaxy" "Mel" "Cartago" "Rider" ...
##   ..$ duration   : Date[1:38], format: NA NA ...

APIs

Uma API, ou Application Program Interface, é basicamente um mensageiro que recebe uma solicitação, diz a um sistema o que você quer fazer e, em seguida, retorna a resposta para você. Uma API RESTful é uma API que usa solicitações HTTP para GET, PUT, POST e DELETE dados. O pacote httr é uma ferramenta útil para trabalhar com HTTP. Cada API tem seu uso e documentação muito específicos.

# instale o pacote
#install.packages('httr')

# carregue o pacote na memória
library(httr)

Downloads no CRAN

A API do CRAN baixa bases de dados. A documentação está disponível aqui.

Exemplo. Qual foi o pacote mais baixado no último mês?

urlBase <- 'https://cranlogs.r-pkg.org/'             # url básico. Ver documentação
endPoint <- 'top/'                                   # endpoint. Ver documentação
periodo <- 'last-month/'                             # parâmetro. Ver documentação
contagem <- 1                                        # parâmetro. Ver documentação
url <- paste0(urlBase, endPoint, periodo, contagem)  # construa toda a url 
x <- GET(url)                                        # recupere a url
dados <- content(x)                                  # extraia os dados
dados                                                # mostra os dados
## $start
## [1] "2021-11-10T00:00:00.000Z"
## 
## $end
## [1] "2021-12-09T00:00:00.000Z"
## 
## $downloads
## $downloads[[1]]
## $downloads[[1]]$package
## [1] "ggplot2"
## 
## $downloads[[1]]$downloads
## [1] "3017030"

O pacote mais baixado entre 10 de novembro de 2021 e 09 de dezembro de 2021 foi ggplot2 com um total de 3017030 downloads.

API KuCoin

A API da KuCoin, uma bolsa de criptomoedas. A documentação está disponível aqui.

Exemplo. Recuperar e fazer o gráfico dos preços de Bitcoin a cada minuto nas últimas 24 horas.

# Escolha o fuso horário. Ver documentação
Sys.setenv(TZ = Sys.timezone()) 

# base url. Ver documentação
urlBase <- 'https://api.kucoin.com'  

# endpoint. Ver documentação
endpoint <- '/api/v1/market/candles'  

# hoje e ontem em segundos
hoje <- as.integer(as.numeric(Sys.time()))  
ontem <- hoje - 24*60*60

# parâmetros da API. Ver documentação
param <- c(symbol = 'BTC-USDT', type = '1min', startAt = ontem, endAt = hoje)

# construa toda a url. Ver documentação
url <- paste0(urlBase, endpoint, '?', paste(names(param), param, sep = '=', collapse = '&')) 

# recupere a url
x <- GET(url) 

# extraia os dados
x <- content(x)      
dados <- x$data

# formatação
dados <- sapply(1:length(dados), 
                function(i) {
               # extraia um único candle
                   candle <- as.numeric(dados[[i]])
                   return( c(time = candle[1], 
                             open = candle[2], 
                             close = candle[3], 
                             high = candle[4], 
                             low = candle[5]) )
                }
         )

# converta para xts
datetime <- as.POSIXct(dados[1,], origin = '1970-01-01')
dados <- xts(t(dados[-1,]), order.by = datetime)

# gráfico dos valores de fechamento
plot(dados$close, 
     col = "darkblue",
     main = 'Preços de Bitcoin em dólares')

Web Scraping

Web scraping é uma técnica de extração de dados utilizada para coletar dados de sítios na web. Os dados são convertidos do formato HTML tags da web para um formato estruturado que pode ser acessado e utilizado diretamente. O pacote rvest é muito utilizado para essa objetivo.

# instale o pacote
#install.packages('rvest')
 
# carregue o pacote na memória
library(rvest)

Exemplo. Uma função que recupera artigos do Google Scholar a partir de uma busca baseada em um string genérico texto.

getArtigos <- function(texto){
  # define a url
  url <- paste0('https://scholar.google.com/scholar?hl=en&q=', texto)
  # "sanitize"limpa" a url
  url <- URLencode(url)
  # Obtem resultados
  res <- read_html(url) %>%           # Obtem a url
    html_nodes('div.gs_ri h3 a') %>%  # seleciona os títulos por um seletor css  
    html_text()                       # extrai o texto
  # retorna resultados
  return(res)
}
 
# recupera artigos sobre 'web scraping in r'
getArtigos('web scraping in r')
##  [1] "Web scraping using R"                                                                                         
##  [2] "Automated data collection with R: A practical guide to web scraping and text mining"                          
##  [3] "Web Scraping With R"                                                                                          
##  [4] "Research note: scraping financial data from the web using the R language"                                     
##  [5] "RCrawler: An R package for parallel web crawling and scraping"                                                
##  [6] "Automated Data Collection with RA Practical Guide to Web Scraping and Text Mining"                            
##  [7] "Web Scraping in the R Language: A Tutorial"                                                                   
##  [8] "Web scraping in the statistics and data science curriculum: Challenges and opportunities"                     
##  [9] "SASSCAL WebSAPI: A Web Scraping Application Programming Interface to Support Access to SASSCAL's Weather Data"
## [10] "Legality and ethics of web scraping"

Outros dados para análise fundamentalista

Uma função para converter números do formato brasileiro para o formato americano.

converte <- function(x) {
    # Primeiro elimina todos os caracteres não-dígitos e qualquer outro após estes
    # Depois elimina os pontos
    # Finalmente, converte vírgulas em pontos
    # Se é um valor em %, divide por 100  
    z <- trimws(x)
    n_digitos <- nchar(z)
    ultimo <- substr(z, n_digitos, n_digitos)

    z <- gsub("[^0-9,.]", "", z)
    z <- gsub("\\.", "", z)
    
    z <- as.numeric(gsub(",", ".", z))
    
    if(ultimo[1] == "%") { 
      z <- z/100 
    }
    
    return(z)
}

Dados da Fundamentus.

library(rvest)
library(tidyverse)

url <- "http://www.fundamentus.com.br/resultado.php"

dadosFund <- url %>%
  read_html() %>%
  rvest::html_table(header = TRUE) %>%
  map_df(bind_cols) %>%
  as_tibble() %>% # transforma para um tibble no formato adequado utilizando a função converte()
  mutate_at(colnames(.)[-1], converte)

Indicadores e dados.

colnames(dadosFund)
##  [1] "Papel"             "Cotação"           "P/L"              
##  [4] "P/VP"              "PSR"               "Div.Yield"        
##  [7] "P/Ativo"           "P/Cap.Giro"        "P/EBIT"           
## [10] "P/Ativ Circ.Liq"   "EV/EBIT"           "EV/EBITDA"        
## [13] "Mrg Ebit"          "Mrg. Líq."         "Liq. Corr."       
## [16] "ROIC"              "ROE"               "Liq.2meses"       
## [19] "Patrim. Líq"       "Dív.Brut/ Patrim." "Cresc. Rec.5a"
glimpse(dadosFund)
## Rows: 984
## Columns: 21
## $ Papel               <chr> "CSTB4", "PORP4", "CFLU4", "PMET3", "MNSA3", "CLAN~
## $ Cotação             <dbl> 147.69, 2.40, 1000.00, 0.00, 0.42, 0.00, 150.00, 1~
## $ `P/L`               <dbl> 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.~
## $ `P/VP`              <dbl> 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.~
## $ PSR                 <dbl> 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0~
## $ Div.Yield           <dbl> 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.~
## $ `P/Ativo`           <dbl> 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0~
## $ `P/Cap.Giro`        <dbl> 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.~
## $ `P/EBIT`            <dbl> 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.~
## $ `P/Ativ Circ.Liq`   <dbl> 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.~
## $ `EV/EBIT`           <dbl> 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.~
## $ `EV/EBITDA`         <dbl> 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.~
## $ `Mrg Ebit`          <dbl> 0.4085, 0.0000, 0.0888, 0.0000, 2.0815, 0.0000, 0.~
## $ `Mrg. Líq.`         <dbl> 0.2898, 0.0000, 0.1072, 0.0000, 3.6266, 0.0000, 0.~
## $ `Liq. Corr.`        <dbl> 2.60, 0.00, 1.10, 0.00, 3.63, 0.00, 2.60, 1.08, 3.~
## $ ROIC                <dbl> 0.2240, 0.0000, 0.1768, 0.0000, 0.1350, 0.0000, 0.~
## $ ROE                 <dbl> 0.2011, 0.0208, 0.3215, 0.0410, 1.4570, 0.0105, 0.~
## $ Liq.2meses          <dbl> 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00~
## $ `Patrim. Líq`       <dbl> 8420670000, 22399000, 60351000, 290863000, 9105000~
## $ `Dív.Brut/ Patrim.` <dbl> 0.14, 0.00, 0.06, 0.00, 6.52, 0.00, 0.14, 0.82, 6.~
## $ `Cresc. Rec.5a`     <dbl> 0.3191, 0.1366, 0.0814, 0.3774, 0.4111, 0.6396, 0.~

Obtem os dados financeiros do Data Hub - Companhias do S&P 500

install.packages("jsonlite", repos="https://cran.rstudio.com/")
## package 'jsonlite' successfully unpacked and MD5 sums checked
## 
## The downloaded binary packages are in
##  C:\Users\SAMSUNG\AppData\Local\Temp\RtmpgB8m4n\downloaded_packages
library("jsonlite")

json_file <- 'https://datahub.io/core/s-and-p-500-companies-financials/datapackage.json'
json_data <- fromJSON(paste(readLines(json_file), collapse=""))

# Obtem a lista de todos os recursos
print(json_data$resources$name)
## [1] "validation_report"                   
## [2] "constituents_csv"                    
## [3] "constituents-financials_csv"         
## [4] "constituents_json"                   
## [5] "constituents-financials_json"        
## [6] "s-and-p-500-companies-financials_zip"
## [7] "constituents"                        
## [8] "constituents-financials"
# apresenta todos os dados tabulares (se existirem)
for(i in 1:length(json_data$resources$datahub$type)){
  if(json_data$resources$datahub$type[i]=='derived/csv'){
    path_to_file = json_data$resources$path[i]
    dados_DataHub <- read.csv(url(path_to_file))
    # print(data)
  }
}

str(dados_DataHub)
## 'data.frame':    505 obs. of  14 variables:
##  $ Symbol        : chr  "MMM" "AOS" "ABT" "ABBV" ...
##  $ Name          : chr  "3M Company" "A.O. Smith Corp" "Abbott Laboratories" "AbbVie Inc." ...
##  $ Sector        : chr  "Industrials" "Industrials" "Health Care" "Health Care" ...
##  $ Price         : num  222.9 60.2 56.3 108.5 150.5 ...
##  $ Price.Earnings: num  24.3 27.8 22.5 19.4 25.5 ...
##  $ Dividend.Yield: num  2.33 1.15 1.91 2.5 1.71 ...
##  $ Earnings.Share: num  7.92 1.7 0.26 3.29 5.44 1.28 7.43 3.39 6.19 0.03 ...
##  $ X52.Week.Low  : num  259.8 68.4 64.6 125.9 162.6 ...
##  $ X52.Week.High : num  175.5 48.9 42.3 60 114.8 ...
##  $ Market.Cap    : num  1.39e+11 1.08e+10 1.02e+11 1.81e+11 9.88e+10 ...
##  $ EBITDA        : num  9.05e+09 6.01e+08 5.74e+09 1.03e+10 5.64e+09 ...
##  $ Price.Sales   : num  4.39 3.58 3.74 6.29 2.6 ...
##  $ Price.Book    : num  11.34 6.35 3.19 26.14 10.62 ...
##  $ SEC.Filings   : chr  "http://www.sec.gov/cgi-bin/browse-edgar?action=getcompany&CIK=MMM" "http://www.sec.gov/cgi-bin/browse-edgar?action=getcompany&CIK=AOS" "http://www.sec.gov/cgi-bin/browse-edgar?action=getcompany&CIK=ABT" "http://www.sec.gov/cgi-bin/browse-edgar?action=getcompany&CIK=ABBV" ...

Uma curva ABC da B3

Podemos utilizar o web scraping para conhecer a proporção de papéis que é negociada em cada segmento de mercado da B3.

library(XML)
library(rvest)
library(Hmisc)
library(tidyverse)
library(kableExtra)

# Scraping na tabela URL no formato HTML

url <- "https://bvmf.bmfbovespa.com.br/CapitalSocial"

capital_social <- url %>%
    rvest::read_html() %>%
    rvest::html_table(header = TRUE) %>%
    purrr::map_df(bind_cols) %>%
    as.data.frame()

# Seleciona o segmento de mercado da B3, eliminando capital subscrito
segmento_de_mercado <- factor(capital_social$`Segmento de Mercado`[capital_social$`Tipo de Capital` != 'Subscrito'])

# Gera frequência simples com a função table e cria o data frame
freq_simples <- table(segmento_de_mercado)
dados_simples <- data.frame(freq_simples)

# Ordena os dados em ordem decrescente
dados_simples <- as_tibble(dados_simples[order(dados_simples$Freq, decreasing = TRUE), ])

# Gera frequência acumulada com a função Cumsum
freq_acumulada <- cumsum(dados_simples$Freq)

# Adicionar a coluna
dados_simples$freq_acumulada <- cumsum(dados_simples$Freq)

# Calcula a frequência relativa simples
freq_relativa_simples <- as.numeric(freq_simples / sum(freq_simples))

# Adiciona a coluna
dados_simples$freq_relativa_simples <- freq_relativa_simples

# Calcula a frequência relativa acumulada
freq_relativa_acumulada <- freq_acumulada / sum(freq_simples)

# Adicionar a frequência acumulada
dados_simples$freq_relativa_acumulada <- freq_relativa_acumulada

# Exibe os dados
kable(dados_simples,
      format = 'pipe',
      digits = 3,
      align = "c",
      col.names = c('segmento', 'freq', 'freq.acum', 'freq.rel', 'freq.rel.acum')) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
segmento freq freq.acum freq.rel freq.rel.acum
BOLSA 213 213 0.399 0.399
NOVO MERCADO 205 418 0.051 0.783
SOMA 31 449 0.047 0.841
BOVESPA NIVEL 1 27 476 0.028 0.891
BOVESPA NIVEL 2 25 501 0.004 0.938
FIP IE 15 516 0.028 0.966
MAIS 15 531 0.002 0.994
FIP MT 2 533 0.384 0.998
MAIS NIVEL 2 1 534 0.058 1.000

Vamos criar a cruva de Pareto (ABC) para as freqências

library(qcc)
freq <- dados_simples$Freq
names(freq) <- dados_simples$segmento_de_mercado
pareto.chart(freq,
             cumperc = seq(0, 100, by = 5),
             main = "Curva ABC para frequências",
             ylab = "Frequências",
             ylab2 = "Segmentos de mercado na B3")

##                  
## Pareto chart analysis for freq
##                     Frequency   Cum.Freq.  Percentage Cum.Percent.
##   BOLSA           213.0000000 213.0000000  39.8876404   39.8876404
##   NOVO MERCADO    205.0000000 418.0000000  38.3895131   78.2771536
##   SOMA             31.0000000 449.0000000   5.8052434   84.0823970
##   BOVESPA NIVEL 1  27.0000000 476.0000000   5.0561798   89.1385768
##   BOVESPA NIVEL 2  25.0000000 501.0000000   4.6816479   93.8202247
##   FIP IE           15.0000000 516.0000000   2.8089888   96.6292135
##   MAIS             15.0000000 531.0000000   2.8089888   99.4382022
##   FIP MT            2.0000000 533.0000000   0.3745318   99.8127341
##   MAIS NIVEL 2      1.0000000 534.0000000   0.1872659  100.0000000

Exercícios

Lucro

Com o pacote GetDFPData, baixe os demostrativos financeiros mais recentes da Petrobras. Qual foi o seu lucro líquido no exercício? Qual foi o pagamento de proventos para o acionista (dividendo ou JSCP) mais recente?

B3

Utilizando função GetDFPData::gdfpd.get.info.companies, baixe informações sobre as ações negociadas na B3. Quantas empresas estão atualmente disponíveis no banco de dados? Qual a proporção de empresas ativas? Qual a empresa mais antiga? Quantas empresas existem para o setor de Utilidade Pública?

Emprego

Crie uma conta no site da Quandl. Utilizando o pacote GetQuandlData, baixe os dados de desemprego no Brasil na base de dados estatísticos do banco Central. Qual é o valor mais recente da série? Faça um gráfico dos dados dos últimos cinco anos.

Importando dados do Tesouro Prefixado com Juros Semestrais

  • Importe os dados de contratos Tesouro Prefixado com Juros Semestrais para os vencimentos: 01/01/2027”, 01/01/2029, 01/01/2031
  • Faça um gráfico com os dados de taxas de juros a partir de 2016

Importar os dados de companhias brasileiras

O site da B3 tem informações sobre todas as companhias com ações listadas.

Encontre os símbolos das companhias:

  • Magazine Luiza
  • Grendene
  • Embraer

Importe os dados destas companhias com getSymbols e faça os gráficos de candlesticks com dados desde o começo de 2019, sem apresentar os dados de volume.

Calcular o IBOVESPA em dólar

O IBOVESPA é uma carteira de ações negociadas na BOVESPA. A cotação do IBOVESPA representa pontos de índice. A cotação do dólar é em reais por dólar americano.

Desafio:

  • Importe os dados do dólar e do IBOVESPA desde jan/2010.
  • Calcule o IBOVESPA em dólar.
  • Compare a variação do IBOVESPA em dólar com a sua variação em reais.

Manipulando data frames

A manipulação de dados é uma tarefa usualmente bastante dolorosa e demorada, podendo muitas vezes tomar mais tempo do que desejaríamos. Como nosso interesse geralmente é na modelagem dos dados, essa tarefa não pode ser negligenciada.

O dplyr é um dos pacotes mais úteis para realizar manipulação de dados, e procura aliar simplicidade e eficiência de uma forma bastante elegante. Os scripts em R que fazem uso inteligente dos verbos dplyr e as facilidades do operador pipe (%>%) tendem a ficar mais legíveis e organizados, sem perder a velocidade de execução.

Por ser um pacote que se propõe a realizar um dos trabalhos mais árduos da análise estatística, e por atingir esse objetivo de forma elegante, eficaz e eficiente, o dplyr pode ser considerado como uma revolução no R.

Vamos exercitar a manipulação de data frames.

  • Clique aqui, se estiver utilizando a versão LOCAL deste arquivo, ou

  • Clique aqui, se estiver utiizando a versão WEB deste arquivo.

Referências