Analisaremos o comportamento da ação da Petrobras, com dados extraídos do site Yahoo Finance por meio do pacote quantmod. O pacote ggplot2 será utilizado para a visualização dos dados.
library(quantmod)
library(tidyverse)
Vamos baixar a série de preços da ação da Petrobras desde 1 de janeiro de 2016 por meio do comando getSymbols.
inicio <- "2016-09-01"
hoje <- Sys.Date()
pbr <- getSymbols("PBR", # Símbolo da Petrobras no Yahoo Finance
src = "yahoo", # "source" Yahoo
from = inicio,
to = hoje,
auto.assign = FALSE) # permite nomear o dataset com o nome que quisermos. se = TRUE,
# o nome será automaticamente o símbolo que estamos buscando,
# ou seja, o primeiro argumento.
O primeiro argumento PBR é o símbolo do ativo que queremos analisar no Yahoo Finance (Petrobras). Você pode procurar pelo símbolo de outra ação ou índice que desejar analisar clicando aqui.
Vamos “enxergar” o data frame com os preços da ação:
glimpse(pbr)
## An 'xts' object on 2016-09-01/2022-01-27 containing:
## Data: num [1:1361, 1:6] 9.16 9.46 9.7 9.96 10.03 ...
## - attr(*, "dimnames")=List of 2
## ..$ : NULL
## ..$ : chr [1:6] "PBR.Open" "PBR.High" "PBR.Low" "PBR.Close" ...
## Indexed by objects of class: [Date] TZ: UTC
## xts Attributes:
## List of 2
## $ src : chr "yahoo"
## $ updated: POSIXct[1:1], format: "2022-01-28 12:14:32"
head(pbr)
## PBR.Open PBR.High PBR.Low PBR.Close PBR.Volume PBR.Adjusted
## 2016-09-01 9.16 9.29 8.97 9.22 18160300 7.271210
## 2016-09-02 9.46 9.70 9.46 9.58 23452500 7.555117
## 2016-09-06 9.70 9.95 9.63 9.94 24739400 7.839025
## 2016-09-07 9.96 10.04 9.81 9.88 18260000 7.791708
## 2016-09-08 10.03 10.24 9.89 10.18 24439000 8.028297
## 2016-09-09 9.86 9.90 9.50 9.51 23746000 7.499913
tail(pbr)
## PBR.Open PBR.High PBR.Low PBR.Close PBR.Volume PBR.Adjusted
## 2022-01-20 12.78 12.93 12.62 12.65 37785700 12.65
## 2022-01-21 12.68 12.89 12.63 12.67 30308700 12.67
## 2022-01-24 12.52 12.65 12.10 12.64 45884700 12.64
## 2022-01-25 12.57 13.27 12.45 13.16 49105600 13.16
## 2022-01-26 13.43 13.85 13.38 13.61 62922000 13.61
## 2022-01-27 13.95 13.99 13.50 13.78 46722900 13.78
psych::describe(pbr)
Visualizando o gráfico dos preços ajustados, visto que eles incorporam eventos como splits e distribuição de dividendos.
ggplot(pbr, aes(x = index(pbr), y = pbr[, 'PBR.Adjusted'])) +
geom_line(color = "darkblue") +
ggtitle("Preços ajustados da ação da Petrobras") +
xlab("Data") +
ylab("Preço ($)") +
theme(plot.title = element_text(hjust = 0.5)) + # centra o título
scale_x_date(date_labels = "%b %y", date_breaks = "6 months")
dygraphslibrary(dygraphs)
# Apenas os candles
dygraph(pbr[, -c(5,6)],
main = 'PBR - NYSE') %>%
dyCandlestick() %>%
dyRangeSelector()
Mesmo considerando a grande queda nos preços em 2020 motivada pela Covid-19, que constitui um choque, será que podemos descartar a hipótese de que os preços da ação seguem um processo estocástico conhecido como um passeio aleatório? Uma maneira de testar essa hipótese é utilizar o teste de Dickey-Fuller. Utilizaremos a função adf.test() do pacote tseries com os preços ajustados.
teste <- tseries::adf.test(pbr$PBR.Adjusted)
teste
##
## Augmented Dickey-Fuller Test
##
## data: pbr$PBR.Adjusted
## Dickey-Fuller = -2.6103, Lag order = 11, p-value = 0.32
## alternative hypothesis: stationary
O p-valor igual a 0.3199733 não indica que devamos rejeitar a hipótese nula (raiz unitária). Portanto, com base neste teste, esta série de preços parece conter uma raiz unitária, ou seja, parece ser um passeio aleatório ou, mais formalmente, a série é não-estacionária.
A maioria das séries econômicas possui raiz unitária, implicando que os choques que elas podem vir a sofrer geram um efeito permanente. As flutuações neste caso não são transitórias, derrubando, por exemplo, as teorias de que os ciclos econômicos seriam flutuações temporárias em torno de uma tendência,
Em Análise Técnica de ações, uma técnica muito utilizada é a plotagem de médias móveis nos gráficos de preços. Uma média móvel simples é a média aritmética dos últimos q dias de uma série \(x_t\), no período de tempo t. A média móvel é dada por:
\[MM_t^q = \frac{1}{q} \sum_{i=0}^{q-1} {x_{t-1}}\] Há várias maneiras de se calcular a média móvel em R. Aqui, utilizaremos a função rollmean do pacote zoo.
pbr_mm <- subset(pbr, index(pbr) >= "2017-07-01")
pbr_mm10 <- zoo::rollmean(pbr_mm[, 'PBR.Adjusted'], 10, fill = list(NA, NULL, NA), align = "right")
pbr_mm30 <- zoo::rollmean(pbr_mm[, 'PBR.Adjusted'], 30, fill = list(NA, NULL, NA), align = "right")
pbr_mm$mm10 <- zoo::coredata(pbr_mm10)
pbr_mm$mm30 <- zoo::coredata(pbr_mm30)
Plotando a série de preços de fechamento e suas médias móveis em 2020, temos:
ggplot(pbr_mm, aes(x = index(pbr_mm))) +
geom_line(aes(y = pbr_mm[, 'PBR.Adjusted'], color = "PBR")) +
ggtitle("Preços ajustados da ação da Petrobras") +
geom_line(aes(y = pbr_mm$mm10, color = "MM10")) +
geom_line(aes(y = pbr_mm$mm30, color = "MM30")) +
xlab("Data") +
ylab("Preço ($)") +
theme(plot.title = element_text(hjust = 0.5),
panel.border = element_blank()) +
scale_x_date(date_labels = "%b %y",
date_breaks = "1 months") +
scale_colour_manual("Séries",
values = c("PBR" = "gray40", "MM10" = "firebrick4", "MM30" = "darkcyan")) +
coord_cartesian(xlim = c(as.Date("2020-01-01"), Sys.Date()))
Grande parte dos estudos envolve retorno ao invés de preços. Dentre as principais razões, destaca-se o fato de séries de retornos serem mais fáceis de manipular que as séries de preços, porque sua forma possui propriedades estatísticas mais atrativas. Existem, entretanto, algumas definições diferentes de retorno que serão abordadas a seguir.
É o mais simples de ser calculado e para um único período pode ser obtido da seguinte maneira:
\[R_t=\frac {P_t -P_ {t-1}} {P_{t-1}} = \frac {P_t} {P_{t-1}} - 1\] onde:
É bem fácil calcular os retornos aritméticos. Podemos fazê-lo com apenas uma linha de código:
pbr$ret_arit <- diff(as.matrix(pbr[, 'PBR.Adjusted'])) / pbr[-nrow(pbr), 'PBR.Adjusted']
head(pbr)
## PBR.Open PBR.High PBR.Low PBR.Close PBR.Volume PBR.Adjusted
## 2016-09-01 9.16 9.29 8.97 9.22 18160300 7.271210
## 2016-09-02 9.46 9.70 9.46 9.58 23452500 7.555117
## 2016-09-06 9.70 9.95 9.63 9.94 24739400 7.839025
## 2016-09-07 9.96 10.04 9.81 9.88 18260000 7.791708
## 2016-09-08 10.03 10.24 9.89 10.18 24439000 8.028297
## 2016-09-09 9.86 9.90 9.50 9.51 23746000 7.499913
## ret_arit
## 2016-09-01 0.039045358
## 2016-09-02 0.037578240
## 2016-09-06 -0.006036082
## 2016-09-07 0.030364203
## 2016-09-08 -0.065815203
## 2016-09-09 0.031545833
Para múltiplos períodos, tem-se:
\[ \begin{aligned} R_{t,k} &= \frac {P_t} {P_{t-k}} - 1 \\ R_{t,k} + 1 &= \frac {P_t} {P_{t-k}} = \frac {P_t} {P_{t-1}} \times \frac {P_{t-1}} {P_{t-2}} \times \ldots \times \frac {P_{t-(k-1)}} {P_{t-k}} \\ &= \frac {P_t} {P_{t-k}} = (1+R_t) \times (1+R_{t-1}) \times \ldots \times (1+R_{t-(k-1)} \\ &= \left[ \prod_{i=0}^{k-1} (1+R_{t_i}) \right] - 1 \end{aligned} \]
Consiste no logaritmo natural do retorno aritmético.
\[r_t = ln(1 + R_t) = ln \frac {P_t}{P_{t-1}} = ln \, P_t - ln \, P_{t-1} = p_t - p_{t-1}\] Uma das grandes vantagens dos retornos logarítmicos é que, para múltiplos períodos de tempo, o retorno é composto pela simples soma dos retornos em cada período de tempo, como pode ser visto a seguir.
\[ \begin{aligned} r_{t,k} &= ln(1+R_{t,k}) = ln \left[ (1+R_t) \times (1+R_{t-1}) \times \ldots \times (1+R_{t-(k-1)}) \right] \\ &= ln(1+R_t) + ln(1+R_{t-1}) + \ldots + ln(1+R_{t-(k-1)}) \\ &= r_t + r_{t-1} + \ldots + r_{t-(k-1)} \\ &= \sum_{i=0}^{k-1} r_{t_i} \end{aligned} \] Quando os retornos são pequenos, o valor do retorno logarítmico se aproxima muito do retorno aritmético, ou seja, satisfeita esta condição, pode-se usar as séries dos retornos logarítmicos dos ativos no lugar do retorno aritmético, isto é \(r_t \approx R_t\).
Esse fato ocorre pela expansão de Taylor da expressão \(ln(1+R_t) = r_t\), como vemos abaixo:
\[r_t = ln(P_t) - ln(P_{t-1}) = ln\left( \frac {P_t}{P_{t-1}} \right) = ln\left( \frac {P_t - P_{t-1}+P_{t-1}}{P_{t-1}} \right) = ln(1+R_t) \approx R_t\]
Na ampla maioria dos casos, os retornos logarítmicos podem e são empregados. Algumas incompatibilidades podem aparecer quando existem mudanças de sinal nos valores, dado que o domínio da função logarítmica é \(]0, \infty[\). Para estes casos, os retornos aritméticos são a melhor solução.
Vimos como o preço da ação tem variado ao longo do tempo. Vamos agora verificar como se comportou o retorno da ação no mesmo período. Para isso, precisamos primeiro criar um novo objeto com os retornos calculados, utilizando também a coluna de preço ajustado:
pbr_ret <- diff(log(pbr[, 'PBR.Adjusted']))
pbr_ret <- pbr_ret[-1,]
summary(pbr_ret)
## Index PBR.Adjusted
## Min. :2016-09-02 Min. :-0.3708985
## 1st Qu.:2018-01-09 1st Qu.:-0.0142569
## Median :2019-05-18 Median : 0.0011862
## Mean :2019-05-17 Mean : 0.0004701
## 3rd Qu.:2020-09-22 3rd Qu.: 0.0167154
## Max. :2022-01-27 Max. : 0.1967904
sd(pbr_ret)
## [1] 0.03429315
ggplot(pbr_ret, aes(x = index(pbr_ret), y = pbr_ret)) +
geom_line(color = "deepskyblue4") +
ggtitle("Série de retornos da Petrobras") +
xlab("Data") +
ylab("Retorno") +
theme(plot.title = element_text(hjust = 0.5)) +
scale_x_date(date_labels = "%b %y", date_breaks = "6 months")
pbr_ret20 <- pbr_ret %>%
subset(index(pbr_ret) > "2020-01-01")
ggplot(pbr_ret20, aes(x = index(pbr_ret20), y = pbr_ret20)) +
geom_line(color = "deepskyblue4") +
ggtitle("Série de retornos da Petrobras a partir de 2020") +
xlab("Data") +
ylab("Retorno") +
theme(plot.title = element_text(hjust = 0.5)) +
scale_x_date(date_labels = "%b %y", date_breaks = "2 months")
summary(pbr_ret20)
## Index PBR.Adjusted
## Min. :2020-01-02 Min. :-0.3708985
## 1st Qu.:2020-07-09 1st Qu.:-0.0164914
## Median :2021-01-14 Median : 0.0006833
## Mean :2021-01-14 Mean : 0.0001380
## 3rd Qu.:2021-07-22 3rd Qu.: 0.0197512
## Max. :2022-01-27 Max. : 0.1967904
sd(pbr_ret20)
## [1] 0.04378049
Considere que a API do Yahoo Finance não esteja funcionando. Obtenha a base de preços diretamente do site, buscando pelo tick da ação ou pelo nome da empresa. Na página do ativo, basta clicar em “Historical Data” e selecionar o período desejado antes de clicar em “Download Data”, conforme imagem abaixo:
O arquivo baixado estará no formato .csv.
read.csv() do R básico ou read_csv do pacote readr para ler o arquivo e atribuí-lo a um data frame.xts() para transformar a base do tipo data frame em xts.Bom trabalho.
Parte deste texto está livremente baseado em “Introdução à Análise de Ações com R”, de Gustavo Monteiro.↩︎