Vimos no post Usando dados do rbmfbovespa para construir gráficos candlestick no R que a partir do arquivo de cotações históricas de 2016 é possível criar séries de preços para ativos negociados na BM&FBovespa. Particularmente, utilizamos as ETFs e fizemos alguns gráficos de candlestick e volume com as bibliotecas quantmod e tidyquant. Neste post vamos utilizar novamente as ETFs para fazer uma avaliação do desempenho de algumas delas, as mais líquidas, no ano de 2016. A biblioteca PerformanceAnalytics possui diversas funções para avaliação de desempenho de ativos, muito útil na comparação de fundos de investimentos e avaliação de benchmarks. Esta biblioteca traz diversos gráficos e tabelas que enriquecem essa análise e alguns deles serão apresentados ao longo deste post. O objetivo aqui é selecionar algumas ETFs que apresentaram boa liquidez em 2016 e avaliar o desempenho delas utilizando as funções da biblioteca PerformanceAnalytics.

Começemos carregando os pacotes que serão utilizados.

library(dplyr)
library(rbmfbovespa)
library(xts)
library(PerformanceAnalytics)

Carregando o arquivo de cotações históricas de 2016.

ch_2016 <- read_marketdata('datasets/COTAHIST_A2016.TXT', 'COTAHIST')

e selecionando as ETFs.

etfs <- ch_2016[[2]] %>% filter(especificacao == 'CI',
                                tipo_mercado == 10,
                                stringr::str_detect(nome_empresa, "^(BB ETF|CAIXAETF|ISHARE|IT NOW)"))

Agora é necessário fazer uma avaliação da liquidez das ETFs, que para o objetivo traçado é basicamente levantar quantos dias cada ETF apresentou negócios no ano. Vamos começar selecionando as variáveis: cod_negociacao, data_referencia e preco_ult, e em seguida agrupar por cod_negociacao e depois contar, com isso teremos a quantidade de dias que cada ativo apresentou de negócios no ano.

etfs %>%
  select(cod_negociacao, data_referencia, preco_ult) %>%
  group_by(cod_negociacao) %>%
  summarise(Count = n()) %>%
  arrange(desc(Count)) %>%
  formattable::formattable()
cod_negociacao Count
BOVA11 249
DIVO11 249
IVVB11 249
PIBB11 249
SMAL11 248
ISUS11 246
SPXI11 245
GOVE11 242
XBOV11 239
BBSD11 238
ECOO11 228
BRAX11 225
FIND11 223
MATB11 153
BOVV11 64

Ordenando a contagem de forma decrescente, observa-se que as ETFs com maior quantidade de dias negociados são BOVA11, DIVO11, PIBB11 e IVVB11 (se quiser saber o que é cada uma delas veja aqui), entretanto, SMAL11, ISUS11, SPXI11 e GOVE11 ficam logo atrás. Dessa forma, estas 8 ETFs serão as selecionadas para este exercício de avaliação de desempenho.

etfs %>%
  select(cod_negociacao, data_referencia, preco_ult) %>%
  filter(cod_negociacao %in% c('DIVO11', 'GOVE11', 'BOVA11', 'PIBB11', 'SMAL11', 'ISUS11', 'IVVB11', 'SPXI11')) %>%
  arrange(cod_negociacao, data_referencia) -> etfs_data

Selecionadas as ETFs, é preciso criar objetos de séries temporais para as séries de preços. As séries temporais são criadas com a função xts do pacote de mesmo nome. Note que aplico um lapply que cria uma lista com as séries e depois uso o merge para juntar todas as séries temporais em um único objeto, etfs_series.

etfs_series <- lapply(split(etfs_data, etfs_data$cod_negociacao), function(x) {
  xts(x$preco_ult, x$data_referencia)
})

etfs_series <- do.call(merge, etfs_series)

O objeto etfs_series possui séries de preços, e as análises de desempenho devem ser feitas com as séries de retornos dos ativos (se quiser saber mais sobre retornos veja o post Calculando Retornos Financeiros com Pandas). Aqui vamos utilizar a função CalculateReturns do pacote PerformanceAnalytics para calcular os retornos logarítimicos.

etfs_series <- CalculateReturns(etfs_series, method = 'log')

Vamos observar então um gráfico de barras com os retornos das séries com charts.Bar.

charts.Bar(etfs_series)

plot of chunk indicadores_de_desempenho_etfs-7

A primeira análise é o cálculo dos retornos acumulados, dado que os retornos são a variação percentual diária do ativo, os retornos acumulados apresentam o ganho (ou perda) do ativo no período. Para simplificar vamos considerar o investimento de R\$ 1,00 no começo de 2016 e vamos avaliar a evolução deste investimento em 2016, se no fim tivermos mais de R\$ 1,00 o investimento teve um retorno positivo no período, caso contrário teve perda pois chegou-se ao fim com menos do que tinha no começo do ano. A função chart.CumReturns apresenta as séries de retornos acumulados para todos os ativos.

chart.CumReturns(etfs_series, wealth.index = TRUE, main = "Retornos Acumulados", legend.loc = 'topleft')

