Extração, manipulação e apresentação de dados financeiros no R

Este post apresenta modelos de cura na Análise de Sobrevivência, uma abordagem essencial para dados em que uma parcela dos indivíduos nunca experimenta o evento, ilustrada com uma aplicação a dados de COVID-19
Estatística
Dados financeiros
R
Autor

Ivan Cunha Vieira

Data de Publicação

2 de março de 2026

Introdução

Se você atua no mercado financeiro, com gestão de riscos, na área da economia ou de alguma forma trabalha com dados dessas áreas, provavelmente já se deparou com situações onde precisou lidar com dados de preços e volumes ao longo do tempo, com o objetivo de entender tendências, volatilidade e métricas desses dados. Nesses casos, a análise de séries temporais financeiras é a área estatística utilizada para resolver essas questões.

A grande particularidade desse tipo de dado é a sua natureza estocástica e a presença de não-estacionariedade. Um dado financeiro bruto (como o preço de fechamento) muitas vezes não segue uma distribuição normal, exigindo transformações, como a transformação logarítmica, amplamente usada na área da economia.

Para análises financeiras em R, ferramentas básicas como ts() permitem o tratamento de séries temporais. No entanto, expandimos essas possibilidades com os pacotes quantmod (Ryan e Ulrich 2025), focado na extração direta de fontes de dados (como Yahoo Finance), e PerformanceAnalytics (Peterson e Carl 2024), que abrange funções de análise técnica, como métricas específicas da área financeira.

Neste texto, abordaremos a extração de cotações, o cálculo de retornos, a visualização de desempenho e o cálculo de métricas de ativos brasileiros (PETR4 e VALE3). Além disso, faremos uma comparação entre as visualizações do pacote PerformanceAnalytics e do ecossistema tidyverse (Wickham et al. 2019), que permite uma manipulação e visualização dinâmica e elegante de dados, demonstrando como podemos utilizar o R para trabalharmos e apresentarmos com facilidade dados financeiros.

Sobre os dados

Para este exemplo, utilizaremos dados históricos diários de duas das maiores empresas da bolsa brasileira: Petrobras e Vale (que possuem os tickers PETR4.SA e VALE3.SA, respectivamente), compreendendo o período de 01/01/2020 a 31/12/2024. O que torna esse período particular e interessante é que ele engloba o período da pandemia e a posterior recuperação do mercado financeiro, permitindo visualizar eventos extremos dos dados econômicos.

Preparação do ambiente

Código
# Instalação dos pacotes
# install.packages(c("quantmod", "PerformanceAnalytics"))

# Chamando os pacotes para utilizarmos na seção
library(quantmod)
library(PerformanceAnalytics)
library(tidyverse)

Extração de dados com quantmod

A função getSymbols() do pacote quantmod é a ferramenta padrão para carregar dados diretamente de fontes públicas. Ela cria objetos do tipo xts (eXtensible Time Series), tipo de objetos lido pelas funções do pacote PerformanceAnalytics e que são matrizes indexadas por data. Esses objetos são criados automaticamente após o uso da função a partir do argumento auto.assign = TRUE.

Código
# Definindo datas e tickers
inicio <- "2020-01-01"
fim <- "2024-12-31"
tickers <- c("PETR4.SA", "VALE3.SA")

# Extração dos dados do Yahoo Finance
getSymbols(tickers, src = "yahoo", from = inicio, to = fim, 
           auto.assign = TRUE)
[1] "PETR4.SA" "VALE3.SA"

Ao inspecionar o objeto PETR4.SA, observamos a estrutura OHLCV (Open, High, Low, Close, Volume), uma estrutura de dados clássica usada em finanças para resumir a atividade do mercado por um determinado tempo, além do preço ajustado por dividendos e desdobramentos (Adjusted).

Código
# Primeiras 5 observações
head(PETR4.SA, n = 3)
           PETR4.SA.Open PETR4.SA.High PETR4.SA.Low PETR4.SA.Close
