1 CONHECENDO OS DADOS


Escolha das ações

As ações escolhidas foram a Gol e a Hapvida, além da utilização da Selic como o ativo livre de risco.


Ativos

Código Nome da Empresa Setor
GOLL4.SA Gol Linhas Aereas SA Empresas Aereas
HAPV3.SA Hapvida Participações e Investimentos S.A. Saúde Suplementar

Hapvida Participações e Investimentos S.A. :

Perfil Corporativo: A Hapvida é uma holding domiciliada no Brasil, com sede em Fortaleza, estado do Ceará. Ela atua no setor de saúde, oferecendo planos de assistência médica e odontológica. A empresa tem se destacado como a maior empresa de planos de saúde do Brasil, conquistando todos os estados do país. Seu compromisso é assegurar o acesso à saúde de qualidade para a população.

Cotação na B3: As ações da Hapvida (código HAPV3) estão listadas no Novo Mercado da B3. A companhia realizou seu IPO em 2018 e é controlada pela Ppar Pinheiro Participações S.A., que detém mais de 77% das ações ordinárias.

Gol Linhas Aéreas S.A. :

Perfil Corporativo: A Gol é uma companhia aérea brasileira que opera voos domésticos e internacionais. Com presença relevante nas principais regiões do Brasil, a Gol é conhecida por sua conectividade e serviços de transporte aéreo. Ela desempenha um papel fundamental no setor de aviação, proporcionando mobilidade e conectando pessoas e destinos.

Ativo Livre de Risco

Foi estabelecido o ativo ‘Risk Free’ como sendo a Selic

Taxa Selic (Banco Central) A sigla Selic provém do Sistema Especial de Liquidação e de Custódia, que é uma infraestrutura do mercado financeiro administrada pelo Banco Central. Essa taxa é calculada com base nas operações de empréstimos de um dia entre os bancos, nos quais títulos públicos federais são utilizados como garantia.

Obtenção dos Dados

Pacotes utilizados:

Pacote Explicação
dplyr Manipulação eficiente de dados
quantmod Análise quantitativa de dados financeiros
forecast Previsão de séries temporais
fImport Importação de dados financeiros
tidytext Manipulação de texto estruturado em análise de dados
stringr Manipulação de strings e expressões regulares
ggplot2 Criação de gráficos e plots
GetBCBData API do Bacen para disponibilizar dados
gridExtra Organização de plot de multiplos graficos
packages <- c('dplyr','GetBCBData','ggplot2','stringr','tidytext','forecast','quantmod','fImport','gridExtra')


# Carregar todos os pacotes
for (package in packages) {
  library(package, character.only = TRUE)
}
rm(package,packages)

Fonte dos Dados

A fonte dos dados é o Yahoo Finance, que é acessado por meio do pacote “quantmod”.

Ao chamar: getSymbols(symbol, src = "yahoo", from = start_date, to = end_date), o código está solicitando ao pacote “quantmod” para baixar os dados históricos da ação especificada usando o símbolo correspondente como um parâmetro de entrada.

Site de acesso a plataforma: https://finance.yahoo.com

Obtenção dos dados

Para as ações

O Código abaixo, em resumo, define os símbolos das ações, utiliza o pacote "quantmod" para baixar os dados históricos dessas ações do https://finance.yahoo.com e armazena-los em objetos separados para análise posterior.

# Definindo as datas de início e fim do período desejado
data_inicio <- as.Date("2023-05-01")
data_fim    <- as.Date("2024-02-01")

# Definindo os objetos das ações da área da saúde
chaves_acesso <- c("GOLL4.SA", "HAPV3.SA")

# Criando um loop para baixar os dados de todas as ações
for (chave in chaves_acesso) {
  getSymbols(chave, src = "yahoo", from = data_inicio, to = data_fim)
  
# Acessar os dados usando o nome do objeto criado pelo 'getSymbols'
assign(chave, get(chave))
  
# Aguardar um segundo antes de baixar o próximo símbolo (para evitar sobrecarga no servidor)
  Sys.sleep(1)
}

# Renomeando as bases
gol <- data.frame(GOLL4.SA) %>%  mutate(data = index(GOLL4.SA))
hapv <- data.frame(HAPV3.SA) %>% mutate(data = index(HAPV3.SA))

# Limpando os nomes das variaveis
names(gol) <- gsub('^GOLL4\\.SA\\.','',names(gol))
names(hapv) <- gsub('^HAPV3\\.SA\\.','',names(hapv))

Para a Selic

Para obter os dados da Selic, utilizamos um pacote que puxa a API do Banco Central brasileiro

# utilizando a API do Bacen para pegar os dados
selic_data <- gbcbd_get_series(
  id         = 12,
  first.date = data_inicio,   
  last.date  = data_fim   
)

