Comparação de carteira com IBOV usando Python

Comparao de carteira com Ibov usando python published at the "Open Code Community"

Nesse post, vou mostrar como fazer como comparar uma carteira qualquer com o IBOV utilizando o python.

1. Instalando e importando bibliotecas

!pip install yfinance
import yfinance as yf
import yfinance as yf
import pandas as pd
import numpy as np

2. Importando dados

Repare que vou importar também os dados da cotação do dólar. Posteriormente vou converter a cotação do Ethereum para reais, por isso que estou trazendo a cotação do dólar. Ou seja, multiplicar a cotação de Dolar-Real pelo preço do ETH em dólar para obter o preço do ETH em real.

Criando o vetor dos tickers.

ativos = ['PETR4.SA','VALE3.SA', 'WEGE3.SA', 
          'RADL3.SA', 'OIBR3.SA','KNRI11.SA',
          'SMAL11.SA','AAPL34.SA','IVVB11.SA','ETH-USD','USDBRL=X']

Criando uma data de inicio e de fim da captação de dados.

inicio = '2020-05-01'
fim = '2021-08-24'

Criando o data.frame dos preços.

precos = pd.DataFrame()

Baixando as cotações
for i in ativos:
  precos[i] = yf.download(i, start = inicio, end = fim)['Adj Close']

Vamos converter a cotação do Ethereum para reais:

precos['ETH-BRL'] = precos['ETH-USD']*precos['USDBRL=X']

Agora podemos remover as colunas do Ethereum em dólares e da cotação do dólar

precos = precos.drop(columns=['ETH-USD', 'USDBRL=X'])
precos.to_csv('Dados.csv', sep = ';', decimal=',')

Vamos normalizar o preço dos ativos para visualizar seus desempenhos.

normalizado = precos/precos.iloc[0]
normalizado.plot(figsize = (8,8));

png

3. Simulação de uma carteira vs. IBOV

Criando um dicionário com as alocações que vamos fazer para cada ativo na nossa carteira

compras = {'PETR4.SA': 1000, 'VALE3.SA': 700, 'WEGE3.SA': 1500, 
           'RADL3.SA': 700, 'OIBR3.SA': 200, 'KNRI11.SA': 700, 
           'SMAL11.SA': 1500, 'AAPL34.SA': 2000, 'IVVB11.SA': 1500, 
           'ETH-BRL': 200}
           
compras_df = pd.Series(data=compras, index=list(compras.keys()))

Qual o valor total da nossa carteira?

sum(compras.values())
10000

Obtendo preços dos ativos no primeiro dia do investimento

primeiro = precos.iloc[0]

Quantidade de papéis comprados de cada ativo

qtd_acoes = compras_df/primeira

Criando um dataframe que contém a posição diária de cada ativo

PL = precos*qtd_acoes
PL.head(3)

PETR4.SAVALE3.SAWEGE3.SARADL3.SAOIBR3.SAKNRI11.SASMAL11.SAAAPL34.SAIVVB11.SAETH-BRL
Date
2020-05-041000.000000700.0000001500.000000700.000000200.000000700.0000001500.0000002000.0000001500.000000200.000000
2020-05-051032.221098696.3351181468.750176696.987266205.882347702.6854491479.3773602059.3690901526.950431200.962154
2020-05-06994.246331706.3737611461.973107693.037478205.882347717.2314861462.3338422137.1675891548.315577199.662245
PL.tail()

PETR4.SAVALE3.SAWEGE3.SARADL3.SAOIBR3.SAKNRI11.SASMAL11.SAAAPL34.SAIVVB11.SAETH-BRL
Date
2021-08-171703.3601431892.9359082648.266605855.407388299.999991594.9552332217.3617143962.5660782256.6490042781.549609
2021-08-181688.2359831829.4253192563.528423852.039629297.058818595.1343002220.2590803953.0622002273.9362112804.717612
2021-08-191678.7832791725.0484522686.437068883.022892299.999991587.6598832275.3095693985.5751252308.4221573002.797046
2021-08-201676.2626451725.7561082746.746469898.177773305.882339596.5664892316.3845083993.5780892303.1029543121.606584
2021-08-231702.7299551701.8731642729.188091892.452603338.235284623.1969802316.2139064037.0954252332.3581663131.866252

Criando uma coluna que contém a posição consolidada da nossa carteira diariamente

PL['PL Total'] = PL.iloc[:].sum(axis = 1)
PL.head()

PETR4.SAVALE3.SAWEGE3.SARADL3.SAOIBR3.SAKNRI11.SASMAL11.SAAAPL34.SAIVVB11.SAETH-BRLPL Total
Date
2020-05-041000.000000700.0000001500.000000700.000000200.000000700.0000001500.0000002000.0000001500.000000200.00000010000.000000
2020-05-051032.221098696.3351181468.750176696.987266205.882347702.6854491479.3773602059.3690901526.950431200.96215410069.520489
2020-05-06994.246331706.3737611461.973107693.037478205.882347717.2314861462.3338422137.1675891548.315577199.66224510126.223764
2020-05-071003.452454733.7809471471.762093694.175587197.058826716.1125601431.6554592199.9998861622.340455212.82394610283.162213
2020-05-081063.291199778.3974101439.759181700.803383202.941174727.3018191433.3597852220.1084261602.393646217.76911410386.125134
PL.tail()

