Portfolio
Carrega os pacotes
library(tidyquant)
library(tidyverse)
Obtém os dados
Nota: conheça a sintaxe das funções utilizadas:
* map()
* reduce()
* ROC()
* to.monthly()
simbolos <- c("SPY", "EEM", "SHY", "IYR", "GLD")
simbolos_min <- tolower(simbolos)
precos <- getSymbols(simbolos, src = "yahoo",
from = "1990-01-01",
auto.assign = TRUE) %>%
map(~ Ad(get(.))) %>% # quantmod::Ad() para preços 'Ajustados'; get() retorna o valor do objeto
reduce(merge) %>%
`colnames<-`(simbolos_min)
# Calcula os preços no último dia de cada mês
precos_mes <- to.monthly(precos, indexAt = "last", OHLC = FALSE)
ret <- TTR::ROC(precos_mes)["2005/2019"]
naive <- ret[, c("spy", "shy")]
basico <- ret[, c("spy", "shy", "gld")]
Cria pesos e carteiras diferentes
peso1 <- rep(1 / (ncol(basico)), ncol(basico))
port1 <- Return.portfolio(basico, peso1) %>%
`colnames<-`("ret")
peso2 <- c(0.9, 0.10, 0)
port2 <- Return.portfolio(basico, weights = peso2) %>%
`colnames<-`("ret")
peson <- c(0.5, 0.5)
portn <- Return.portfolio(naive, peson)
port_comp <- data.frame(data = index(port1), igual = as.numeric(port1),
wtd = as.numeric(port2),
naive = as.numeric(portn))
port_comp %>%
gather(key, value, -data) %>%
group_by(key) %>%
mutate(value = cumprod(value + 1)) %>%
ggplot(aes(data, value * 100, color = key)) +
geom_line() +
scale_color_manual("",
labels = c("Igual", "Naive", "Arriscado"),
values = c("blue", "black", "red")) +
labs(x = "",
y = "Índice",
title = "Três portfolios, qual é o melhor?",
caption = "Fonte: Yahoo, OSM estimates") +
theme(legend.position = "top",
plot.caption = element_text(hjust = 0))

Tabela de resumos do Portfolio
port_comp %>%
rename("Igual" = igual,
"Naive" = naive,
"Arriscado" = wtd) %>%
gather(Asset, value, -data) %>%
group_by(Asset) %>%
summarise(`Média (%)` = round(mean(value, na.rm = TRUE),3) * 1200,
`Volatilidade (%)` = round(sd(value, na.rm = TRUE) * sqrt(12), 3) * 100,
`Ajustado ao risco (%)` = round(mean(value, na.rm = TRUE) / sd(value, na.rm = TRUE) * sqrt(12), 3) * 100,
`Cumulativo (%)` = round(prod(1 + value, na.rm = TRUE), 3) * 100) %>%
knitr::kable(caption = "Métricas de desempenho anualizadas")
Métricas de desempenho anualizadas
| Arriscado |
6.0 |
13.4 |
47.9 |
192.9 |
| Igual |
3.6 |
8.5 |
40.5 |
144.5 |
| Naive |
3.6 |
7.3 |
51.8 |
152.2 |
Funções para o cálculo de semi-variância
down_dev <- function(vec){
mean_vec <- mean(vec, na.rm = TRUE)
down_vec <- vec[vec < mean_vec]
dev <- sqrt(mean((down_vec - mean_vec)^2))
dev
}
up_dev <- function(vec){
mean_vec <- mean(vec, na.rm = TRUE)
up_vec <- vec[vec > mean_vec]
dev <- sqrt(mean((up_vec - mean_vec)^2))
dev
}
Tabela da semi-variância
port_comp %>%
rename("Igual" = igual,
"Naive" = naive,
"Arriscado" = wtd) %>%
gather(Asset, value, -data) %>%
group_by(Asset) %>%
summarise(`Volatilidade negativa (%)` = round(down_dev(value)*sqrt(12),3)*100,
`Volatilidade positiva (%)` = round(up_dev(value)*sqrt(12),3)*100) %>%
knitr::kable(caption = "Métricas de desempenho anualizadas")
Métricas de desempenho anualizadas
| Arriscado |
15.8 |
10.9 |
| Igual |
9.1 |
7.8 |
| Naive |
8.5 |
6.0 |
Simulação de Portfolios
Portfolio
mean_ret <- apply(ret[-1, c("spy", "shy", "gld")], 2, mean)
cov_port <- cov(ret[-1, c("spy", "shy", "gld")])
port_exam <- data.frame(ports = colnames(port_comp)[-1],
ret = as.numeric(apply(port_comp[,-1],2, mean)),
dp = as.numeric(apply(port_comp[,-1], 2, sd)))
port_exam
Pesos aleatórios que garantem mais variação da participação das ações no portfolio
set.seed(123)
wts <- matrix(nrow = 1000, ncol = 3)
for(i in 1:1000){
a <- runif(1,0,1)
b <- c()
for(j in 1:2){
b[j] <- runif(1,0,1-sum(a,b))
}
if(sum(a,b) < 1) {
inc <- (1-sum(a,b))/3
vec <- c(a+inc, b+inc)
} else {
vec <- c(a,b)
}
wts[i,] <- sample(vec,replace = FALSE)
}
Calcula os portfolios aleatórios
port <- matrix(nrow = 1000, ncol = 2)
for(i in 1:1000){
port[i,1] <- as.numeric(sum(wts[i,] * mean_ret))
port[i,2] <- as.numeric(sqrt(t(wts[i,] %*% cov_port %*% wts[i,])))
}
colnames(port) <- c("retornos", "risco")
port <- as.data.frame(port)
port
Gráfico de pontos
port %>%
ggplot(aes(risco*sqrt(12)*100, retornos*1200)) +
geom_point(color = "blue", size = 1.2, alpha = 0.4) +
geom_point(data = port_exam, aes(port_exam[1,3]*sqrt(12)*100,
port_exam[1,2]*1200),
color = "red", size = 6) +
geom_point(data = port_exam, aes(port_exam[2,3]*sqrt(12)*100,
port_exam[2,2]*1200),
color = "purple", size = 7) +
geom_point(data = port_exam, aes(port_exam[3,3]*sqrt(12)*100,
port_exam[3,2]*1200),
color = "black", size = 5) +
scale_x_continuous(limits = c(0,14)) +
labs(x = "Risco (%)",
y = "Retorno (%)",
title = "Portfolios simulados")