2020-01-02         30.51         30.70        30.31          30.70
2020-01-03         30.88         31.24        30.45          30.45
2020-01-06         30.43         30.94        29.95          30.81
           PETR4.SA.Volume PETR4.SA.Adjusted
2020-01-02        37774500          8.816065
2020-01-03        71595600          8.744275
2020-01-06        81844000          8.847654

É importante ressaltar que a coluna Adjusted é crucial para análises de longo prazo, pois nela é apresentado o desconto do pagamento de proventos, que no geral são remunerações ou benefícios distribuídos pelas empresas a seus investidores e/ou empregados, refletindo o retorno real do acionista.

Estatísticas dos dados

Agora, podemos analisar as estatísticas dos dados de maneira simples com a função Ad do pacote quantmod, que extrai a coluna Adjusted de um objeto com estrutura OHLC, e a função table.Stats do pacote PerformanceAnalytics, que retorna uma tabela básica de estatísticas dos dados.

Código
# Selecionando apenas preços ajustados
precos <- merge(Ad(PETR4.SA), Ad(VALE3.SA))
names(precos) <- c("PETR4", "VALE3")
table.Stats(precos)
                    PETR4     VALE3
Observations    1244.0000 1244.0000
NAs                0.0000    0.0000
Minimum            3.2421   18.9173
Quartile 1         8.0994   49.3487
Median            12.9243   52.9913
Arithmetic Mean   15.6135   51.6738
Geometric Mean    13.3255   50.0968
Quartile 3        24.1016   59.1318
Maximum           33.7639   73.0253
SE Mean            0.2553    0.3322
LCL Mean (0.95)   15.1127   51.0221
UCL Mean (0.95)   16.1144   52.3255
Variance          81.0819  137.2553
Stdev              9.0046   11.7156
Skewness           0.6224   -0.7765
Kurtosis          -1.0673    0.1127

Podemos observar que, para ambos os ativos, há um total de 1244 observações Entre esses dados, percebemos que os preços das ações da Petrobras apresentaram valores mais baixos em todos os seus quantis quando em comparação com os preços da Vale. Além disso, observando as médias aritméticas e geométricas de ambos os ativos, é possível reparar que elas apresentam uma boa proximidade, indicando que os dados podem não apresentar valores outliers ou podem possuir baixa variabilidade, ideia essa que é corroborada pelos seus respectivos valores de desvio padrão aparentemente pequenos. Fora essas informações, a tabela também traz estatísticas de curtose e assimetria, importantes para análises de distribuições.

Manipulação e cálculo de retornos

Enquanto os preços nos mostram o nível do ativo, para a modelagem estatística utilizamos os retornos. De acordo com Tsay (2010), os retornos simples (\(R_t\)) são dados pela equação

\[R_t=\dfrac{P_t-P_{t-1}}{P_{t-1}},\]

onde \(P_t\) é o preço no tempo t e \(P_{t-1}\) é o preço no tempo t-1. Sua forma acumulada por k períodos é dada pela equação \[\Pi_{j=0}^{k-1}(1+R_{t-j}).\]

No R, podemos calcular isso facilmente e converter o formato xts para tibble, facilitando a visualização com ggplot2. Para isso, basta, primeiramente, juntarmos as informações

Código
# Transformação para formato tibble
dados_tibble <- precos %>%
  fortify.zoo() %>% 
  as_tibble() %>%
  rename(Data = Index) %>%
  pivot_longer(cols = -Data, names_to = "Ativo", values_to = "Preco") %>%
  group_by(Ativo) %>%
  # Cálculo de retornos simples e acumulados
  mutate(Retorno_Diario = replace_na((Preco-lag(Preco))/lag(Preco),0),
         Retorno_Acumulado = cumprod(1 + Retorno_Diario) - 1)

head(dados_tibble)
# A tibble: 6 × 5
# Groups:   Ativo [2]
  Data       Ativo Preco Retorno_Diario Retorno_Acumulado
  <date>     <chr> <dbl>          <dbl>             <dbl>