knitr::kable(head(selic_data),align = "c")
ref.date value id.num series.name
2023-04-28 0.050788 12 id = 12
2023-05-02 0.050788 12 id = 12
2023-05-03 0.050788 12 id = 12
2023-05-04 0.050788 12 id = 12
2023-05-05 0.050788 12 id = 12
2023-05-08 0.050788 12 id = 12

Ele trás as informações já com as porcentagens trazidas à valor diário.

Variáveis utilizadas

As bases de dados geradas pelo código fornecido contém informações de preços históricos das ações escolhidas durante o período de 2023-05-01 a 2024-02-01. Essas bases de dados contém as seguintes variáveis:

Date:

A data correspondente ao preço de fechamento da ação.

Open:

O preço de abertura da ação no dia específico.

High:

O preço mais alto alcançado pela ação durante o dia.

Low:

O preço mais baixo alcançado pela ação durante o dia.

Close:

O preço de fechamento da ação no dia específico.

Volume:

O volume de negociações da ação no dia específico.

Adjusted:

Preço ajustado que considera eventos como divisões de ações e dividendos

2 ESTATÍSTICAS DESCRITIVAS


Retornos anualizados

Primeiramente, serão calculados os retornos anualizados de ambas as ações.

Com base nos preços diários das ações, construimos os retornos anualizados, utilizando a seguinte equação:

\[r_{i,t}= 252 \cdot \ln \left( \frac{P_{i,\ t}}{P_{i,\ t-1}} \right)\] onde:

  • \(P_{i,t}\) é o preço da ação;

  • \(i\) no período \(t\);

  • \(r_{i,t}\) é o retorno da ação \(i\) no período \(t\).

Para a Selic, como seus dados já estão em porcentagem a valor diário, utilizamos a seguinte equação:

\[r_{(t)} = 252 \ \cdot \ \ln \left( 1+ \frac {Selic_{(t)}}{100} \right)\]

A equação acima transforma a variação percentual dos preços diários em um retorno contínuo e depois o anualiza, multiplicando pelo número de dias úteis no ano. Isso é útil para comparar retornos de diferentes ativos ao longo do tempo em uma base anualizada.

Na prática, isso significa que a taxa de retorno contínua é mais precisa para cálculos financeiros que envolvem múltiplas composições ao longo do tempo. Ela é expressa em termos de logaritmos naturais (usando o símbolo: \(\ln\) ), o que facilita a manipulação matemática.

Portanto, Teremos:
retornos_gol     <- c()
retornos_hapvida <- c()
retornos_selic   <- c()

for (i in 2:nrow(gol)) {
  # calculando os retornos da GOL
  retornos_gol[i] <- 252 * log( 
    gol$Adjusted[i] / gol$Adjusted[i-1]
  )
  
  # calculando os retornos da HAPVIDA
  retornos_hapvida[i] <- 252 * log( 
    hapv$Adjusted[i] / hapv$Adjusted[i-1]
    )
    
  # calculando os valores da selic
  retornos_selic[i] <- 252 * log( 1 + (selic_data$value[i]/100) )
}

# retirando a primeira linha da base de dados
# pois ela foi perdida no calculo dos retornos
gol  <- gol[2:121,]
hapv <- hapv[2:121,]


# adicionando esses retornos nas bases de dados
gol$retornos_anualizados  <- retornos_gol[2:121]
hapv$retornos_anualizados <- retornos_hapvida[2:121]
retornos_selic            <- retornos_selic[-1]

# apresentando uma parte dos retornos para visualizacao
knitr::kable(
  data.frame(
    HAPVIDA_retornos = retornos_hapvida[2:6],
    GOL_retornos     = retornos_gol[2:6],
    SELIC_retornos   = retornos_selic[2:6]
  )
)
HAPVIDA_retornos GOL_retornos SELIC_retornos
-1.8129557 14.618219 0.1279533
6.2890906 -3.668184 0.1279533
7.8620028 5.120636 0.1279533
-0.8615385 2.163101 0.1279533
-3.4759137 3.210240 0.1279533

Apresentando estatísticas descritivas

Agora iremos apresentar algumas estatísticas descritivas básicas para cada um dos conjuntos de retornos calculados anteriormente.

Calculando uma tabela com as descritivas:

# Estatísticas descritivas dos retornos
estatisticas_gol <- summary( gol$retornos_anualizados)
estatisticas_hpv <- summary(hapv$retornos_anualizados)


# Criando a tabela das estatísticas descritivas
tabela_estatisticas <- data.frame(
  Empresa       = c("Gol Linhas Aéreas S.A. (GOLL4.SA)", "Hapvida Investimentos S.A. (HAPV3.SA)"),
  `Média`          = c(estatisticas_hpv[[4]], estatisticas_gol[[4]]),
  `Mediana`        = c(estatisticas_hpv[[3]], estatisticas_gol[[3]]),
  `Mínimo`         = c(estatisticas_hpv[[1]], estatisticas_gol[[1]]),
  `Máximo`         = c(estatisticas_hpv[[5]], estatisticas_gol[[5]]),
  `Desvio Padrão`= c(sd(retornos_gol[-1]), sd(retornos_hapvida[-1])),
  `Variância`      = c( ( sd(retornos_gol[-1]) )^2 , ( sd(retornos_hapvida[-1]) )^2 )
)

