Seleção de Carteiras e Teoria de Markowitz

By | mercado financeiro

A gestão de portfólio tem como seu máximo expoente Harry Markowitz, pioneiro da seleção da carteira e da teoria que leva o seu próprio nome: Teoria de Markowitz. A teoria teve um impacto enorme no mundo das finanças, cumprindo o objetivo de minimizar o risco de uma carteira de investimento e rendendo ao autor até mesmo um prêmio Nobel. No post de hoje, iremos dar uma olhada na teoria da seleção de carteira e na teoria de Markowitz.

A gestão de portfolio tem como principal objetivo lidar com a gestão de risco de um número de ativos financeiros em um conjunto em que todos os ativos estão contidos na mesma carteira de investimentos. Mas afinal, qual o beneficio da escolha de vários ativos financeiros em uma carteira? A questão é que, por suposição, quanto maior o número de ativos em uma carteira, menos risco o investidor incorrerá, mas como isso é possível?

Dado o contexto de que o Retorno de um ativo é dado por:

    \[R_t = ln(\frac{P_t}{P_t-1})\]

Ou seja, o log-retorno R_t é dado pelo logaritmo natural do preço de hoje divido pelo preço de ontem.

O retorno de um ativo é a estrutura do estudo, pois é basicamente dele que é encontrado duas importantes medidas de estimação para que possamos realizar o cálculo do risco do nosso conjunto de ativos e encontrar os pesos ideais de um portfólio, essas duas medidas são a média e a variância (mean-variance).

A média dos retornos, a grosso modo, seria o Retorno Esperado no nosso investimento, baseado na média amostral dos retornos históricos do nossos ativos.

    \[E(R) = \frac{\sum_{t = 1}^{T}(R_it)}{T}\]

Por outro lado, a variância, ou o que em finanças é chamado de volatidade ou risco, também mensurado pelo desvio padrão, que é dado por:

    \[\sigma^2 = \frac{(E[(R_i - \mu)^2])}{T-1}\]

Dito isso, sabemos que estamos lidando com ativos individuais, porém, como o contexto é dado pelo retorno de um conjunto de ativos, devemos calcular os estimadores corretos, buscando encontrar o retorno e a variância do portfólio.

O Retorno de um portfólio é calculado como:

    \[R_p = \sum_{i=1}^n(W_iR_i)\]

Ou seja, o retorno do ativo i ponderado pelo seu peso w_i.

Para o seu retorno esperado, calcula-se como a média amostral de seus retornos passados, assim como o retorno esperado de um único ativo

Por outro lado, a variância de um portfólio não é igual ao calculo da variância de um ativo individual. Quando estamos falando em risco de um ativo, sabe-se que eles podem incorrer dos mesmo riscos. Seja dois ativos que possuem risco cambial ou risco de mercado, tem-se que levar em conta essas duas questões ao realizar o calculo do risco de um portfólio.

Portanto, para computar esses tipos de riscos, podemos fazer isso através de duas importantes medidas estatística: covariância e correlação

A covariância permite que seja calculado a dependência linear entre as variáveis. O mesmo serve para a correlação, que diferente da covariância, é uma medida em forma percentual. Quando medimos a covariância (ou correlação) de dois ou mais ativos, estamos considerando o quanto os ativos se movimentam em relação ao outro, se positivamente ou negativamente.

Calculamos a covariância como:

    \[\sigma_{jk}=\frac{\sum_{t=1}^T[R_{jt}-\bar{R}_j][R_{kt}-\bar{R}_k]}{T-1}\]

Quando ocorre de os ativos terem covariância negativa, a variância ou risco do portfólio tende a diminuir. Quando a covariância é positiva, o risco do portfólio tende a aumentar. Essa questão é um principio básico da diversificação. Quanto menor a covariância dos ativos em uma carteira, menor o risco, quanto maior a covariância, maior o risco.

Sendo assim, calcula-se o risco (variância) de um portfólio como:

    \[\sigma_P=\sqrt{\sum_{j=1}^N(w_j^2 \sigma_j^2)+\sum_{j=1}^N\sum_{\substack {k=1 \\ k \neq j}}^N(w_j w_k \sigma_{jk})}\]

Mas todo o papel da covariância e variância dos ativos individuais em uma carteira, dependerá de seus pesos. Isto leva a crer que pode existir um combinação grande de pesos para uma só carteira, e o investidor se vê tentado a tentar uma combinação que melhor satisfaça suas preferências. Em muitos casos, a preferência que melhor pode atender a todos será a combinação de pesos de ativos que melhor minimize o risco do portfólio.