1 2020-01-02 PETR4  8.82        0                 0      
2 2020-01-02 VALE3 30.1         0                 0      
3 2020-01-03 PETR4  8.74       -0.00814          -0.00814
4 2020-01-03 VALE3 29.9        -0.00736          -0.00736
5 2020-01-06 PETR4  8.85        0.0118            0.00358
6 2020-01-06 VALE3 29.7        -0.00593          -0.0133 

No entanto, também podemos calcular os retornos simples e acumulados a partir da função Return.calculate do pacote PerfomanceAnalytics, encontrando um resultado igual ao do cálculo feito anteriormente. Dessa forma, otimizamos o código ao evitar o processo de adicionar a fórmula ao mesmo.

A função Return.calculate permite o cálculo de diferentes tipos de retorno, como o retorno simples e o retorno logarítmico (utilizando os argumentos “discrete” e “log”, respectivamente), abrangendo abordagens diversas para a análise de dados financeiros.

A principal vantagem ao fazer uso dessa função é que não transformarmos os dados de xts para tibble, permitindo com que nós continuemos a trabalhar com eles diretamente no formato extraído e aplicando as funções especializadas da área para esses tipos de dados.

Código
# Retornos simples
retornos_simples <- Return.calculate(precos, method = "discrete")
retornos_simples <- na.fill(retornos_simples, 0)
head(retornos_simples)
                  PETR4         VALE3
2020-01-02  0.000000000  0.0000000000
2020-01-03 -0.008143060 -0.0073622377
2020-01-06  0.011822507 -0.0059338435
2020-01-07 -0.003895041  0.0072748744
2020-01-08 -0.006190794  0.0001849595
2020-01-09 -0.003278387 -0.0131456716
Código
# Retornos acumulados
retornos_acumulados <- cumprod(1 + retornos_simples) - 1
head(retornos_acumulados)
                   PETR4        VALE3
2020-01-02  0.0000000000  0.000000000
2020-01-03 -0.0081430596 -0.007362238
2020-01-06  0.0035831756 -0.013252395
2020-01-07 -0.0003258219 -0.006073930
2020-01-08 -0.0065145991 -0.005890094
2020-01-09 -0.0097716283 -0.018958336

Outra função interessante para análise dos retornos é a função Return.cumulative, que entrega o retorno acumulado final dos ativos no período analisado. O retorno acumulado final pode ser comparado aos gráficos gerados mais a frente no texto.

Código
# Retorno acumulado final em porcentagem
Return.cumulative(retornos_simples)*100
                     PETR4    VALE3
Cumulative Return 268.6078 59.91256

Visualização de Resultados

A visualização da evolução do retorno simples acumulado permite comparar o desempenho relativo dos ativos, normalizando o ponto de partida. Para isso, podemos utilizar o ggplot, função do ecossistema tidyverse para visualização gráfica, para os dados salvos no formato tibble.

Código
# Gráfico de retornos acumulados
ggplot(dados_tibble, 
       aes(x = Data, y = Retorno_Acumulado, color = Ativo)) +
  geom_line(linewidth = 0.8) +
  scale_y_continuous(labels = scales::percent) +
  labs(title = "Retorno simples acumulado: PETR4 x VALE3",
       subtitle = "Período: 2020-2024",
       y = "Retorno Simples Acumulado (%)", x = "Data") +
  theme_minimal() +
  scale_color_manual(values = c("#0072B2", "#D55E00"))

Evolução do retorno acumulado (PETR4 e VALE3): ggplot

Pelas curvas dos retornos simples acumulados de ambas as empresas, podemos notar uma queda abrupta entre o começo e o meio de 2020 (início da pandemia) e a subsequente recuperação por parte das duas empresas, com a Vale demonstrando uma alta mais acentuada em 2021 (ainda durante a pandemia) e se estabilizando até o final de 2024, enquanto a Petrobras demonstrou uma recuperação mais lenta, porém constante, e em 2023 apresentou um crescimento que se estendeu pelo menos até a última data analisada (final de 2024).