# Imprimindo a tabela formatada
knitr::kable( tabela_estatisticas )
Empresa Média Mediana Mínimo Máximo Desvio.Padrão Variância
Gol Linhas Aéreas S.A. (GOLL4.SA) 0.6871471 0.2644217 -14.99519 4.796536 13.399368 179.54307
Hapvida Investimentos S.A. (HAPV3.SA) 0.1157403 0.4254359 -33.64991 4.982864 7.727512 59.71444

2.1 Curtose e Assimetria

A curtose e a assimetria são duas medidas estatísticas que que descrevem características importantes da distribuição de dados em um conjunto de observações.

Calculando a curtose

A curtose é uma medida estatística que descreve a forma da distribuição dos dados em relação à distribuição normal, também conhecida como distribuição de Gauss. Ela avalia se a distribuição tem caldas mais “pesadas” ou “leves”.

A fórmula da curtose é dada por:

\[\text{Curtose} = \frac{\sum_{i=1}^{n} (x_i - \bar{x})^4}{n \cdot s^4} - 3\] onde: - \(n\) é o número de observações;

  • \(x_i\) é cada observação individual;

  • \(xˉ\) é a média das observações;

  • \(s\) é o desvio padrão das observações.

Portanto, teremos:
# FUNCAO QUE CALCULA A CURTOSE
calculo_curtose <- function(retornos){
  
  # Calcular a média
  media <- mean(retornos)
  
  # Calcular os desvios da média
  desvios <- retornos - media
  
  # Calcular a quarta potência dos desvios
  quarta_potencia_desvios <- desvios^4
  
  # Calcular a variância
  variancia <- var(retornos)
  
  # Calcular a curtose
  curtose <- sum(quarta_potencia_desvios) / (length(retornos) * variancia^2) - 3
}

# APLICANDO A FUNCAO NOS RETORNOS
curtose_gol     <- calculo_curtose(gol$retornos_anualizados)
curtose_hapvida <- calculo_curtose(hapv$retornos_anualizados)

A partir dos dados, conseguimos observar que ambas as ações apresentam curtoses positivas, o que significa que ambas têm alta probabilidade de presenciarem eventos extremos, seja de perda ou ganho. A Gol, em maior grau de 0.98 e a Hapvida de menor grau com 0.42.

Aplicando o calculo da Assimetria (Skewness)

A assimetria mede o grau de simetria da distribuição. Uma distribuição simétrica tem assimetria zero, logo, quanto mais distante de zero, mais assimétrica esta distribuição em questão.

Além disso, o sinal deste indicador também entrega informações. Uma distribuição com uma cauda longa à direita (valores maiores) terá assimetria positiva, enquanto uma distribuição com uma cauda longa à esquerda (valores menores) terá assimetria negativa.

A partir da utilização da formula: \[ g_1=\frac{n}{(n-1)(n-2)}\sum_{i=1}^{n} \left( \frac{x_i-\bar{x}}{s} \right)^3 \] onde: - \(n\) é o número de observações;

  • \(x_i\) é cada valor individual;

  • \(\bar{x}\) é a média dos valores;

  • \(s\) é o desvio padrão.

aplicando em R, teremos:
# FUNCAO QUE CALCULA A ASSIMETRIA 
assimetria <- function(dados){
  
  # Calcule a média dos dados
  media <- mean(dados)
  
  # Calcule o desvio padrão dos dados
  desvio_padrao <- sd(dados)
  
  # Calcule a assimetria manualmente
  assimetria <- sum((dados - media)^3) / length(dados) / desvio_padrao^3
  
  return(assimetria)
}

# Aplicando a funcao para os retornos
assim_gol <- assimetria(gol$retornos_anualizados)
assim_hpv <- assimetria(hapv$retornos_anualizados)

Desta forma, obetemos um valor de Assimetria para os retornos da Gol de: -0.0611028 e um da hapvida de 0.4531635.

3 GRÁFICOS DA TRAJETÓRIA DOS ATIVOS


Para melhor visualização dos dados, foram feitos alguns gráficos para mostrar o comportamento das ações:

# Gráfico no tempo dos preços de fechamento
historico_precos <- ggplot() +
  geom_line(data = gol, aes(x = data, y =Close), color = "blue", linetype = "solid") +
  geom_line(data = hapv, aes(x = data, y =Close), color = "red", linetype = "solid") +
  labs(title = "Gráfico no Tempo dos Preços de Fechamento", x = "Data", y = "Pre") +
  scale_x_date(date_labels = "%Y-%m", date_breaks = "1 month") +
  scale_y_continuous() +
  theme_classic()