PETR4.SAVALE3.SAWEGE3.SARADL3.SAOIBR3.SAKNRI11.SASMAL11.SAAAPL34.SAIVVB11.SAETH-BRLPL Total
Date
2021-08-171703.3601431892.9359082648.266605855.407388299.999991594.9552332217.3617143962.5660782256.6490042781.54960919213.051672
2021-08-181688.2359831829.4253192563.528423852.039629297.058818595.1343002220.2590803953.0622002273.9362112804.71761219077.397575
2021-08-191678.7832791725.0484522686.437068883.022892299.999991587.6598832275.3095693985.5751252308.4221573002.79704619433.055463
2021-08-201676.2626451725.7561082746.746469898.177773305.882339596.5664892316.3845083993.5780892303.1029543121.60658419684.063959
2021-08-231702.7299551701.8731642729.188091892.452603338.235284623.1969802316.2139064037.0954252332.3581663131.86625219805.209825

Obtendo dados do IBOV para comparar com a nossa carteira

ibov = yf.download('^BVSP', start = inicio, end = fim)
ibov.head()

OpenHighLowCloseAdj CloseVolume
Date
2020-05-0480501.080502.077640.078876.078876.08594200
2020-05-0578887.081066.078886.079471.079471.09154700
2020-05-0679473.079996.078056.079064.079064.09775900
2020-05-0779072.080061.078061.078119.078119.013808900
2020-05-0878152.080557.078152.080263.080263.010734400
ibov.rename(columns = {'Adj Close': 'IBOV'}, inplace = True)
ibov = ibov.drop(ibov.columns[[0,1,2,3,5]], axis = 1)
ibov

IBOV
Date
2020-05-0478876.0
2020-05-0579471.0
2020-05-0679064.0
2020-05-0778119.0
2020-05-0880263.0
......
2021-08-17117904.0
2021-08-18116643.0
2021-08-19117165.0
2021-08-20118053.0
2021-08-23117472.0

324 rows × 1 columns

Verificando se o índice dos dataframes está no formato ‘data’

ibov.index = pd.to_datetime(ibov.index)
PL.index = pd.to_datetime(PL.index)

Juntando tudo num dataframe só

novo_df = pd.merge(ibov, PL, how = 'inner', on = 'Date')
novo_df.head()

IBOVPETR4.SAVALE3.SAWEGE3.SARADL3.SAOIBR3.SAKNRI11.SASMAL11.SAAAPL34.SAIVVB11.SAETH-BRLPL Total
Date
2020-05-0478876.01000.000000700.0000001500.000000700.000000200.000000700.0000001500.0000002000.0000001500.000000200.00000010000.000000
2020-05-0579471.01032.221098696.3351181468.750176696.987266205.882347702.6854491479.3773602059.3690901526.950431200.96215410069.520489
2020-05-0679064.0994.246331706.3737611461.973107693.037478205.882347717.2314861462.3338422137.1675891548.315577199.66224510126.223764
2020-05-0778119.01003.452454733.7809471471.762093694.175587197.058826716.1125601431.6554592199.9998861622.340455212.82394610283.162213
2020-05-0880263.01063.291199778.3974101439.759181700.803383202.941174727.3018191433.3597852220.1084261602.393646217.76911410386.125134

Normalizando esse novo dataframe que contém o IBOV, todos os ativos e o PL da nossa carteira

PL_normalizado = novo_df/novo_df.iloc[0]
PL_normalizado.head()

IBOVPETR4.SAVALE3.SAWEGE3.SARADL3.SAOIBR3.SAKNRI11.SASMAL11.SAAAPL34.SAIVVB11.SAETH-BRLPL Total
Date
2020-05-041.0000001.0000001.0000001.0000001.0000001.0000001.0000001.0000001.0000001.0000001.0000001.000000
2020-05-051.0075431.0322210.9947640.9791670.9956961.0294121.0038360.9862521.0296851.0179671.0048111.006952
2020-05-061.0023830.9942461.0091050.9746490.9900541.0294121.0246160.9748891.0685841.0322100.9983111.012622
2020-05-070.9904031.0034521.0482580.9811750.9916790.9852941.0230180.9544371.1000001.0815601.0641201.028316
2020-05-081.0175851.0632911.1119960.9598391.0011481.0147061.0390030.9555731.1100541.0682621.0888461.038613
PL_normalizado.tail()

IBOVPETR4.SAVALE3.SAWEGE3.SARADL3.SAOIBR3.SAKNRI11.SASMAL11.SAAAPL34.SAIVVB11.SAETH-BRLPL Total
Date
2021-08-171.4948021.7033602.7041941.7655111.2220111.5000000.8499361.4782411.9812831.50443313.9077481.921305
2021-08-181.4788151.6882362.6134651.7090191.2171991.4852940.8501921.4801731.9765311.51595714.0235881.907740
2021-08-191.4854331.6787832.4643551.7909581.2614611.5000000.8395141.5168731.9927881.53894815.0139851.943306
2021-08-201.4966911.6762632.4653661.8311641.2831111.5294120.8522381.5442561.9967891.53540215.6080331.968406
2021-08-231.4893251.7027302.4312471.8194591.2749321.6911760.8902811.5441432.0185481.55490515.6593311.980521

Plot da nossa carteira vs. o IBOV

PL_normalizado[['IBOV', 'PL Total']].plot(figsize = (10,10));

png

Podemos observar que nossa carteira teórica, montada pelos ativos descritos anteriomentes e seus respectivos pesos, bate o IBOV (tem um retorno maior). Esse exercício de montar carteiras a partir de um racional, e olhar como ela teria se comportado no passado, se chama backtest. Portanto, pelo nosso backtest, nossa carteira bate o IBOV.


Please, cite this work:

Gomes, Victor (2021), “Comparação de carteira com Ibov usando python published at the “Open Code Community” ”, Mendeley Data, V1, doi: 10.17632/49knfhr5t5.1

Victor Gomes (since 2021/05)
Victor Gomes (since 2021/05)
CEO (Trading com Dados)
Próximo
Anterior

Relacionados