Em comparação ao realizado pelo tidyverse, podemos então gerar um gráfico para a visualização dos retornos por meio de funções próprias do pacote PerformanceAnalytics, como a função chart.CumReturns.

Código
# Gráfico de retornos acumulados
chart.CumReturns(retornos_simples, 
                 main = "Retorno simples acumulado: PETR4 x VALE3", 
                 legend.loc = "topleft", 
                 colorset = c("#0072B2", "#D55E00"))

Evolução do retorno acumulado (PETR4 e VALE3): chart.CumReturns

Podemos perceber que o gráfico gerado possui a mesma dinâmica, alterando apenas algumas formatações do layout do gráfico quando comparado ao feito pelo tidyverse. Além disso, a eficiência da função chart.CumReturns se mostrou muito maior, uma vez que precisou de menos linhas de código para gerar o mesmo gráfico.

Observando os gráficos acima, percebemos que os retornos variam constantemente em ambos os ativos. Com o pacote PerformanceAnalytics, é possível analisar a frequência dessas movimentações, utilizando a função DownsideFrequency (ou UpsideFrequency, que é complementar à função anterior).

Código
# Frequência em que os ativos estavam em queda
DownsideFrequency(retornos_simples)
                                  PETR4     VALE3
Downside Frequency (MAR = 0%) 0.4710611 0.5088424

Ao usarmos o retorno mínimo aceitável (\(MAR = 0%\)) como parâmetro de comparação, percebemos que, entre as duas empresas, os retornos da Petrobras se mantiveram abaixo da margem de 0% por menos tempo em toda a série (aproximadamente 47% do tempo), enquanto os da Vale se mantiveram abaixo por praticamente metade do tempo analisado (aproximadamente 50% do tempo), indicando uma melhor constância no aumento dos retornos da Petrobras, algo que foi possível observar anteriormente através dos gráficos.

Métricas de performance

Uma métrica fundamental para gestão de risco é o Maximum Drawdown (Queda Máxima). Essa métrica mede a maior queda percentual de um pico até um fundo antes que um novo pico seja atingido.

Utilizando a função maxDradown do pacote PerformanceAnalytics, podemos extrair essa métrica facilmente.

Código
max_dd <- maxDrawdown(retornos_simples)
print(max_dd)
                   PETR4     VALE3
Worst Drawdown 0.6335604 0.4134301

O resultado indica que, no pior momento do período analisado, um investidor da Petrobras chegou a ver seu capital reduzir-se em aproximadamente 63,3% em relação ao topo anterior, enquanto um investidor da Vale teve seu capital reduzido em aproximadamente 41,34% no maior ponto de queda.

Para sabermos exatamente em qual período essa queda aconteceu e podermos associá-la a eventos macroeconômicos, além de entendermos quanto tempo aquele ativo demorou a se recuperar da queda, é necessário compreendermos as datas exatas em que ocorreram cada um desses processos. Para isso, basta utilizarmos a função table.Drawdowns, que apresenta em sua estrutura:

  • A data do topo anterior (From);
  • A data exata da queda máxima (Trough);
  • A data em que o ativo recuperou o preço do topo anterior (To);
  • A profundidade da queda (Depth);
  • A duração total do ciclo em dias (Length);
  • A duração do topo até a queda (To Trough);
  • A duração da queda até a recuperação (Recovery)
Código
table.Drawdowns(retornos_simples$PETR4, top = 1)
        From     Trough         To   Depth Length To Trough Recovery
1 2020-01-07 2020-03-18 2021-01-07 -0.6336    249        50      199
Código
table.Drawdowns(retornos_simples$VALE3, top = 1)
        From     Trough         To   Depth Length To Trough Recovery
1 2021-07-29 2021-11-18 2023-01-26 -0.4134    375        77      298

Ao analisar o comportamento histórico apresentado na tabela, observamos que o pior cenário para a Petrobras ocorreu de fato no início de 2020, coincidindo com o choque do mercado no início da pandemia observado graficamente. O ativo levou apenas 50 dias para atingir sua queda máxima de 63,36%, mas necessitou de quase 200 dias adicionais para se recuperar dessa queda.

