Análise de Ações Brasileiras
1 Introdução
Nesta apresentação, analisamos as ações da Azul, Vale, Petrobrás e Itaú desde 2015, com: - preços semanais, - retornos logarítmicos, - estatísticas descritivas (média, desvio padrão, coeficiente de variação, razão de Sharpe ~ 1/CV), - histogramas com kernel e linha vertical na média, - e densidades sobrepostas.
2 Preços semanais das ações
3 Retornos (%)
4 Estatísticas resumo
5 Distribuição dos dados
6 Comparação das distribuições dos retornos
7 Códigos
Mostrar/ocultar códigos
# install.packages(c("quantmod","tidyverse","plotly","DT"))
library(quantmod)
library(tidyverse)
library(plotly)
library(DT)
# Download dos dados (Yahoo Finance)
tickers <- c("VALE3.SA","PETR4.SA","ITUB4.SA")
rotulos <- c("VALE3.SA"="Vale", "PETR4.SA"="Petrobrás", "ITUB4.SA"="Itaú")
get_weekly_prices <- function(sym, from = "2015-01-01") {
xt <- getSymbols(sym, src = "yahoo", from = from, auto.assign = FALSE)
wk <- to.period(Ad(xt), period = "weeks", OHLC = FALSE) # série semanal do preço ajustado
tibble(
date = as.Date(index(wk)),
price = as.numeric(wk[, 1]),
symbol = sym
)
}
prices <- map_dfr(tickers, get_weekly_prices) %>%
arrange(symbol, date)
# Retornos logarítmicos semanais
returns <- prices %>%
group_by(symbol) %>%
arrange(date, .by_group = TRUE) %>%
mutate(ret = log(price / dplyr::lag(price))) %>%
filter(!is.na(ret), is.finite(ret)) %>%
ungroup()
# Funções auxiliares (gráficos)
# Preços: um painel por ativo
make_price_fig <- function(df_sym) {
plot_ly(df_sym, x = ~date, y = ~price, type = "scatter", mode = "lines",
name = rotulos[unique(df_sym$symbol)]) %>%
layout(
title = list(text = rotulos[unique(df_sym$symbol)]),
yaxis = list(title = df_sym$symbol[1]),
showlegend = FALSE
)
}
# Retornos: um painel por ativo, com linha horizontal na média
make_return_fig <- function(df_sym) {
m <- mean(df_sym$ret, na.rm = TRUE)
plot_ly(df_sym, x = ~date, y = ~ret, type = "scatter", mode = "lines",
name = rotulos[unique(df_sym$symbol)]) %>%
layout(
title = list(text = paste0(rotulos[unique(df_sym$symbol)], " — retornos (log)")),
yaxis = list(title = df_sym$symbol[1]),
showlegend = FALSE,
shapes = list(list(
type = "line", xref = "x", yref = "y",
x0 = min(df_sym$date), x1 = max(df_sym$date),
y0 = m, y1 = m,
line = list(dash = "dash", width = 1)
)),
annotations = list(list(
x = max(df_sym$date), y = .25, xref = "x", yref = "y",
text = sprintf("média = %.4f", m), showarrow = FALSE,
xanchor = "right", yanchor = "bottom"
))
)
}
# Histograma + densidade + linha vertical na média (plotly)
make_hist_density <- function(vec, titulo, papel) {
vec <- vec[is.finite(vec)]
dens <- density(vec)
m <- mean(vec, na.rm = TRUE)
plot_ly() %>%
add_histogram(x = vec,
histnorm = "probability density",
nbinsx = 50,
name = "Histograma",
showlegend = FALSE) %>%
add_lines(x = dens$x, y = dens$y,
name = "Densidade (kernel)",
showlegend = FALSE) %>%
layout(
title = titulo,
xaxis = list(title = paste("Retorno - ",papel)),
yaxis = list(title = "Densidade"),
# linha vertical na média (corrigido: shapes no plotly, yref = 'paper')
shapes = list(list(
type = "line",
xref = "x", yref = "paper",
x0 = m, x1 = m,
y0 = 0, y1 = 1,
line = list(dash = "dot", width = 1)
)),
annotations = list(list(
x = m, y = 1, xref = "x", yref = "paper",
text = sprintf("média = %.4f", m),
showarrow = TRUE, ax = 0, ay = -20
))
)
}
# Preços semanais
fig_preco_list <- prices %>%
split(.$symbol) %>%
lapply(make_price_fig) %>%
unname()
fig_precos <- do.call(
subplot,
c(fig_preco_list,
list(nrows = 3, shareX = TRUE, titleY = TRUE, margin = 0.03))
) %>%
layout(title = "Preços (R$) semanais (ajustados)",
xaxis = list(title = "Data"))
# Retornos semanais
fig_ret_list <- returns %>%
split(.$symbol) %>%
lapply(make_return_fig) %>%
unname()
fig_retornos <- do.call(
subplot,
c(fig_ret_list,
list(nrows = 3, shareX = TRUE, titleY = TRUE, margin = 0.03))
) %>%
layout(title = "Retornos semanais (log - %) com linha de média",
xaxis = list(title = "Data"))
# Estatísticas descritivas
resumo <- returns %>%
group_by(symbol) %>%
summarise(
Empresa = rotulos[first(symbol)],
`Média (log)` = mean(ret, na.rm = TRUE),
`Mediana (log)` = median(ret, na.rm = TRUE),
`Desvio Padrão` = sd(ret, na.rm = TRUE),
`Coef. de Variação` = `Desvio Padrão` / abs(`Média (log)`),
.groups = "drop"
) %>%
select(Empresa, `Média (log)`,`Mediana (log)`, `Desvio Padrão`, `Coef. de Variação`)
TABELA <- datatable(
resumo %>%
mutate(
`Média (log)` = round(`Média (log)`, 5),
`Mediana (log)` = round(`Mediana (log)`, 5),
`Desvio Padrão` = round(`Desvio Padrão`, 5),
`Coef. de Variação` = round(`Coef. de Variação`, 2),
`Razão de Sharpe = (1/CV)` = round(1/`Coef. de Variação`, 2)
),
rownames = FALSE,
options = list(pageLength = 5),
caption = "Estatísticas dos retornos semanais (log - %) desde 2015"
)
# Histogramas dos retornos com densidade
hists <- returns %>%
mutate(Empresa = rotulos[symbol]) %>%
split(.$Empresa) %>%
lapply(function(d) make_hist_density(d$ret, "", d$symbol[1])) %>%
Filter(function(p) inherits(p, "plotly"), x = .) %>%
unname()
fig_hist_lado_a_lado <- do.call(
subplot,
c(hists,
list(nrows = 1, shareY = FALSE, titleX = TRUE, titleY = TRUE, margin = 0.03))
)
# Densidades sobrepostas (comparação)
densidades <- returns %>%
mutate(Empresa = rotulos[symbol]) %>%
split(.$Empresa) %>%
imap(~ {
d <- density(.x$ret, na.rm = TRUE)
tibble(x = d$x, y = d$y, Empresa = .y)
}) %>%
list_rbind()
fig_densidades <- plot_ly()
for (emp in unique(densidades$Empresa)) {
df_emp <- filter(densidades, Empresa == emp)
fig_densidades <- fig_densidades %>%
add_lines(data = df_emp, x = ~x, y = ~y, name = emp)
}
fig_densidades <- fig_densidades %>%
layout(title = "",
xaxis = list(title = ""),
yaxis = list(title = "Densidade"),
legend = list(orientation = "h", x = 0.5, xanchor = "center"))