Introdução

De acordo com o manual de referência do pacote PerformanceAnalytics, “qualquer período no qual os retornos acumulados de um ativo caem em relação ao retorno acumulado máximo, configura-se um drawdown.” Ainda, “drawdowns são medidos como uma porcentagem deste retorno acumulado máximo, em efeito, medido desde o pico do ativo”.

Nesse post, levantaremos os drawdowns do Ibovespa desde 1995, ou seja, após o Plano Real, a partir do qual a hiperinflação deixou de afetar sistematicamente o valor dos ativos nacionais.

A importância de estudar drawdowns reside na ideia de que o passado pode fornecer pistas sobre o futuro, neste caso, sobre os riscos a que está sujeito o patrimônio do investidor exposto, por exemplo, a ETFs que buscam replicar o desempenho do Ibovespa.

Para tanto, usaremos o pacote PerformanceAnalytics, de Brian G. Peterson e colaboradores.

Importação do banco de dados

Primeiro, prepararemos o ambiente de trabalho…

# limpar o ambiente de trabalho
rm(list = ls())

# deletar gráficos anteriormente criados
graphics.off()

# desativar pacotes previamente em uso
lapply(names(sessionInfo()$otherPkgs), function(pkgs)
  detach(
    paste0('package:', pkgs),
    character.only = T,
    unload = T,
    force = T
  ))

# instalar (se necessário) e carregar os pacotes que serão utilizados 
if (!require("pacman")) install.packages("pacman")
p_load(tidyquant, tidyverse, ggthemes, scales, knitr, kableExtra)

… para em seguida importar os dados do site Yahoo Finance:

# importar dados
ibov1995 <- tq_get("^BVSP", from = "1995-01-01", get = "stock.prices")
kable(head(ibov1995), digits = 0) %>%
  kable_styling("striped", "bordered")
symbol date open high low close volume adjusted
^BVSP 1995-01-02 4354 4398 4300 4301 0 4301
^BVSP 1995-01-03 4370 4386 4094 4098 0 4098
^BVSP 1995-01-04 4098 4098 3861 3968 0 3968
^BVSP 1995-01-05 3968 4040 3944 4037 0 4037
^BVSP 1995-01-06 4037 4106 3813 3827 0 3827
^BVSP 1995-01-09 3827 3836 3570 3628 0 3628

Na continuidade, converteremos os preços ajustados (coluna adjusted, acima) em retornos diários:

# calcular retornos diários
ibov1995_daily <- ibov1995 %>%
  tq_transmute(adjusted, periodReturn, period = "daily", col_rename = "return")
kable(head(ibov1995_daily), digits = 4) %>%
  kable_styling("striped", "bordered")
date return
1995-01-02 0.0000
1995-01-03 -0.0472
1995-01-04 -0.0317
1995-01-05 0.0173
1995-01-06 -0.0518
1995-01-09 -0.0522

Como o pacote PerformanceAnalytics requer o uso de dados de séries temporais (na maior parte das vezes, objetos de classe ts, xts ou zoo), converteremos nosso objeto de classe tibble em zoo.

# converter tibble em zoo
class(ibov1995_daily)
## [1] "tbl_df"     "tbl"        "data.frame"
ibov1995_daily_zoo <- ibov1995_daily %>%
  read.zoo()
class(ibov1995_daily_zoo)
## [1] "zoo"

Análise

Drawdowns têm uma duração total, compreendida pela duração da profundidade (período de queda) e da recuperação (intervalo de alta). Com base nisso, podemos extrair parâmetros que sintetizam drawdowns (no caso, médias):

# retornar parâmetros médios de drawdowns
averages <- tibble(
  "Parâmetro" = c("Duração Média do Drawdown",
                  "Duração Média da Recuperação",
                  "Drawdown Médio"),
  "Valor" = c(AverageLength(ibov1995_daily_zoo),
              AverageRecovery(ibov1995_daily_zoo),
              AverageDrawdown(ibov1995_daily_zoo))
  )
kable(head(averages)) %>%
  kable_styling("striped", "bordered")
Parâmetro Valor
Duração Média do Drawdown 38.9940120
Duração Média da Recuperação 26.2155689
Drawdown Médio 0.0486941