Já a Vale apresentou sua maior queda em um período diferente, iniciando em julho de 2021. Embora a profundidade tenha sido menor (41,34%), o ciclo de queda e recuperação foi significativamente mais longo, totalizando 375 dias entre o topo anterior e o retorno ao mesmo nível de preço.

Para complementar as análises feitas pelos dados das tabelas, podemos utilizar as funções AverageDrawdown, AverageLength e AverageRecovery para obtermos as quedas médias e o tempo médio de recuperação

Código
# Médias de queda e recuperação
drawdown_stats <- data.frame(
  Métrica = c("Profundidade média de queda", "Tempo médio de queda", "Tempo médio de recuperação"),
  PETR4 = c(AverageDrawdown(retornos_simples$PETR4), AverageLength(retornos_simples$PETR4), AverageRecovery(retornos_simples$PETR4)),
  VALE3 = c(AverageDrawdown(retornos_simples$VALE3), AverageLength(retornos_simples$VALE3), AverageRecovery(retornos_simples$VALE3))
)
print(drawdown_stats)
                      Métrica       PETR4       VALE3
1 Profundidade média de queda  0.07124564  0.07575652
2        Tempo médio de queda 24.26530612 46.88461538
3  Tempo médio de recuperação 15.59183673 19.61538462

Por fim, ao analisarmos as métricas de desempenho médio, nota-se que ambos os ativos possuem uma profundidade média de queda bastante próxima, situada entre 7,1% e 7,5%. No entanto, a dinâmica de tempo mostra que a Vale tende a ser mais persistente em seus movimentos de desvalorização, levando em média aproximadamente 46 dias para atingir o fundo da queda, quase o dobro do tempo observado para a Petrobras, que é de 24,2 dias. Essa característica se estende ao período de recuperação, no qual a Vale também demonstra maior lentidão, com um tempo médio de recuperação de 19,6 dias contra 15,5 dias da Petrobras, sugerindo que, embora a Petrobras sofra quedas mais abruptas em momentos de crise, ela historicamente demonstra uma capacidade de reação mais ágil do que a Vale.

Conclusão

Este tutorial demonstrou como o R não apresenta dificuldades para o trabalho com dados financeiros, possuindo funções que fazem desde a busca automática de informações de ativos até a criação de métricas que ajudam a entender os riscos de um investimento, com implementações diretas para visualização dos gráficos.

Sobre a comparação da Petrobras com a Vale, exemplo utilizado para explorarmos as ferramentas dos pacotes apresentados, vimos que as análises dos retornos e de métricas como o drawdown são fundamentais para uma visão real de lucro e segurança. Percebemos que, embora a Petrobras tenha enfrentado uma queda muito mais forte durante a pandemia, ela mostrou uma capacidade de se recuperar e crescer com mais agilidade do que a Vale nos anos seguintes. Por outro lado, a Vale apresentou quedas menos profundas, mas que duraram muito mais tempo para serem superadas, o que exige mais paciência do investidor.

Todas essas análises puderam ser realizadas através do uso dos pacotes quantmod e PerformanceAnalytics, que permitem que qualquer pessoa transforme dados financeiros brutos em análises visuais e estatísticas.

Referências

Peterson, Brian G., e Peter Carl. 2024. PerformanceAnalytics: Econometric Tools for Performance and Risk Analysis. https://doi.org/10.32614/CRAN.package.PerformanceAnalytics.
Ryan, Jeffrey A., e Joshua M. Ulrich. 2025. quantmod: Quantitative Financial Modelling Framework. https://doi.org/10.32614/CRAN.package.quantmod.
Tsay, Ruey S. 2010. Analysis of Financial Time Series. 3rd ed. Wiley.
Wickham, Hadley, Mara Averick, Jennifer Bryan, Winston Chang, Lucy D’Agostino McGowan, Romain François, Garrett Grolemund, et al. 2019. «Welcome to the tidyverse». Journal of Open Source Software 4 (43): 1686. https://doi.org/10.21105/joss.01686.