Para isso, Markowitz criou um método para que seja possível descobrir o pesos tal qual a relação de risco x retorno melhor se satisfaz dentro de um contexto que o retorno esperado é dado pela média amostral dos retornos e o risco é dado pela variância e covariância dos ativos.

O ponto em que é conhecido como aquele em que é minimizado o risco dados os estimadores, é conhecido como portfólio de variância mínima. Esse ponto é resolvido a partir de um problema de otimização, que possui algumas restrições; 1) a soma das proporções alocadas em cada ativo tem que ser igual a um; 2) cada ativo tem que ter peso maior ou igual a zero; 3) em cada problema escolhemos um retorno esperado para o qual minimizaremos o risco.

A otimização é dado por:

    \[min_{w_i} \sum_{j=1}^N(w_j^2 \sigma_j^2)+\sum_{j=1}^N\sum_{\substack{k=1 \\ k \neq j}}^N(w_j w_k \sigma_{jk})\]

s.a.

\sum_{j=1}^N w_j = 1

w_j \geq 0, \forall i

\sum_{j=1}^N w_i\bar{R}_j = \bar{R}_p

Como dito, a solução deste problema nos dá os pesos ótimos para investir em cada um dos ativos.

A partir da teoria, podemos calcular o ponto mínimo de um portfólio dentro do R. Para isso, utilizamos o pacote {PortfolioAnalytics}, que permite configurar um portfólio e calcular a partir de restrições escolhidas.

Primeiro, devemos coletar os dados dos ativos.

library(quantmod)
library(PerformanceAnalytics)
library(PortfolioAnalytics)
library(tidyverse)

Como obrigatório, devemos ter em mãos os retorno dos nossos ativos.

# Define os ativos que irão ser coletados

tickers <- c("PETR4.SA", "ITUB4.SA", "ABEV3.SA", "JBSS3.SA")

# Define a data de início da coleta

start <- as.Date("2016-12-01")

# Realiza a coleta dos preços diários

prices <- getSymbols(tickers,
auto.assign = TRUE,
warnings = FALSE,
from = start,
src = "yahoo") %>%
map(~Cl(get(.))) %>%
reduce(merge) %>%
`colnames<-`(tickers)

# Transfroma os preços diários em mensais

prices_monthly <- to.monthly(prices,
indexAt = "lastof",
OHLC = FALSE)

# Calcula os retornos mensais

asset_returns <- Return.calculate(prices_monthly,
method = "log") %>%
na.omit()

Com os retornos em mãos, configuramos as restrições e os objetivos do nosso portfólio.


# Define os nomes dos ativos na especificação

portfolio_spec <- portfolio.spec(assets = tickers)

# Considera que a soma dos pesos será igual a 1

portfolio_spec <- add.constraint(portfolio = portfolio_spec,
type = "full_investment")

# Não permite vendas a descoberto

portfolio_spec <- add.constraint(portfolio = portfolio_spec,
type = "long_only")

# Adiciona os objetivos - Retorno esperado através da média amostral

portfolio_spec <- add.objective(portfolio = portfolio_spec,
type = "return",
name = "mean")

# Adiciona os objetivos - Risco esperado através do desvio padrão

portfolio_spec <- add.objective(portfolio = portfolio_spec,
type = "risk",
name = "StdDev")

Por fim calculamos o portfolio através da otimização pelo método "random" no qual o solver irá ser uma combinação de diferentes pesos do portfólio.


# Calcula a otimização do portfólio

opt <- optimize.portfolio(asset_returns,
portfolio = portfolio_spec,
optimize_method = "random",
trace = TRUE)

# Plota o gráfico de Risco x Retorno

chart.RiskReward(opt,
risk.col = "StdDev",
return.col = "mean",
chart.assets = TRUE,
main = "Risco x Retorno - Combinações dos ativos selecionados")

Vemos no gráfico os resultados de retorno e risco para as diferentes combinações de pesos dos ativos no portfólio. O ponto azul, é o ponto que minimiza os risco de acordo com a equação de Markowitz.

________________________

(*) Para entender mais sobre Mercado Financeiro, seleção de carteira e a Teoria de Markowitz, confira nosso curso de R para o Mercado Financeiro.
________________________

Relatório AM #34 - Pesquisa Mensal de Serviços (PMS)

By | Indicadores