Portfolios dominados
naive_dom <- port %>%
filter(risco < port_exam[3,3]+0.0005,
risco > port_exam[3,3]-0.0005) %>%
summarise(round(max(retornos) - port_exam[3,2],4)*1200+.02) %>%
as.numeric()
naive_dom
## [1] 0.02
equal_dom <- port %>%
filter(risco < port_exam[1,3]+0.0005,
risco > port_exam[1,3]-0.0005) %>%
summarise(round(max(retornos) - port_exam[1,2],3)*1200) %>%
as.numeric()
equal_dom
## [1] 1.2
risky_dom <- port %>%
filter(risco < port_exam[2,3]+0.0005,
risco > port_exam[2,3]-0.0005) %>%
summarise(round(max(retornos) - port_exam[2,2],4)*1200+.02) %>%
as.numeric()
risky_dom
## [1] 0.26
Encontra o máximo retorno e o risco equivalente para a mesma faixa de risco
equal_max <- port %>%
filter(risco < port_exam[1,3]+0.0005,
risco > port_exam[1,3]-0.0005) %>%
mutate(retornos = retornos*1200,
risco = risco * sqrt(12)*100) %>%
arrange(desc(retornos)) %>%
slice(1)
equal_max
Encontra os pesos para o porfolio dominante
eq_wt <- port %>%
mutate(spy_wt = wts[,1],
shy_wt = wts[,2],
gld_wt = wts[,3],
retornos = retornos * 1200,
risco = risco * sqrt(12) *100) %>%
filter(retornos == equal_max$retornos,
risco == equal_max$risco) %>%
select(spy_wt, shy_wt, gld_wt)
Gráfico dos pesos
eq_wt %>%
rename("SPY" = spy_wt,
"SHY" = shy_wt,
"GLD" = gld_wt) %>%
gather(key,value) %>%
ggplot(aes(factor(key, level = c("SPY", "SHY", "GLD")), value*100)) +
geom_bar(stat = 'identity', fill = "blue") +
geom_text(aes(label = round(value,2)*100), nudge_y = 5) +
labs(x = "Ativos",
y = "Pesos (%)",
title = "Pesos para um melhor resultado")