plot of chunk indicadores_de_desempenho_etfs-8

Aqui é possível observar diversas coisas interessantes.

  • SPXI11 e IVVB11 apresentaram perda, e estas ETFs, ambas, seguem o S&P500.
  • DIVO11 disparou apresentando um resultado no fim de pouco mais de R\$ 1,50, ganho acima de 50% no ano!
  • BOVA11, PIBB11 seguem IBOVESPA e IBrX50, respectivamente, por isso apresentam resultado semelhante e andam bastante juntas o tempo todo.
  • GOVE11 segue o Índice de Governança Corporativa Trade (IGCT), também segue de perto os índices.

Um ponto interessante é que podemos mudar o esquema de cores para destacar 1 ativo em particular. Por exemplo, o SMAL11 apresentou um resultado interessante, mas não apareceu muito no gráfigo, talvez por estar amarelo. Eu vou redefinir a paleta de cores de forma que SMAL11 seja destacado.

chart.CumReturns(etfs_series, wealth.index = TRUE, main = "Retornos Acumulados", legend.loc = 'topleft',
                 colorset = c(rep('gray', 6), 'red', rep('gray', 1)))

plot of chunk indicadores_de_desempenho_etfs-9

Assim é possível destacar qualquer ativo comparando o seu resultado com os demais.

Outra forma de verificar o desempenho no ano mais diretamente é montar a tabela de retornos anuais com a função table.AnnualizedReturns.

table.AnnualizedReturns(etfs_series) %>% formattable::formattable()
BOVA11 DIVO11 GOVE11 ISUS11 IVVB11 PIBB11 SMAL11 SPXI11
Annualized Return 0.3738 0.5841 0.4181 0.1781 -0.1051 0.3780 0.3614 -0.1129
Annualized Std Dev 0.2708 0.3046 0.2453 0.2342 0.1996 0.2585 0.2508 0.1747
Annualized Sharpe (Rf=0%) 1.3807 1.9176 1.7046 0.7608 -0.5266 1.4621 1.4408 -0.6458

Diretamente vemos que DIVO11 entregou 58% de retorno em 2016, seguido por GOVE11 com 41%. Note que temos o índice Sharpe na tabela, que aqui deve ser ignorado por não estarmos definindo os parâmetros adequadamente para o seu cálculo.

Vamos reordenar as séries de acordo com os retornos anuais.

etfs_series <- etfs_series[,c('DIVO11', 'GOVE11', 'BOVA11', 'PIBB11', 'SMAL11', 'ISUS11', 'IVVB11', 'SPXI11')]

Fiz isso deliberadamente porque quero fazer a análise de correlação das série e acredito (dadas as observações recentes) que os ativos com bom desempenho estejam correlacionados. O PerformanceAnalytics tem a função chart.Correlation que constroi uma matriz de correlação com todos os ativos e traz diversas informações estatísticas e da distribuição dos ativos.

chart.Correlation(etfs_series)

plot of chunk indicadores_de_desempenho_etfs-12

Bem, como já imaginava, uma correlação forte entre as ETFs baseadas em ativos nacionais e outro grupo formado por ETFs baseadas em ativos internacionais (basicamente o S&P500). Na diagonal principal temos o histograma de retornos com uma densidade em vermelho, no triangulo inferior esquerdo temos os gráficos de pontos com retornos contra retornos dos pares de séries, que trazem uma forma visual de observar a correlação entre ativos. Note que, nos gráficos de pontos do SPXI11 com o BOVA11 (ou DIVO11, por exemplo) há quase uma figura circular, não indicando tendência, já entre SPXI11 e IVVB11 temos uma figura mais oval com inclinação bem definida. O mesmo gráfico oval aparace para a comparação entre diversas ETFs nacionais, como DIVO11 e GOVE11, por exemplo. No trigangulo superior direito, são apresentados os coeficientes de correlação calculados com o método de Pearson, que é o padrão, entretanto também podem ser usados Kendall e Spearman. Os tamanhos dos números e os asteriscos em vermelho representam a significância da correlação, quanto mais asteriscos (ou maior) é menor a probabilidade de que o coeficiente de correlação seja nulo. Para entender melhor este resultado da correlação dê uma olhada na função cor.test.

Como último tópico vou apresentar a análise de risco e retorno. A função chart.RiskReturnScatter apresenta um gráfico de risco e retorno anuais, onde observa-se o retorno anual de cada ativo contra o risco do ativo no ano.

chart.RiskReturnScatter(etfs_series)

plot of chunk indicadores_de_desempenho_etfs-13

O DIVO11 que apresentou o maior retorno, provavelmente deu dor de cabeça a alguns gestores, pois foi quem também apresentou o maior risco. O GOVE11 aparece como boa alternativa apresentando 5% a menos de volatilidade. O grupinho PIBB11, BOVA11 e SMAL11 são irmãos em risco e retorno e os ETFs baseaos em S&P500 são só desgraça.

Bem, ainda há mais análises disponíveis no PerformanceAnalytics, mas essas ficam para outro post.