A Pesquisa Mensal de Serviços (PMS) é um dos principais indicadores de acompanhamento do setor de serviços no Brasil. A pesquisa produzida pelo IBGE podem ter seus dados acessados pelo SIDRA. No R, é possível acessar os dados da PMS através do pacote {sidrar}. Nós ensinamos além dessa coleta, o tratamento e a visualização  no nosso Curso de Análise de Conjuntura.

Primeiro carregamos os pacotes.


library(tidyverse)
library(sidrar)
library(patchwork)

Prosseguimos para a coleta dos dados via SIDRA e também para o tratamento dos dados.


# PMS
parametros <- list(api_pms = "/t/6442/n1/all/v/all/p/all/c11046/40311,40312/d/v8676%201,v8677%201")

# Função get_sidra realiza a coleta dos dados

raw_pms <- sidrar::get_sidra(api = parametros$api_pms)

# Tratamentos dos dados e o cálculos das variações

pms <- raw_pms %>%
dplyr::filter(`Variável` == "Índice de volume de serviços") %>%
dplyr::select(
"date" = `Mês (Código)`,
"index" = `Tipos de índice`,
"value" = Valor
) %>%
tidyr::pivot_wider(
id_cols = date,
names_from = index,
values_from = value
) %>%
rename_with(~c("date", "volume", "volume_sa")) %>%
dplyr::mutate(
date = lubridate::ym(date),
margem_volume = (volume_sa / dplyr::lag(volume_sa, 1) - 1) * 100,
interanual_volume = (volume / dplyr::lag(volume, 12) - 1) * 100,
anual_volume = acum_i(volume, 12),
id = "PMS (Volume)"
) %>%
filter(date > "2015-01-01")

A partir disso, podemos visualizar nossos dados.

 

 

 

Além do gráfico de linhas, construímos também uma tabela.

________________

Você confere o script completo no nosso Curso de Análise de Conjuntura usando o R. A apresentação da PMC também está disponível no Clube AM.

Acessando microdados da PNAD Contínua no R

By | Data Science

Os microdados da Pesquisa Nacional por Amostra de Domicílios Contínua (PNADC), produzida pelo IBGE, possuem uma riqueza enorme de informação de um conjunto de indicadores relacionados à força de trabalho no país, constituindo um verdadeiro tesouro para economistas e cientistas sociais. Esse grande volume de dados exige, por consequência, o uso de ferramentas adequadas para o tratamento, análise, visualização e sua utilização em geral. Em suma, é necessário utilizar linguagens de programação para "colocar a mão" nesses dados e, neste exercício, mostraremos como fazer isso usando o R.

Para reproduzir o exercício a seguir você precisará dos seguintes pacotes:


library(PNADcIBGE) # CRAN v0.7.0
library(survey) # CRAN v4.0
library(convey) # CRAN v0.2.3
library(magrittr) # CRAN v2.0.1

1)  Importar microdados trimestrais  

Para começar o exercício, vamos importar os microdados para o environment do R usando o pacote PNADcIBGE - que foi desenvolvido pela própria equipe do IBGE. Os microdados trimestrais serão o alvo do nosso exemplo: apontamos na função get_pnadc o último período (ano/trimestre) disponível da pesquisa e, opcionalmente, as variáveis de interesse1.


# Importar online microdados do 3º trimestre de 2021
dados_pnadc <- get_pnadc(year = 2021, quarter = 3, vars = c("VD4020", "V2007"))

# Classe do objeto
class(dados_pnadc) # útil para análises de dados amostrais complexos

[1] "svyrep.design"

2)  Análise de dados

Após este simples comando de importação executado, os microdados da PNADC já estão disponíveis para fazermos uma análise. A função, inclusive, já configura o plano amostral internamente através do argumento design = TRUE - mas o usuário pode desabilitar para obter os dados brutos -, sendo assim podemos usar o pacote survey para obter, por exemplo, o total de homens e mulheres:


# Obter nº total de homens e mulheres
svytotal(x = ~V2007, design = dados_pnadc, na.rm = TRUE)

#                  total     SE
# V2007Homem   104020393 0.1207
# V2007Mulher  108787836 0.0998

Da mesma forma, e com comandos simples, o usuário pode estimar o índice de Gini a nível nacional:


# Estimar o índice de Gini
dados_pnadc %>%
convey_prep() %>%
svygini(formula = ~VD4020, na.rm = TRUE)

#           gini     SE
# VD4020 0.51625 0.0034

Diversas outras análise podem ser feitas, como esta publicada no blog da Análise Macro:

Saiba mais

Para saber mais confira os cursos aplicados de R e Python.


[1] Note que os microdados consomem espaço excepcionalmente grande na memória do computador, portanto, evite a importação sem nenhum tipo de filtro de variáveis.

 

Gerando Previsões Combinadas para a Inflação a partir dos grupos do IPCA

By | Comentário de Conjuntura

A inflação cheia medida pelo IPCA em um período t qualquer nada mais é do que a soma da contribuição da inflação em cada um dos seus nove grupos, de acordo com os pesos dos mesmos no índice. Em outros termos,

(1)   \begin{align*} \pi_t = \sum_{i=1}^{9} \pi_{t,i}^{g} p_{t,i}^{g} \end{align*}

onde \pi_t é a inflação cheia, \pi_{t,i}^{g} é a inflação em t no grupo i e p_{t,i}^{g} é o peso em t do grupo i no índice cheio. De modo a ilustrar, podemos baixar com o pacote sidrar, as variações e os pesos desses nove grupos do IPCA, conforme o código abaixo.


## Pacotes
library(sidrar)
library(ggplot2)
library(forecast)
library(timetk)
library(zoo)
library(scales)
library(tidyverse)

## Baixar e tratar os dados
tab1 = get_sidra(api='/t/2938/n1/all/v/63,66/p/all/c315/7170,7445,7486,7558,7625,7660,7712,7766,7786/d/v63%202,v66%204')
tab2 = get_sidra(api='/t/1419/n1/all/v/63,66/p/all/c315/7170,7445,7486,7558,7625,7660,7712,7766,7786/d/v63%202,v66%204')
tab3 = get_sidra(api='/t/7060/n1/all/v/63,66/p/all/c315/7170,7445,7486,7558,7625,7660,7712,7766,7786/d/v63%202,v66%204')

series = c(7170, 7445, 7486, 7558, 7625, 7660,
7712, 7766, 7786)

names = c('Alimentos', 'Habitação', 'Art de Resid',
'Vestuário', 'Transporte', 'Saúde e cuid pessoais',
'Despesas Pessoas', 'Educação', 'Comunicação')

var1 <- matrix(NA, ncol=length(series),
nrow=nrow(tab1)/length(series)/2)

peso1 <- matrix(NA, ncol=length(series),
nrow=nrow(tab1)/length(series)/2)

var2 <- matrix(NA, ncol=length(series),
nrow=nrow(tab2)/length(series)/2)

peso2 <- matrix(NA, ncol=length(series),
nrow=nrow(tab2)/length(series)/2)

var3 <- matrix(NA, ncol=length(series),
nrow=nrow(tab3)/length(series)/2)

peso3 <- matrix(NA, ncol=length(series),
nrow=nrow(tab3)/length(series)/2)

for(i in 1:length(series)){

var1[,i] <- tab1Valor[tab1`Variável (Código)`==63&
tab1`Geral, grupo, subgrupo, item e subitem (Código)`==series[i]]  var2[,i] <- tab2Valor[tab2`Variável (Código)`==63& tab2`Geral, grupo, subgrupo, item e subitem (Código)`==series[i]]

var3[,i] <- tab3Valor[tab3`Variável (Código)`==63&
tab3`Geral, grupo, subgrupo, item e subitem (Código)`==series[i]]  peso1[,i] <- tab1Valor[tab1`Variável (Código)`==66& tab1`Geral, grupo, subgrupo, item e subitem (Código)`==series[i]]

peso2[,i] <- tab2Valor[tab2`Variável (Código)`==66&
tab2`Geral, grupo, subgrupo, item e subitem (Código)`==series[i]]  peso3[,i] <- tab3Valor[tab3`Variável (Código)`==66& tab3`Geral, grupo, subgrupo, item e subitem (Código)`==series[i]]
}

variacao = ts(rbind(var1, var2, var3), start=c(2006,07), freq=12)
peso = ts(rbind(peso1, peso2, peso3), start=c(2006,07), freq=12)

Assim, a inflação medida pelo IPCA nada mais será do que a variação vezes o respectivo peso do grupo. Com isso em mente, nós podemos gerar a previsão para cada grupo e depois recuperar a previsão da inflação cheia a partir dessas previsões individuais. O resultado é exposto no gráfico abaixo.

A previsão para a inflação em janeiro, por essa metodologia, é de 0,47%.

________________

(*) Para aprender a fazer esse tipo de projeção, veja nossos cursos de Previsão Macroeconométrica e Modelos Preditivos aplicados à Macroeconomia.