historico_rentabilidade <- ggplot() +
  geom_line(data = gol, aes(x = data, y =retornos_anualizados), color = "blue", linetype = "solid") +
  geom_line(data = hapv, aes(x = data, y =retornos_anualizados), color = "red", linetype = "solid") +
  labs(title = "Gráfico no Tempo dos retornos", x = "Data", y = "Retornos Anualizados") +
  scale_x_date(date_labels = "%Y-%m", date_breaks = "1 month") +
  scale_y_continuous() +
  theme_classic()

# Gráfico estimando a distribuição dos retornos
dist_retornos <- ggplot() +
  geom_density(data = gol, aes(x = retornos_anualizados, fill = "GOL Linhas Aéreas"), alpha = 0.5) +
  geom_density(data = hapv, aes(x = retornos_anualizados, fill = "Hapvida"), alpha = 0.5) +
  labs(title = "Estimativa da Distribuição dos Retornos", x = "Retornos Diários", y = "Densidade") +
  # xlim(-120, 120) +
  geom_vline(aes(xintercept = 0), color = "black", linetype = "dashed",size = 1)  +
  theme_classic()

# Combinação dos gráficos lado a lado
gridExtra::grid.arrange(historico_precos, historico_rentabilidade ,dist_retornos, ncol = 1)

Observação: Click no Gráfico para visualiza-lo

Os Gráficos apresentados neste Documento Web são todos clicaveis

É possível perceber que, pelo gráfico 1, a Gol possui um preço de fechamento maior quando comparada a habvida, o que faz sentido acreditar, já que por ser uma emrpesa de companhia aérea e ter maior valorilidade, isso passa a se refletir no seu preço. O gráfico 2 evidencia que ambas as ações, na média, tendem a ter o mesmo comportamento, claro que em maior ou menor grau em alguns momentos. Já o último gráfico, mostra a distribuição dos retornos diários das ações, sem diferenças extremas entre as duas.

4 CARTEIRA DE RISCO

Esta seção abordará a apresentação da carteira de risco e as diversas combinações de peso associadas a ela. Primeiramente, será delineada a fronteira de possibilidades. Em seguida, será discutida a minimização da variância da carteira, refletindo a aversão ao risco do investidor e sua busca por minimizar perdas. Por fim, será explorada a maximização da utilidade, refletindo o desejo do investidor de alcançar o maior retorno possível.


4.1 Fronteira eficiente

Para uma carteira com duas ações,temos: \[ r_p = w_g r_g + w_h r_h \]

onde:

  • \(w_g\) eh a proporcao das acoes da gol na carteira \(p\);

  • \(w_h\) sendo a proporcao das acoes da hapvida na carteira \(p\);

  • \(r_g\) é o retorno da gol.

  • \(r_h\) é o retorno da hapvida.

Encontrando os Retornos Esperados

Existem inúmeras formas de encontrar os Retornos Esperados. Como há uma incerteza em relação ao cenário futuro, a melhor forma seria encontrarmos uma estimativa boa o suficiente e não viesada dessa esperança em questão. Mas para isso precisariamos de modelos que tornariam este trabalho muito extenso.

Por conta disso, iremos avaliar o \(E[r]\) como sendo a média simples dos retornos anualizados já calculados.

# estabelecendo variaveis para serem utilizadas nos calculos
retorno_g = mean(gol$retornos_anualizados )
retorno_h = mean(hapv$retornos_anualizados)

Encontrando os desvios

•Uma medida de risco usual é o desvio-padrão, que mede a dispersão dos possíveis retornos em relação ao retorno esperado.

desvio_padrao_g = tabela_estatisticas$Desvio.Padrão[1]
desvio_padrao_h = tabela_estatisticas$Desvio.Padrão[2]

Encontrando a Covariância e a Correlação

  1. Covariância: A covariância entre dois vetores pode ser calculada usando a seguinte fórmula: \[Cov(r_g , r_h ) = \frac{1}{n} \sum_{i=1}^n (r_g - \bar{r_g}) (r_h - \bar{r_h}) \]

  2. Correlação: Já a correlação, esta é calculada a partir da equação: \[ Corr(r_g,r_h) = \frac{cov(r_g,r_h)}{\sigma_{r_g} \cdot \sigma_{r_h}} \]

Aplicando a função no R:

# Covariância
covariancia <- cov(gol$retornos_anualizados, hapv$retornos_anualizados)

# Correlação
correlacao <- cor(gol$retornos_anualizados, hapv$retornos_anualizados)

Função da Variância e do Desvio Padrão de \(r_p\)

temos a função da variância como: \[\sigma^2_p = Var[r_p] = Var[w_hr_h+w_gr_g] = w_h^2\sigma_h^2+w_g^2\sigma_g^2 + 2w_hw_gCov(r_h,r_g) \] onde: \(\sigma_g^2 = Var[r_g]\); \(\sigma_h^2 = Var[r_h]\).

Percebemos neste caso que a variância da carteira diminui se o termo da covariância for negativo.

