1 Introdução

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)

2 Plotagem das carteiras aleatórias

2.1 Dados e principais medidas

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

2.2 Definindo os pesos aleatórios

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

2.3 Criando função para calcular retorno esperado e risco

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.

3 Plotagem com carteiras ótimas

3.1 Carteiras ótimas obtidas

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

3.2 Calculando o risco e retorno

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

3.3 Plotando no gráfico

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)

4 Plotagem da carteiras ótimas

Agora através do pacote fPortfolio podemos acessar os pesos das carteiras eficientes

4.1 Acessando os dados

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)))

4.2 Plotagem no gráfico

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.

5 Plotagem dos ativos individuais

5.1 Pesos individuais

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

5.2 Calculando o risco e retorno

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)  

6 Alterando o gráfico

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.

7 Conclusão

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.