(**) Os códigos completos do exercício estão disponíveis no Clube AM.

Hackeando o R: acessando os dados do datasus com o R

By | Hackeando o R

Dentro do universo do R, cada vez mais tem sido facilitado o acesso a diversos tipos de dados. Para tanto, O pacote {microdatasus} tem como principal propósito a importação dos microdados do DATASUS, este sendo um sistema do estado brasileiro de apoio a conexão e suporte de informações sobre a saúde com os entes federativos. No Hackeando o R de hoje, iremos dar uma olhada sobre o pacote.

Antes de tudo é necessário realizar o download do pacote, que se encontra no repositório do autor no github.


# remotes::install_github("rfsaldanha/microdatasus")

library(microdatasus)
library(tidyverse)

O pacote se separa em dois tipos de funções, a primeira  sendo fetch_datasus(), que consiste na função que realiza o download dos dados. E o segundo tipo, que se refere ao pré-processamento dos dados, sendo eles: process_sim(), process_sinac() e process_sih().

Para importar os dados mostraremos exemplos da função fetch_datasus().

(obs: antes de replicar o código, certifique que sua máquina pode lidar com grandes quantidades de dados. O processo pode demorar um pouco).

# Sistema de Informação sobre Mortalidade de Minas Gerais de 2019

data_sim_mg <- fetch_datasus(year_start = 2019,
year_end = 2019,
uf = "MG",
information_system = "SIM-DO")

# Sistema de informação Hospital Descentralizada de Minas Gerais de 2019
data_sih_mg <- fetch_datasus(year_start = 2019,
year_end = 2019,
month_start = 1,
month_end = 12,
uf = "MG",
information_system = "SIH-RD")

# Sistema de informações sobre Nascidos Vivos de Minas Gerais de 2019

data_sinasc_mg <- fetch_datasus(year_start = 2019,
year_end = 2019,
uf = "MG",
information_system = "SINASC")

Trataremos de pegar somente dados de um único ano, já que são grandes quantidade de dados. Dependendo da máquina, pode demorar um pouco o tempo de download.

Ao seguir a etapa, agora é preciso tratar os dados com as respectivas funções de cada sistema.


# Trata os dados do SIM

sim_mg <- process_sim(data_sim_mg)

# Trata os dados do SIH

sih_mg <- process_sih(data_sih_mg)

# Trata os dados do SIA

sinasc_mg <- process_sinasc(data_sinasc_mg)

As variáveis dos dados de cada sistema possuem uma forma especial de lidar, além de seus nomes serem processados em abreviações. Para obter a informações de todas as variáveis e suas convenções, é recomendável checar o repositório do github do pacote.


# Seleciona os dados de interesse: Estado civil da mãe e Sexo do bebê

sinasc <- sinasc_mg %>%
select(ESTCIVMAE, SEXO) %>%
na.omit()

# Visualiza os número de Mães por Estado Civil

sinasc %>%
count(ESTCIVMAE) %>%
ggplot(aes(x = ESTCIVMAE, y = n,
fill = ESTCIVMAE,
color = ESTCIVMAE,
label = n))+
geom_bar(stat = "identity")+
geom_label(color = "black")+
labs(title = "Estado Civil das Mães de Nascidos em Minas Gerais",
subtitle = "ano de 2019",
x = "",
y = "",
caption = "Elaborado por analisemacro.com.br com dados do DATASUS")+
theme_minimal()+
theme(legend.position = "none")


# Visualiza o número de bebês por sexo

sinasc %>%
count(SEXO) %>%
ggplot(aes(x = SEXO, y = n,
fill = SEXO,
color = "SEXO",
label = n))+
geom_bar(stat = "identity")+
geom_label(color = "black")+
labs(title = "Sexo dos bebês nascidos em Minas Gerais",
subtitle = "ano de 2019",
x = "",
y = "",
caption = "Elaborado por analisemacro.com.br com dados do DATASUS")+
theme_minimal()+
theme(legend.position = "none")

 

 

________________________________

Na Análise macro oferecemos cursos que ensinam você a como lidar com o micro dados e análise de dados. Veja nossa trilha de Micro dados e nosso curso de R para análise de dados.

________________________________

Receba diretamente em seu e-mail gratuitamente nossas promoções especiais
e conteúdos exclusivos sobre Análise de Dados!

Assinar Gratuitamente
{"cart_token":"","hash":"","cart_data":""}