Agora, achando o Desvio Padrão utilizando a formula acima \[\sigma_p = (Var[r_p])^{1/2} = \sqrt{ \ w_h^2r_h^2+w_g^2r_g^2 + 2w_hw_gCov(r_h,r_g)} \]

Aplicando as combinações de pesos

Para isso, iremos criar uma tabela com os possíveis valores de de pesos das duas ações e testar suas combinações a fim de gerar um vetor com os possíveis valores de retorno esperado e desvio padrão. Com eles, iremos estabelecer o gráfico com os retornos e desvios.

Tabela com os Pesos

# produzindo tabela para calcular a fronteira de retornos
tabela_pesos <- data.frame(
  w_g = seq(0,1, 0.001),
  w_h = seq(1,0,-0.001)
)

Para cada um dos valores de \(w_g\) e \(w_h\), faremos o calculo do retorno da carteira a fim de produzir um grafico da fronteira de retornos.

Calculando os valores de Retorno esperado e Desvio Padrão para as ações

Agora, iremos fazer um loop para poder calcular os valores de desvio-padrão e Retorno esperado da carteira para todos os possíveis pares de pesos \([w_g,\ w_h]\) sabendo que, \(w_g + w_h = 1\). E, a partir desses resultados, podemos encontrar o gráfico de retornos possíveis para cada desvio-padrão e construir a fronteira eficiente.:

Realizando o loop para todos os pessos possíveis:

# variaveis de armazenamento dos valores
retorno_carteira <- c()
desvio_carteira <- c()

# renomeando para melhor visualizacao
sd_g <- desvio_padrao_g
sd_h <- desvio_padrao_h

# aplicacao do loop
for ( i in 1:nrow(tabela_pesos) ) {
  Wg <- tabela_pesos$w_g[i] # iterando os pesos
  Wh <- tabela_pesos$w_h[i] # iterando os pesos
  
  # utilizando a formula de retorno de p
  retorno_carteira[i] <-(Wg * retorno_g) + (Wh * retorno_h)
  
  # utilizando a formula do desvio da carteira
  desvio_carteira[i] <- (
    ( (Wg^2 * sd_g^2) + (Wh^2 * sd_h^2) + (2*Wg*Wh*covariancia) )^(0.5)
  )
}

# Criando um data.frame com os dados
tabela_retornos <- data.frame(
  retorno  = retorno_carteira,
  desvio   = desvio_carteira,
  peso_gol = tabela_pesos$w_g,
  peso_hpv = tabela_pesos$w_h
  )

# plotando a tabela no HTML
knitr::kable( head(tabela_retornos) )
retorno desvio peso_gol peso_hpv
0.6871471 7.727512 0.000 1.000
0.6865757 7.723137 0.001 0.999
0.6860043 7.718785 0.002 0.998
0.6854329 7.714454 0.003 0.997
0.6848615 7.710146 0.004 0.996
0.6842900 7.705859 0.005 0.995

Agora, plotando o gráfico da fronteira eficiente, temos:

ggplot(tabela_retornos, aes(x = desvio, y = retorno)) +
  geom_point(color = "darkblue", size = 1.5) +
  labs(
    x = "Desvio Padrão (σ)",
    y = "Retorno Esperado (E[r])",
    title = "Relação entre Desvio Padrão e Retorno Esperado",
    subtitle = "Análise de Portfólio",
    caption = "Fonte: Yahoo.finance"
  ) +
  theme_classic() +
  annotate(
    "segment",
    x = min(tabela_retornos$desvio)+0.1,
    xend = min(tabela_retornos$desvio) + 1.2 ,
    y = tabela_retornos[tabela_retornos$desvio == min(tabela_retornos$desvio),"retorno"],
    yend= tabela_retornos[tabela_retornos$desvio == min(tabela_retornos$desvio),"retorno"],
    arrow = arrow(length = unit(0.3, "cm"),ends = 'first', type = 'open'),
    color = "black"
    ) +
    annotate(
      "text",
      x = min(tabela_retornos$desvio) +1.3,
      y = tabela_retornos[tabela_retornos$desvio == min(tabela_retornos$desvio),"retorno"]-0.01,
      label = paste("Ponto de risco mínimo e com retorno = ",round(tabela_retornos[tabela_retornos$desvio == min(tabela_retornos$desvio),"retorno"],3)),
      hjust = 0,
      vjust = 0,
      color = "black"
      ) +
  theme(
    plot.title = element_text(face = "bold", size = 14),
    plot.subtitle = element_text(face = "italic", size = 12),
    plot.caption = element_text(size = 8),
    axis.title.x = element_text(face = "bold", size = 12),
    axis.title.y = element_text(face = "bold", size = 12),
    axis.text.x = element_text(angle = 45, hjust = 1),
    legend.position = "none"
  ) +
  scale_x_continuous(labels = scales::comma)

Observação: Click no Gráfico para visualiza-lo

Como podemos ver no gráfico, temos a o valor com o menor desvio padrão como aquele ponto da curva que é tangenciado por uma linha vertical.