Drawdowns duraram em média 39 dias, levaram aproximadamente 26 dias para completarem a recuperação e, considerando todas as quedas no período, o Ibovespa perdeu quase 5% de seu valor de pico. Mas, como sabemos, a média pode significar muito pouco, pois os valores extremos podem diferir muito dela, e os investidores estão, de fato, mais interessados nas maiores quedas. O drawdown máximo pode ser obtido rapidamente com a função abaixo:

# retornar máximo drawdown
maximum <- ibov1995_daily %>%
  tq_performance(Ra = return, performance_fun = maxDrawdown)
kable(head(maximum)) %>%
  kable_styling("striped", "bordered")
maxDrawdown.1
0.6503635

Antes de investir todo o seu patrimônio em renda variável brasileira, faça a você mesmo(a) a seguinte pergunta: você aguentaria 65% de queda? Suportaria, por exemplo, R$ 100 mil se transformar em R$ 35 mil (ou R$ 1 milhão virar R$ 350 mil)? Por outro lado, a duração da queda e da recuperação são tão importantes quanto a perda em si. A função table.Drawdowns() cria uma tabela com parâmetros para os piores drawdowns. Podemos controlar o número de elementos que desejamos obter. O padrão são os 5 piores:

# retornar tabela com os piores drawdowns
table <- table.Drawdowns(ibov1995_daily_zoo)
kable(head(table)) %>%
  kable_styling("striped", "bordered")
From Trough To Depth Length To Trough Recovery
1997-07-10 1998-09-10 1999-11-26 -0.6504 591 293 298
2008-05-21 2008-10-27 2017-09-11 -0.5996 2305 112 2193
2000-03-28 2002-10-16 2003-11-14 -0.5583 904 634 270
1995-01-03 1995-03-09 1995-08-07 -0.5028 146 44 102
2020-01-24 2020-03-23 2021-01-06 -0.4682 235 40 195

O pior drawdown teve início em 1997, época da crise asiática, e levou 591 dias para a recuperação total (aproximadamente 1 ano e meio). Mas houve um drawdown muito pior, em termos de duração da recuperação: o da crise do subprime norte-americano. A perda foi parecida, de aproximadamente 60%, mas a duração foi muito pior, tendo levado ao todo 2.305 dias (pouco mais que 6 anos!). Então, na verdade, a pergunta deve ser essa: você aguentaria perder mais da metade do seu patrimônio, e levar mais de 6 anos para recuperar o dinheiro?

Outra forma de olhar para drawdowns é por meio de gráficos. A função chart.Drawdown() faz isso facilmente:

# gráfico de drawdowns
chart.Drawdown(ibov1995_daily_zoo, geometric = TRUE, plot.engine = "plotly")

O gráfico é interativo, o que significa que você pode “brincar” com ele de diversas formas nos botões acima do eixo x. Ao passar o botão do mouse acima do gráfico, é possível visualizar a data e a queda até aquele período do último pico.

Por fim, selecionaremos as datas trazidas pela função table.Drawdowns() e coloriremos um gráfico do Ibovespa com as 5 piores quedas (de vermelho), suas respectivas recuperações (de laranja), e os momentos em que o Ibovespa deixou o último drawdown para trás (de verde).

### gráfico com os 5 piores drawdowns
ibov1995_daily %>%
  left_join(ibov1995 %>% select(date, close)) %>%
  mutate(color = case_when(date >= '1995-01-03' & date <= '1995-03-09' ~ "red",
                           date >= '1997-07-10' & date <= '1998-09-10' ~ "red",
                           date >= '2000-03-28' & date <= '2002-10-16' ~ "red",
                           date >= '2008-05-21' & date <= '2008-10-27' ~ "red",
                           date >= '2020-01-24' & date <= '2020-03-23' ~ "red",
                           date >  '1995-03-09' & date <= '1995-08-07' ~ "orange",
                           date >  '1998-09-10' & date <= '1999-11-26' ~ "orange",
                           date >  '2002-10-16' & date <= '2003-11-14' ~ "orange",
                           date >  '2008-10-27' & date <= '2017-09-11' ~ "orange",
                           date >  '2020-03-23' & date <= '2021-01-06' ~ "orange",
                           TRUE ~ "green")) %>%
  ggplot(aes(x = date, y = close, color = color, group = 1)) + 
  geom_line() +
  theme_economist_white() + 
  scale_color_manual(values = c("green4","orange","red")) + 
  labs(x = "Ano", y = "Cotação de fechamento",
       title = "Drawdowns do Ibovespa desde 1995 ") + 
  theme(legend.position = "none") + 
  scale_y_continuous(labels = comma)