A criação de fronteiras eficientes é uma tarefa desafiadora e complexa no campo da análise de carteiras de investimento. Com o aumento da disponibilidade de dados e o avanço da tecnologia, surgem novas ferramentas e técnicas para auxiliar nessa tarefa. No entanto, ainda há dificuldades em se construir fronteiras eficientes de forma fácil e precisa. Nesse contexto, o uso do RStudio, juntamente com o pacote ggplot2, oferece uma abordagem eficaz para criar fronteiras eficientes de maneira mais intuitiva e visualmente atraente.
Ao longo deste trabalho, exploraremos o processo de criação de fronteiras eficientes usando o RStudio e o pacote ggplot. A ideia é gerar várias carteiras aleatórias e, em seguida, simular sua plotagem em uma fronteira eficiente. O objetivo é ilustrar como essas ferramentas podem facilitar o processo de análise e seleção de carteiras, fornecendo uma representação visual clara e informativa das opções de investimento.
Com a ajuda do método de Monte Carlo (MMC), onde esse método consiste em criar pesos aleatórios com as retrições impostas pela definição vetorial de carteiras e calcular medidas de risco e retorno, e finalmente, traçar a área de possibilidades de todas as carteiras.
Além disso, iremos explorar o uso do pacote fPortfolio para obter carteiras ótimas, ou seja, carteiras que são dominantes em relação a todas as outras com o mesmo nível de risco. Essas carteiras ótimas representam combinações ideais de ativos que maximizam o retorno esperado dado um nível de risco.
Através desse estudo, esperamos contribuir para a compreensão e aplicação prática da análise de carteiras de investimento, mostrando como o R e o pacote ggplot2 podem ser ferramentas valiosas para a plotagem de área de possibilidade de todas carteiras.
De antemão, os todos os pacotes a serem utilizados em todo o trabalho são:
library(ggplot2)
library(dplyr)
library(fPortfolio)
library(tidyverse)
library(tidyquant)
library(ROI.plugin.quadprog)
library(ROI.plugin.glpk)
library(timetk)
library(PortfolioAnalytics)
Primeiramente definindo quantas ações teram nas nossas nossas carteiras, usaremos cinco ações:
PRIO3.SA
GGBR4.SA
GOAU4.SA
PETR4.SA
PETR3.SA
A partir dos dados disponiveis no formato de tabela wide, podemos calcular as matriz coluna das medias de retorno e a matriz quadrada de covariância
Iremos usar o pacote tidyquant para baixar esses dados direto da rede. Como o intuito não é mostrar como se baixar os dados, omitiremos os comando
Nossa tabela de retornos mensais do período entre 2018 e 2022 terá o nome de “tbl_retornos_wide_training”
tbl_retornos_wide_training
## PRIO3.SA GGBR4.SA GOAU4.SA PETR4.SA PETR3.SA
## 2018-01-31 0.079462098 0.163166558 0.188255779 0.223602703 0.259609758
## 2018-02-28 -0.178935435 0.154166713 0.145348472 0.089339779 0.086854437
## 2018-03-31 -0.186206959 -0.065651120 -0.093908591 -0.002329662 0.009071576
## 2018-04-30 0.231186525 0.074193750 0.095238373 0.072863251 0.054366282
## 2018-05-31 -0.018447161 -0.106950116 -0.124696000 -0.172052393 -0.097517543
## 2018-06-30 -0.018232835 -0.060135258 -0.092511171 -0.094309656 -0.124831333
## 2018-07-31 0.145857166 0.199137278 0.244336964 0.147178429 0.129763359
## 2018-08-31 0.178531330 -0.029854005 0.031434813 -0.020883725 0.008632397
## 2018-09-30 0.174230439 0.071695925 0.015267019 0.095015584 0.097373345
## 2018-10-31 0.072072110 -0.054101203 -0.005012540 0.309625495 0.251341195
## 2018-11-30 -0.186554665 -0.039838854 -0.066873056 -0.074527363 -0.068828696
## 2018-12-31 0.024793377 -0.042635643 -0.051912414 -0.078551691 -0.095134016
## 2019-01-31 0.159274188 0.056005263 0.073486926 0.127866196 0.163385768
## 2019-02-28 0.312869555 -0.032587791 -0.036241612 0.057857764 0.010490701
## 2019-03-31 0.251821459 0.006698027 -0.002726254 0.036954652 0.043201816
## 2019-04-30 -0.023809501 -0.065389732 -0.043600447 -0.033177973 -0.038202382
## 2019-05-31 -0.058536606 -0.014768663 -0.041075207 -0.053972158 -0.054460546
## 2019-06-30 -0.092112820 0.095890442 0.117284087 0.072798421 0.063407657
## 2019-07-31 0.116043098 -0.095394731 -0.081491903 -0.048522219 -0.040972547
## 2019-08-31 -0.039772690 -0.058804114 -0.054125628 -0.014555713 -0.010959234
## 2019-09-30 0.030769186 0.022533301 0.000000000 0.080392073 0.066501538
## 2019-10-31 0.061997727 0.020516586 0.006400239 0.103085396 0.084577149
## 2019-11-30 0.257297268 0.269145150 0.243556774 -0.034431467 -0.040051584
## 2019-12-31 0.421324174 0.176470500 0.189743460 0.049662993 0.025641253
## 2020-01-31 0.449788333 0.002500058 0.026939622 -0.057322678 -0.051562599
## 2020-02-29 -0.177967896 -0.155611066 -0.165792267 -0.109314579 -0.105436628
## 2020-03-31 -0.576142149 -0.405325410 -0.413619166 -0.447908462 -0.479189722
## 2020-04-30 0.224550975 0.168159301 0.107526982 0.290277095 0.356030055
## 2020-05-31 0.514914393 0.143952200 0.198058196 0.126869822 0.117426315
## 2020-06-30 0.142349896 0.192107201 0.184765017 0.059488695 0.071976938
## 2020-07-31 0.118677613 0.089943689 0.099863188 0.030183107 0.026487380
## 2020-08-31 0.058095482 0.093982952 0.093283643 -0.013963949 -0.016740193
## 2020-09-30 -0.167104327 0.089575791 0.069396789 -0.104157216 -0.114247211
## 2020-10-31 -0.102321612 0.048557475 0.042553266 -0.034166245 -0.038948075
## 2020-11-30 0.601851931 0.041775736 0.054230998 0.314678034 0.344736850
## 2020-12-31 0.399043208 0.089451916 0.106396297 0.138152573 0.129158675
## 2021-01-31 0.004274075 -0.049079731 -0.060390694 -0.058221587 -0.052686348
## 2021-02-28 0.186125736 0.112688198 0.094517625 -0.166729169 -0.189535290
## 2021-03-31 0.103695685 0.173599044 0.165538962 0.083633115 0.080812602
## 2021-04-30 -0.007585576 0.099272089 0.108128128 0.013068424 -0.002292730
## 2021-05-31 0.077200238 0.002556356 0.011114163 0.137595214 0.153679805
## 2021-06-30 -0.012164206 -0.100546851 -0.066801598 0.095273523 0.136585390
## 2021-07-31 -0.084145685 0.040189160 0.030368843 -0.085626863 -0.092109726
## 2021-08-31 0.073949561 -0.063857867 -0.074100433 0.070584765 0.074194690
## 2021-09-30 0.305164338 -0.029273914 -0.023579308 0.001471115 0.008237838
## 2021-10-31 -0.061950484 -0.007379872 0.007246458 -0.002938060 -0.017051497
## 2021-11-30 -0.135492053 0.026986876 -0.015662586 0.083977958 0.089266238
## 2021-12-31 0.018728395 0.056589226 0.068544738 0.085953373 0.140755078
Para calcular a matriz de retorno e covariância
matriz_retornos <- matrix(colMeans(tbl_retornos_wide_training), nrow = 5)
matriz_retornos
## [,1]
## [1,] 0.07642619
## [2,] 0.02717335
## [3,] 0.02718135
## [4,] 0.02687056
## [5,] 0.02818350
matriz_covariancia <- matrix(cov(tbl_retornos_wide_training), nrow = 5, ncol = 5)
matriz_covariancia
## [,1] [,2] [,3] [,4] [,5]
## [1,] 0.04451993 0.012053739 0.013773104 0.014974062 0.015353563
## [2,] 0.01205374 0.013064948 0.013131197 0.008046519 0.008199882
## [3,] 0.01377310 0.013131197 0.013877065 0.008857461 0.008949430
## [4,] 0.01497406 0.008046519 0.008857461 0.017098885 0.017699855
## [5,] 0.01535356 0.008199882 0.008949430 0.017699855 0.018955139
A definição dos pesos aleatórios. Criando vetores com as ações e números de ações:
acoes <- c("PRIO3.SA","GGBR4.SA","GOAU4.SA","PETR4.SA","PETR3.SA")
n_ativos <- length(acoes)
n_ativos
## [1] 5
Demonstração de como funciona os pesos aleatórios
#Criando vetores aleatrios de cinco entrada
#Todas as entrar dentro do intervalo [0,1]
pesos <- runif(n_ativos)
pesos
## [1] 0.5682308 0.2729528 0.5931291 0.2853758 0.1129870
# Assegurando que a soma de todos será um.
pesos <- pesos/sum(pesos)
pesos
## [1] 0.3100553 0.1489368 0.3236411 0.1557154 0.0616514
sum(pesos)
## [1] 1
Ou seja, com base nisto toda vez que rodarmos o comando de “pesos” estaresmos criando um novo vetor
Criando uma função para calcular os retornos e risco de uma carteira aleatoria dado o números de ativos que se tem.
cal_retor_ris_ale <- function(n_ativos) {
pesos <- runif(n_ativos)
pesos <- pesos / sum(pesos)
retorno<- t(matriz_retornos)%*%pesos
matriz_pesos <- matrix(pesos, nrow = 5)
risco <- sqrt(t(matriz_pesos)%*%matriz_covariancia%*%matriz_pesos)
return(data.frame(Retorno = retorno, Risco = risco))
}
Agora criaremos um loop para gerar várias carteiras e já calcular oque desejamos e agrupar em data frame.
#número de repetições
reps <- 10000
#Criando um data frame vazia para recer os dados
df_resultados <- data.frame()
#criando um loop para simular varias carteiras
for (i in 1:reps) {
ret_ris <- cal_retor_ris_ale(n_ativos)
#risco <- calcular_risco(n_ativos)
df_resultados <- rbind(df_resultados, ret_ris)
}
Dessa maneira já poderemos plotar um simples gráfico usando o ggplot2, cujo mostra as possibilidades de carteiras:
Como o intuito é mostrar a ideia de como fazer os pesos aleatórios o detalhamento visual do gráfico será explicado ao final do trabalho.
ggplot(df_resultados, aes(x= Risco , y = Retorno))+
geom_point()
Percebe-se que não tem a área completamente preenchida, pois, o método usado é aleatoriedade. Porém se da para ter uma boa noção de como seria a área toda preenchida.
Uma vez que você tenha carteiras ótimas e queria colocar no gráfico, basta calcular os risco e retorno, colocar em data frame, e adicionar ao gráfico, as carteiras que usaramos serão quatros, uma de variância mínima, máximo retorno esperado, máximo índide de Sharpe e por último uma de pesos iguais, descritas vetorialmente por (Valores aprozimados):
\[ \text{pesos_var_min} =\begin{pmatrix} 0,05 & 0,58 & 0,05 & 0,27 & 0,05 \end{pmatrix}^T \] \[ \text{pesos_retorno_maximo} =\begin{pmatrix} 0,70 & 0,05 & 0,05 & 0,05 & 0,15 \end{pmatrix}^{T} \]
\[ \text{pesos_sharpe} =\begin{pmatrix} 0,66 & 0,19 & 0,05 & 0,05 & 0,05 \end{pmatrix}^T \]
\[ \text{pesos_neutro}=\begin{pmatrix} 0,20 & 0,20 & 0,20 & 0,20 & 0,20 \end{pmatrix}^T \]
Cateiras ótimas podem ser obtidas por diversas maneiras, no caso, essas carteiras foram obtidas através do pacote PortfolioAnalytics.
## ***********************************
## PortfolioAnalytics Optimization
## ***********************************
##
## Call:
## optimize.portfolio(R = ., portfolio = carteira_min_var, optimize_method = "quadprog",
## trace = TRUE)
##
## Optimal Weights:
## PRIO3.SA GGBR4.SA GOAU4.SA PETR4.SA PETR3.SA
## 0.0500 0.5758 0.0500 0.2742 0.0500
##
## Objective Measure:
## StdDev
## 0.1077
## ***********************************
## PortfolioAnalytics Optimization
## ***********************************
##
## Call:
## optimize.portfolio(R = ., portfolio = portfolio_retorno_maximo,
## optimize_method = "glpk", trace = TRUE)
##
## Optimal Weights:
## PRIO3.SA GGBR4.SA GOAU4.SA PETR4.SA PETR3.SA
## 0.70 0.05 0.05 0.05 0.15
##
## Objective Measure:
## mean
## 0.06179
## ***********************************
## PortfolioAnalytics Optimization
## ***********************************
##
## Call:
## optimize.portfolio(R = ., portfolio = portfolio_sharpe, optimize_method = "ROI",
## trace = TRUE, maxSR = TRUE)
##
## Optimal Weights:
## PRIO3.SA GGBR4.SA GOAU4.SA PETR4.SA PETR3.SA
## 0.661 0.189 0.050 0.050 0.050
##
## Objective Measure:
## StdDev
## 0.1634
##
##
## mean
## 0.05977
Todas as carteiras obtidas são ótimas no cenário de que todas as propoções das ações estejam no interlado de 5% à 70%.
Adicionando os dados no R
pesos_var_minima
## PRIO3.SA GGBR4.SA GOAU4.SA PETR4.SA PETR3.SA
## 0.0500000 0.5757911 0.0500000 0.2742089 0.0500000
pesos_retorno_maximo
## PRIO3.SA GGBR4.SA GOAU4.SA PETR4.SA PETR3.SA
## 0.70 0.05 0.05 0.05 0.15
pesos_sharpe
## PRIO3.SA GGBR4.SA GOAU4.SA PETR4.SA PETR3.SA
## 0.6610451 0.1889549 0.0500000 0.0500000 0.0500000
pesos_neutro
## [1] 0.2 0.2 0.2 0.2 0.2
Criando uma função para calcular o retorno e risco de pesos específico, e criar um data frame com os resultados
#Função
cal_ris_ret<- function(pesos){
matriz_pesos <- matrix(pesos, nrow = 5)
retorno<- t(matriz_retornos)%*%pesos
risco <- sqrt(t(matriz_pesos)%*%matriz_covariancia%*%matriz_pesos)
return(data.frame(Retorno = retorno, Risco = risco))
}
# Lista de pesos obtidos
lista_pesos <- list(pesos_var_minima,
pesos_retorno_maximo,
pesos_sharpe,
pesos_neutro)
# Aplicar a função cal_ris_ret a cada conjunto de pesos usando lapply
Ret_ris_otimos <- do.call(rbind, lapply(lista_pesos, cal_ris_ret))
#Data frame com risco e retorno das carteiras otimas obtidas
Estrategias<- c("pesos_var_minima","pesos_retorno_maximo","pesos_sharpe","pesos_neutro")
rownames(Ret_ris_otimos) <- Estrategias
Ret_ris_otimos
## Retorno Risco
## pesos_var_minima 0.02960387 0.1077168
## pesos_retorno_maximo 0.06178712 0.1706007
## pesos_sharpe 0.05976746 0.1634159
## pesos_neutro 0.03716699 0.1182529
De maneira isolada podemos plota apenas as carteiras
ggplot(data = Ret_ris_otimos, aes(x= Risco , y = Retorno))+
geom_point()
Jutando no que já temos
ggplot(df_resultados, aes(x= Risco , y = Retorno))+
geom_point(size=0.02)+
geom_point(color = "green")+
geom_point(data = Ret_ris_otimos, color = "red", size = 2)
Agora através do pacote fPortfolio podemos acessar os pesos das carteiras eficientes
Transformando os dados em series temporais, usando o as.timeSerias
returns_tempo <- as.timeSeries(tbl_retornos_wide_training)
Caculando a froteira eficiente com o portfolioFrontier() do fPortfolio, observa-se que as cartiras obtidas serão para um problema de caixa de limitação de ativos, 5% à 70%
fronteira <- portfolioFrontier(returns_tempo,
constraints = c("minW[1:5]=0.05", "maxW[1:5]=0.7", "maxsumW[c(1:5)]=1 "))
class(fronteira)
## [1] "fPORTFOLIO"
## attr(,"package")
## [1] "fPortfolio"
A partir desse objeto ‘fronteira’ podemos acessar os pesos eficientes, e colocando em um data frame, daí calcularmos o retorno espera eo risco:
pesos_eficentes<- data.frame(fronteira@portfolio@portfolio$weights)%>%
rowwise() %>%
mutate(Retorno = t(matriz_retornos)%*%
matrix(c(PRIO3.SA, GGBR4.SA, GOAU4.SA, PETR4.SA, PETR3.SA), ncol = 1)) %>%
mutate(Risco = sqrt(t(matrix(c(PRIO3.SA, GGBR4.SA, GOAU4.SA, PETR4.SA, PETR3.SA), ncol = 1))%*%
matriz_covariancia %*%
matrix(c(PRIO3.SA, GGBR4.SA, GOAU4.SA, PETR4.SA, PETR3.SA), ncol = 1)))
Isoladamente:
ggplot(pesos_eficentes, aes(x= Risco , y = Retorno))+
geom_point()
Agrudando com já temos:
ggplot(df_resultados, aes(x= Risco , y = Retorno))+
geom_point(size=0.02)+
geom_point(color = "green")+
geom_point(data = Ret_ris_otimos, color = "red", size = 2)+
geom_point(data = pesos_eficentes, color= "blue", size=2)
Vale ressaltar que as restrições aplicadas nesta etapa, podem ser facilmente ajustadas de acordo com as necessidades e preferências individuais dos investidores. No exemplo apresentado, as restrições foram definidas para limitar a participação individual de cada ativo entre 5% e 70% do portfólio total.
Essas restrições fornecem uma maneira flexível de controlar a exposição a cada ativo e permitem uma diversificação adequada, evitando concentrações excessivas em um único ativo. No entanto, é importante destacar que esses limites podem ser personalizados e adaptados às preferências de cada investidor, de acordo com sua tolerância ao risco e objetivos específicos.
Os pesos individuais podem ser descrito como uma matriz identidade 5x5.
Pesos_individuais<- diag(length(acoes)) %>%
as.data.frame()
colnames(Pesos_individuais) <- acoes
Pesos_individuais
## PRIO3.SA GGBR4.SA GOAU4.SA PETR4.SA PETR3.SA
## 1 1 0 0 0 0
## 2 0 1 0 0 0
## 3 0 0 1 0 0
## 4 0 0 0 1 0
## 5 0 0 0 0 1
Calculando o risco e o retorno esperado e agrupando em um data frame.
Ret_ris_ind<- Pesos_individuais %>%
rowwise() %>%
mutate(Retorno = t(matriz_retornos)%*%
matrix(c(PRIO3.SA, GGBR4.SA, GOAU4.SA, PETR4.SA, PETR3.SA), ncol = 1)) %>%
mutate(Risco = sqrt(t(matrix(c(PRIO3.SA, GGBR4.SA, GOAU4.SA, PETR4.SA, PETR3.SA), ncol = 1))%*%
matriz_covariancia %*%
matrix(c(PRIO3.SA, GGBR4.SA, GOAU4.SA, PETR4.SA, PETR3.SA), ncol = 1)))
Ret_ris_ind<- cbind(acoes, Ret_ris_ind)
Ret_ris_ind
## acoes PRIO3.SA GGBR4.SA GOAU4.SA PETR4.SA PETR3.SA Retorno Risco
## 1 PRIO3.SA 1 0 0 0 0 0.07642619 0.2109975
## 2 GGBR4.SA 0 1 0 0 0 0.02717335 0.1143020
## 3 GOAU4.SA 0 0 1 0 0 0.02718135 0.1178010
## 4 PETR4.SA 0 0 0 1 0 0.02687056 0.1307627
## 5 PETR3.SA 0 0 0 0 1 0.02818350 0.1376777
#Plotando no gráfico A plotagem dos ativos individuais:
ggplot(Ret_ris_ind, aes(x= Risco , y = Retorno, color = acoes))+
geom_point(size=2)
Juntando com os demais graficos:
ggplot(df_resultados, aes(x= Risco , y = Retorno))+
geom_point(size=0.02)+
geom_point(color = "green")+
geom_point(data = Ret_ris_otimos, color = "red", size = 2)+
geom_point(data = pesos_eficentes, color= "blue", size=0.5)+
geom_point(data = Ret_ris_ind, color="orange", size= 2)
O objetivo principal deste “tutorial” foi demonstrar como podemos utilizar as ferramentas do pacote ggplot2 para modificar e aprimorar o gráfico gerado. O ggplot2 é amplamente utilizado e reconhecido por sua capacidade de criar visualizações de alta qualidade. Nesta etapa, faremos ajustes que resultarão em melhorias visuais significativas no gráfico, elevando ainda mais seu impacto e clareza.
ggplot(df_resultados, aes(x= Risco , y = Retorno))+
geom_point(size=0.02)+
geom_point(color = "green")+
geom_point(data = Ret_ris_otimos, color = "red", size = 2)+
geom_point(data = pesos_eficentes, color= "blue", size=0.5)+
geom_point(data = Ret_ris_ind, color = "orange", size= 2)+
labs(x = "Risco", y = "Retorno esperado")+ #adicionando eixos
scale_y_continuous(labels = scales::percent)+
scale_x_continuous(labels = scales::percent)
É importante destacar que este trabalho não pretende ser um tutorial completo sobre o ggplot2, mas sim uma demonstração do seu potencial como uma ferramenta poderosa para visualização de dados e criação de fronteiras eficientes. Ao disponibilizar o código e as configurações utilizadas, incentivamos os usuários a explorar diferentes estilos, cores, formas e elementos gráficos, permitindo uma expressão pessoal e uma abordagem única na representação das fronteiras eficientes. Dessa forma, cada pessoa pode personalizar as visualizações de acordo com suas necessidades e objetivos, proporcionando uma experiência enriquecedora e criativa no processo de análise e interpretação dos resultados obtidos.
A criação de fronteiras eficientes no campo da análise de carteiras de investimento é uma tarefa desafiadora, mas fundamental para tomar decisões informadas sobre alocação de ativos. Neste trabalho, exploramos o uso do RStudio em conjunto com o pacote ggplot e fPortfolio para facilitar e aprimorar o processo de criação e análise de fronteiras eficientes.
Ao utilizar o ggplot, pudemos gerar visualizações intuitivas e atraentes das carteiras aleatórias, permitindo uma compreensão clara das opções de investimento. Em seguida, com o auxílio do fPortfolio, fomos capazes de obter carteiras ótimas, identificando combinações de ativos que oferecem o máximo retorno esperado para um determinado nível de risco.
Em conclusão, a utilização do RStudio, ggplot e fPortfolio possibilita a criação de fronteiras eficientes e a obtenção de carteiras ótimas, ao mesmo tempo em que permite ajustar facilmente as restrições de alocação de ativos. Essas ferramentas combinadas oferecem uma abordagem abrangente e personalizável para a análise e seleção de carteiras de investimento, fornecendo uma base sólida para a tomada de decisões embasadas e a maximização do potencial de retorno ajustado ao risco.