4.2 Carteira de mínima variância

Para a carteira de mínima variância temos aquela de mínimo desvio-padrão:

Temos algumas formas diferentes para poder encontrar a carteira de mínima variância.

Como foi visto no exercício anterior, calculamos todas os desvios possíveis para as carteiras. Dessa forma, encontramos o valor de menor risco e podemos usar o par de pesos gerou o menor desvio.

Contudo, podemos também resolver esse execício através de uma ótica matemática, interpretanto as formulas como um problema de minimização da equação do desvio dado a restrição de \(w_g + w_h = 1\).

fariamos isso dessa forma:

  1. Caso Geral: \[\sigma^2_p = w_h^2\sigma_h^2+w_g^2\sigma_g^2 + 2w_hw_gCov(r_h,r_g) \] Dado a restrição de que $w_g = 1 -w_h $, podemos substituir para encontrar:

\[\sigma^2_p = w_h^2\sigma_h^2+(1 -w_h)^2\sigma_g^2 + 2w_h(1 -w_h)Cov(r_h,r_g)\]

Portando, minimizaremos a Função escolhendo o valor de \(w_h\), aplicando a CPO: \[\frac{\partial(\sigma^2_p)}{\partial w_h} = 2w_h\sigma_h^2 - 2(1 - w_h)\sigma_g^2 + 2(1 - 2w_h)Cov(r_h,r_g)\]

Portanto, ao acharmos o valor que torne a CPO = zero, teremos seu valor mínimo.

Igualando a derivada a zero e encontrando o valor de \(w_h\) que minimiza a variância

\[2w_h\sigma_h^2 - 2\sigma_g^2 + 2w_h\sigma_g^2 + 2Cov(r_h,r_g) - 4w_hCov(r_h,r_g) = 0\]

\[w_h^* = \frac{\sigma_g^2 - Cov(r_h,r_g)}{\sigma_h^2 + \sigma_g^2 - 2Cov(r_h,r_g)}\]

Agora, podemos aplicar a função utilizando os valores calculados anteriormente para encontrar a carteira que minimiza a variância sem ter que testar todos os pesos possíveis.

Aplicando:

# aplicacao da formula para o peso que min. o risco
w_h_menor_var <- 
  (desvio_padrao_g^2 - covariancia) / 
  (desvio_padrao_g^2 + desvio_padrao_h^2 - (2*covariancia) )

# encontrando o outro peso da acao
w_g_menor_var <- 1 - w_h_menor_var

Valores de estatísticas para o valor de mínima variância

knitr::kable(resultados)
Estatística Valor
Esperança 0.5837225
Variância 53.5934684
Desvio Padrão 7.3207560
wg 0.1806309
wh 0.8193691

4.3 Cateira com maximização da utilidade

Pesos que maximizam a utilidade do investidor

A utilidade é dada por: \[U = E[r_p] - \frac{1}{2}A\sigma^2_p\]

Da mesma forma que achamos a carteira de mínima variância calculando os resultados para todos os pesos possíveis, podemos forçar a maximização da utilidade dessa mesma forma:

# definindo a aversao ao risco
A <- 2.5
# vetor vazio de armazenamento das utilidades
utilidades <- c()

# Calculando a utilidade para todos os possiveis pesos
for (i in 1:nrow(tabela_pesos)) {

# definindo as variaveis pelo iterador em questao
w_g <- tabela_pesos$w_g[i]
w_h <- tabela_pesos$w_h[i]
desvio <- tabela_retornos$desvio[i]
retorno_esperado <- tabela_retornos$retorno[i]

# aplicando o calculo da utilidade para cada par de pesos
utilidades[i] <- (retorno_esperado - (0.5 * A * desvio^2) )
}

# acrescentando os valores da utilidade para cada peso
tabela_retornos$utilidades <- utilidades

Como as utilidades são calculadas por meio da subtração do retorno esperado menos um produto do desvio padrão, temos boa parte das utilidades negativas. Ainda assim, como a parte importante das funções utilidades é o seu carácter ordinal e não seu valor em si, só a utilizaremos para ver qual par de pesos que a tornou máxima.

Calculando a Utilidade

Temos:

\[U = \color{green}{E[r_p]} - 0.5 A \color{red}{ \sigma_p^2} \] \[\color{green}{E[r_p]} = w_gE[r_g] + w_hE[r_h]\]

\[\color{red}{\sigma^2_p} = w_h^2\sigma_h^2+w_g^2\sigma_g^2 + 2w_hw_gCov(r_h,r_g) \]

Portanto, a utilidade pode ser escrita como: \[U = \color{green}{w_gE[r_g]+w_hE[r_h]} - 0.5A \color{red}{[w_g^2\sigma_g^2+w_h^2\sigma_h^2+2w_gw_hCov(r_g,r_h)]}\]

Dessa forma, quando maximizamos ela, teremos:

\[w_g^* = \frac{E[r_g] - E[r_h] + A[\sigma^2_h - 2Cov(r_D, r_E)]}{A[\sigma^2_g + \sigma^2_h - 2Cov(r_g, r_h)]}\] \[w_h^* = 1 - w_g^* = \frac{E[r_g] - E[r_h] + A[\sigma^2_g 2Cov(r_g, r_h)] }{A[\sigma^2_g + \sigma^2_h - 2Cov(r_g, r_h)]}\]

Aplicando:

w_g_max_uti <- 
  ( retorno_g - retorno_h + (A * (desvio_padrao_h^2 - covariancia)) ) / 
  ( A * (desvio_padrao_g^2 + desvio_padrao_h^2 - (2*covariancia) ) )

# encontrando o peso da ação hapvida
w_h_max_uti <- 1 - w_g_max_uti

Valores de estatística para maximziação da utilidade

Criando um data frame com os resultados

knitr::kable(resultados)
Estatística Valor
Esperança (E[r]) 0.5848653
Variância (σ^2) 53.5939418
Desvio Padrão (σ) 7.3207883
peso gol(wg) 0.1794126
peso hapvida(wh) 0.8205874

5 CARTEIRA COMPLETA

Esta seção destina-se a apresentar a carteira completa do indivíduo, incluindo o ativo livre de risco. Em seguida, serão delineados os pesos ótimos que maximizam o índice de Sharpe.


5.1 Risk Free na maximização da carteira completa

Para otimizar a utilidade do consumidor, considerando o ativo livre de risco, empregamos o índice de Sharpe para determinar os pesos ideais dos ativos. O índice de Sharpe representa a relação entre retorno e risco, destacando a busca por um equilíbrio favorável. Encontrar a carteira com o máximo índice de Sharpe implica maximizar a compensação do retorno em relação ao risco assumido. Essa abordagem visa aprimorar a eficiência da alocação de recursos, priorizando investimentos que oferecem maior retorno ajustado ao risco.

dado que a \(r_f\) é a taxa do risk free, o Índice de Sharpe é dado por:

\[S = \frac{E[r_c] - r_f}{\sigma_c}\]

Aplicando o calculo do Sharpe para todos os pesos:

# Risk free
risk_free <- mean(retornos_selic)

# vetor vazio de armazenamento dos Sharpes calculados
sharpe <- c()

# Calculando a utilidade para todos os possiveis pesos
for (i in 1:nrow(tabela_pesos)) {

  # definindo as variaveis pelo iterador em questao
  w_g <- tabela_pesos$w_g[i]
  w_h <- tabela_pesos$w_h[i]
  desvio <- tabela_retornos$desvio[i]
  retorno_esperado <- tabela_retornos$retorno[i]


  # aplicando o calculo do sharpe para cada par de pesos
  sharpe[i] <- (retorno_esperado - risk_free) / (desvio)
}

# acrescentando os valores de sharpe para cada peso
tabela_retornos$sharpe <- sharpe

# pontos que maximizam o sharpe tirando aqueles abaixo da linha de min(Variancia)
tabela_acima_min_risco <- tabela_retornos[
  tabela_retornos$retorno > tabela_retornos[
    tabela_retornos$desvio == min(tabela_retornos$desvio),"retorno"
    ],
  ]

  # encontrando pontos de maximo sharpe
  w_g_max_sharpe <- tabela_acima_min_risco[
    tabela_acima_min_risco$sharpe == max(tabela_acima_min_risco$sharpe),"peso_gol"
  ]

w_h_max_sharpe <- 1 - w_g_max_sharpe

Os pesos que maximizam o sharpe são,respectivamente: \[Max(Sharpe) \rightarrow w_g = 0; w_h = 1 \]

Agora, vamos plotar uma figura com a reta LAC, na qual sua inclinação é dada pelo índice de Sharpe, que tangencia a curva da fronteira eficiente

# adicionando os pontos de sharpe maximo
x_ponto_desvio  <- tabela_retornos[tabela_retornos$peso_gol == w_g_max_sharpe,"desvio"]
y_ponto_retorno <- tabela_retornos[tabela_retornos$peso_gol == w_g_max_sharpe,"retorno"]

ggplot(tabela_retornos, aes(x = desvio, y = retorno)) +
  geom_point(color = "black", size = 1) +
  geom_point(data = data.frame(x = x_ponto_desvio, y = y_ponto_retorno), aes(x = x, y = y), color = "darkred", size = 3) + # Adicionando o ponto
  geom_segment(x = 0, y = 0, xend = 2*x_ponto_desvio, yend = 2*y_ponto_retorno, color = "red", linetype = "solid") + # Desenhando a linha da origem ao ponto vermelho
  labs(
    x = "Desvio Padrão (σ)",
    y = "Retorno Esperado (E[r])",
    title = "Relação entre Desvio Padrão e Retorno Esperado",
    subtitle = "Análise de Portfólio",
    caption = "Fonte: Yahoo.finance"
  ) +
  theme_classic() +
  theme(
    plot.title = element_text(face = "bold", size = 14),
    plot.subtitle = element_text(face = "italic", size = 12),
    plot.caption = element_text(size = 8),
    axis.title.x = element_text(face = "bold", size = 12),
    axis.title.y = element_text(face = "bold", size = 12),
    axis.text.x = element_text(angle = 25, hjust = 1),
    legend.position = "none"
    ) +
    scale_x_continuous(
      expand = c(0, 0),
      limits = c(0, 2+ max(tabela_retornos$desvio)),
      breaks = seq(0, 2+ max(tabela_retornos$desvio), by = 1)
      ) +
  scale_y_continuous(
    expand = c(0, 0),
    limits = c(0, 0.2 + max(tabela_retornos$retorno)),
    breaks = seq(0, 0.2 + max(tabela_retornos$retorno),by = 0.1)
    )

Apresentando os valores importantes do ponto de máximo

\[ \begin{align} \begin{cases} E[r_p] & = 0.6871471 \\ \sigma_p^2 & = 59.7144353 \\ \sigma_p & = 7.7275116 \\ S_p & = 0.0732786 \end{cases} \end{align} \]

Pesos ótimos da carteira completa C

Quando queremos maximizar o Sharpe por meio das equações escolhendo um dos pesos, teremos:

\[\max_{w_e,w_D} S_p\] \[ \begin{align} \text{s.a.} \quad & \begin{cases} w_g + w_h = 1 \\ E[r_p] = w_gE[r_g] + w_hE[r_h] \\ \sigma_p = (\sigma^2_p)^{1/2} \\ \sigma_P^2 = w_g^2\sigma_g^2 + w_h^2\sigma_h^2+ 2w_gw_h \cdot Cov(r_g,r_h) \end{cases} \end{align} \]

Se substituirmos tudo, teremos um problema de maximização dado por: \[ \max_{w_g} \frac{(1-w_g)E[r_h]+w_gE[r_g] - r_f} {\sqrt{ [w_g^2\sigma_g^2 + (1-w_g)^2\sigma_h^2+ 2w_g(1-w_g) \cdot Cov(r_g,r_h)]}} \]

Aplicando a maximização, teremos os pesos ótimos dados pela equação: \[ w_G^* =\frac{E[R_G]\sigma_H^2 - E[R_H] Cov(R_G,R_H)} {E[R_G]\sigma_H^2 - E[R_H]\sigma_G^2 - (E[R_G] - E[R_H]) \cdot Cov(R_G,R_H)} \]

onde consideramos os retornos excedentes: \[E[R_G] = E[r_g-r_f]\] \[E[R_H] = E[r_h-r_f]\] ### 3.2.1 Aplicando a formula para os pontos:

# definindo variaveis
R_G <- retorno_g - risk_free
R_H <- retorno_h - risk_free

w_g_maximo_sharpe <- 
    ( (R_G * desvio_padrao_h^2) - (R_G * covariancia) ) / # dividido por...
  (
    (R_G*desvio_padrao_h^2) - (R_H*desvio_padrao_g^2) - 
    ( (R_G - R_H) * (covariancia) )
  )

w_h_maximo_sharpe <- 1 - w_g_maximo_sharpe

Os pesos que maximizam o sharpe por meio das equações são, respectivamente: \[Max(Utilidade) \rightarrow w_g = 0.0019991; w_h = 0.9980009 \]

Peso em ações e risk free

Agora, tendo a carteira ótima de títulos de risco P, usaremos o grau de aversão ao risco A, para calcular a proporção ótima da carteira completa a ser investida no componente de risco

Calculando o peso em acoes

\[ y =\frac{E[r_p] - r_f}{A\sigma_p^2} \]

Aplicando em R, teremos

pesoacoes <- (retorno_sharpe - risk_free)/(A*desvio_sharpe^2)
pesoselic <- 1 - pesoacoes

peso_g <- w_g_maximo_sharpe*pesoacoes
peso_h <- w_h_maximo_sharpe*pesoacoes

Apresentando os resultados:

\[Max(Utilidade Risk Free)\] \[w_g = 7.5830316\times 10^{-6};\] \[w_h = 0.0037855\] \[y = 0.9962069 \] ### calculando as variaveis de saída:

retorno_c   <- (pesoselic * risk_free) + (pesoacoes*retorno_sharpe)

desvio_c    <- ((pesoacoes^2 * desvio_sharpe^2) )^(0.5)
variancia_c <- ((pesoacoes^2 * desvio_sharpe^2) )

sharpe_c    <- ( (retorno_sharpe - risk_free) / (desvio_sharpe) )   

\[ \begin{align} \begin{cases} E[r_c] & = 0.1230336 \\ \sigma_c^2 & = 8.5916085\times 10^{-4} \\ \sigma_c & = 0.0293114 \\ S_c & = 0.0732786 \end{cases} \end{align} \]