– Integração Python para Finanças
Atenção!! Este módulo não é sobre finanças ou mercado financeiro.
Nosso objetivo aqui é entender como interagir via Python com ferramentas, bases comumente utilizadas no mercado financeiro.
Essencialmente, o que veremos aqui são métodos ou bibliotecas já conhecidas aplicadas a essa realidade. Dito isso, vamos começar ☺ !
Como sempre vamos iniciar pela importação de bibliotecas que nos permitirão analisar dados de ativos financeiros.
As importações estão destacadas ao lado.
Nosso objetivo aqui é entender como interagir via Python com ferramentas, bases comumente utilizadas no mercado financeiro.
Essencialmente, o que veremos aqui são métodos ou bibliotecas já conhecidas aplicadas a essa realidade. Dito isso, vamos começar ☺ !
Como sempre vamos iniciar pela importação de bibliotecas que nos permitirão analisar dados de ativos financeiros.
As importações estão destacadas ao lado.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import pandas_datareader.data as web
• Além do nosso bom e velho Pandas, vamos importar também pandas_datareader que nos permite ler dados da web (doc)
Para essa integração, usaremos o Yahoo Finance. Por isso, vai ser necessário conhecer a nomenclatura utilizada por esse site. Por exemplo, se queremos saber as cotações da IBOVESPA no Yahoo Finance iremos usar o código ^BVSP. Outro exemplo, são em casos de ações brasileiras como a ITUB4(nome original usado na Bovespa). No Yahoo Finance, utilizaremos ITUB4.SA.
Sabendo dessas informações, podemos usar nosso primeiro método do pandas_datareader:
.DataReader()
Esse método nos permite buscar os dados de cotação da web do período solicitado conforme apresentado ao lado.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import pandas_datareader.data as web
cotacao_ibov = web.DataReader('^BVSP', data_source='yahoo', start='2020-1-1', end='2020-11-10')
display(cotacao_ibov)
_________________________________

• data_source: indica que será puxada do yahoo.
• start: início do período desejado;
• end: fim do período desejado.
Feito essa importação dos dados, podemos trata-los de acordo com nosso interesse. Para isso, usaremos as outras bibliotecas que foram importadas.
No exemplo ao lado fizemos um gráfico usando o matplotlib a partir dos dados da coluna ‘Adj Close’.
cotacao_ibov['Adj Close'].plot(figsize=(15, 5))
________________________
<AxesSubplot:xlabel='Date'>

• Adj Close - Coluna a ser considerada para o gráfico.
• Figsize: permite ajustar o tamanho do gráfico criado.
– Retorno IBOV e Média Móvel
Tendo as informações extraídas no Yahoo Finance, podemos agora realizar diversas análises. Vamos começar por uma muito comum e bem simples. O cálculo do retorno da Bovespa para o período definido anteriormente.
Como queremos o retorno do período, vamos calcular o ganho percentual entre a cotação do último dia do período e o primeiro dia do período. O cálculo do retorno será dado por:
Ú𝑙𝑡𝑖𝑚𝑎 𝑐𝑜𝑡𝑎çã𝑜 𝑑𝑜 𝑝𝑒𝑟í𝑜𝑑𝑜
𝑅𝑒𝑡𝑜𝑟𝑛𝑜 = ______________________ _ 1
𝑃𝑟𝑖𝑚𝑒𝑖𝑟𝑎 𝑐𝑜𝑡𝑎çã𝑜 𝑑𝑜 𝑝𝑒𝑟í𝑜𝑑𝑜
Para acessarmos a última cotação usaremos a posição [-1] da coluna [‘Adj Close’], já para a primeira cotação do período, usaremos a posição [0].
retorno_ibov = cotacao_ibov['Adj Close'][-1] / cotacao_ibov['Adj Close'][0] - 1
print('Retorno de {:.2%}'.format(retorno_ibov))
____________________
Retorno de -11.15%
Calculado o retorno, vamos para outra análise muito comum pelos investidores de bolsa de valores. A Média Móvel. Para isso, usaremos o Pandas. Ao invés de definirmos uma fórmula, usaremos dois métodos já existentes dentro dessa biblioteca:
rolling().mean()
Ela nos permitirá definir as médias apenas informando o número de pontos que desejamos. Nesse caso, como cada ponto representa um dia, ao definirmos 21 no método rolling, estamos definindo 21 dias. Veja o exemplo ao lado, além do Pandas também utilizamos o Matplotlib para plotarmos no gráfico as médias móveis definidas por nós.
#Média móvel da bolsa
cotacao_ibov['Adj Close'].plot(figsize=(15, 5), label='IBOV')
cotacao_ibov['Adj Close'].rolling(21).mean().plot(label='MM21')
cotacao_ibov['Adj Close'].rolling(34).mean().plot(label='MM34')
plt.legend()
plt.show()
_______________________

– Pegando Cotações Carteira com Python
Para esse exemplo vamos usar uma carteira de investimentos “Carteira do Lira” ( obviamente não é a real ☺ ). Nosso objetivo é criar um dataframe de todos os ativos da nossa carteira com as cotações do período indicado. Usaremos um pouco do conhecimento adquirido anteriormente nesse módulo, mas vamos precisar adicionar alguns outros elementos.
Para que o entendimento, fique mais fácil vamos dividir a explicação em X partes:
Passo 1 : Importar as bibliotecas e os dados da carteira contidos no arquivo “Carteira.xlsx”;
Passo 2 : Criar um dataframe vazio que receberá os ativos e as cotações “puxadas” do Yahoo Finance;
Passo 3 : Definir linha de código de preenchimento de apenas 1 dos ativos no Dataframe;
Passo 4: Usando o FOR, criar um código que preencha todos os ativos no dataframe criado.

Passo 1 : Importar as bibliotecas e os dados da carteira contidos no arquivo “Carteira.xlsx”;
Assim como nos exemplos anteriores deste módulo, usaremos o pandas.reader para a busca de informações no site do Yahoo Finance e o pandas para o tratamento dos dados dentro de um dataframe.
Além disso, usaremos posteriormente o numpy e matplotlib para elaboração de gráficos.
Como já vimos no módulo sobre PANDAS, para importarmos as informações de um Excel, usaremos o método .read_excel().
O exemplo ao lado, apresenta o código em Python para a conclusão do PASSO 1.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import pandas_datareader.data as web
carteira = pd.read_excel('Carteira.xlsx')
display(carteira)
_____________________

Passo 2 : Criar um dataframe vazio que receberá os ativos e as cotações “puxadas” do Yahoo Finance;
Esta é a linha menos intuitiva de todas, então vamos avaliá-la por partes. Se usarmos essencialmente o mesmo código utilizado anteriormente, conseguimos buscas as cotações, mas além disso, também obtemos uma série de informações que não nos interessa por enquanto (high, low, open, close, volume).
De todas as informações apresentadas ao lado, apenas a última coluna nos interessa e além disso, pensando que vamos ter vários ativos no nosso dataframe, será importante renomeá-lo de acordo com o nome do ativo. Nesse caso ‘BOVA11.SA’.
Vamos entender como fazer essa etapa na próxima página ☺.
cotacoes_carteira = pd.DataFrame()
cotacoes_carteira = web.DataReader('BOVA11.SA', data_source='yahoo', start='2020-01-01', end='2020-11-10')
display(cotacoes_carteira)
_____________________

Passo 3 : Definir linha de código de preenchimento de apenas 1 dos ativos no Dataframe;
Para facilitar a visualização desta etapa, criamos uma variável ‘extracao’ que armazenará o dataframe apresentado anteriormente.
Como vimos, queremos que no nosso dataframe cotacoes_carteira exista uma coluna com o nome do ativo [‘BOVA11.SA’] mas que apenas a coluna [‘Adj Close’] seja utilizada.
O exemplo ao lado, apresenta como realizar esta etapa.
cotacoes_carteira = pd.DataFrame()
cotacoes_carteira = web.DataReader('BOVA11.SA', data_source='yahoo', start='2020-01-01', end='2020-11-10')
cotacoes_carteira = web.DataReader['BOVA11.SA'] = extracao['Adj Close']
display(cotacoes_carteira)
A T E N Ç Ã O !
Por fins didáticos, dividimos essa linha em 2 etapas, mas seria possível realizar essa etapa diretamente sem a necessidade da criação da variável extracao.
Passo 4: Usando o FOR, criar um código que preencha todos os ativos no dataframe criado.
Como temos vários ativos, podemos utilizar o FOR para percorrer todos esses ativos adicionando seus dados ao nosso dataframe cotações_carteira.
cotacoes_carteira = pd.DataFrame()
for ativo in carteira['Ativos']:
extracao = web.DataReader('{}.SA'.format(ativo), data_source='yahoo', start='2020-01-01', end='2020-11-10')
cotacoes_carteiraátivo] = extracao['Adj Close']
display(cotacoes_carteira)
• For permite percorrer toda lista de ativos existentes no dataframe carteira.
• Ao invés de utilizar o nome do ativo, é utilizada a variável ativo que possui o nome correspondente àquela iteração.
– Tratando Problemas de importação para o Dataframe e Normalização
Assim como vimos no módulo do Pandas, é sempre importante analisarmos a qualidade dos dados antes de iniciar a análise dos dados.
Um método já conhecido por nós que nos permite ter uma visão geral do dados é o método .info() conforme apresentado ao lado.
Podemos perceber que aparentemente todos os dados foram trazidos corretamente, com exceção do ativo XPLG11. Nesse caso temos apenas 176 dados não nulos enquanto os outros ativos, 210.
Possivelmente algum problema ocorreu na própria base do Yahoo Finance. Nesse caso, não temos muito o que fazer além de tratarmos esses dados faltantes usando alguma premissa.
cotacoes_carteira.info()
___________________________________
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 210 entries, 2020-01-02 to 2020-11-10
Data columns (total 14 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 BOVA11 210 non-null float64
1 SMAL11 210 non-null float64
2 MGLU3 210 non-null float64
3 BBDC4 210 non-null float64
4 ITUB4 210 non-null float64
5 ENEV3 210 non-null float64
6 MOVI3 210 non-null float64
7 BPAC11 210 non-null float64
8 GNDI3 210 non-null float64
9 NTCO3 210 non-null float64
10 BCRI11 210 non-null float64
11 VILG11 210 non-null float64
12 KNRI11 210 non-null float64
13 XPLG11 176 non-null float64
dtypes: float64(14)
memory usage: 24.6 KB
• Valores faltantes no ativo XPLG11. Era esperado 210 assim como os outros ativos.
Para o ajuste destes dados faltantes, poderíamos usar algumas premissas. Segue abaixo a listagem de algumas mais comuns :
• Excluir dados faltantes;
• Utilizar a média de todos ou uma dos valores;
• Replicar o dado anterior existente mais próximo.
Não existe uma abordagem 100% correta, qualquer uma que venha a ser adotada será uma premissa utilizada e qual utilizar irá variar de projeto para projeto.
No nosso caso, usaremos o valor existente imediatamente anterior ao dado faltante. Ou seja, O valor da cotação do dia anterior ao do dado faltante.
Para isso, usaremos o método .ffill() que nos permite preencher os espaços vazios com os dados existentes na linha anterior.
cotacoes_carteira = cotacoes_carteira.ffill()
cotacoes_carteira.info()
____________________________
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 210 entries, 2020-01-02 to 2020-11-10
Data columns (total 14 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 BOVA11 210 non-null float64
1 SMAL11 210 non-null float64
2 MGLU3 210 non-null float64
3 BBDC4 210 non-null float64
4 ITUB4 210 non-null float64
5 ENEV3 210 non-null float64
6 MOVI3 210 non-null float64
7 BPAC11 210 non-null float64
8 GNDI3 210 non-null float64
9 NTCO3 210 non-null float64
10 BCRI11 210 non-null float64
11 VILG11 210 non-null float64
12 KNRI11 210 non-null float64
13 XPLG11 210 non-null float64
dtypes: float64(14)
memory usage: 24.6 KB
• Apesar de não serem dados reais, a premissa nos permite igualar a quantidade de dados existentes.
Para conseguirmos analisar nossos ativos em um mesmo gráfico é interessante normalizarmos os valores.
O que isso significa? Vamos considerar o primeiro valor conhecido da nossa base de ativos como a linha de base. Todas as variações (positivas ou negativas) serão referencias a essa linha de base. Isso nos permitirá avaliar a evolução de todos os ativos em um mesmo gráfico independentemente do seus valores serem, em valores absolutos, muito distintos.
Como normalizar? Considerando nosso caso, vamos criar um novo dataframe que será:
𝑉𝑎𝑙𝑜𝑟 𝑑𝑎 𝑐𝑜𝑡𝑎çã𝑜 𝑑𝑜 𝑑𝑖𝑎
_____________________________
𝑉𝑎𝑙𝑜𝑟 𝑑𝑎 𝑐𝑜𝑡𝑎çã𝑜 𝑑𝑜 1º 𝑑𝑖𝑎 𝑑𝑎 𝑏𝑎𝑠𝑒 𝑑𝑒 𝑑𝑎𝑑𝑜𝑠
Chamaremos esse novo dataframe de carteira_norm conforme apresentado ao lado.
carteira_norm = cotacoes_carteira / cotacoes_carteira.iloc[0]
carteira_norm.plot(figsize=(15, 5))
plt.legend(loc='upper left')
_____________________________

• Cotação do 1º dia. O iloc[0] significa que estamos pegando a primeira linha do nosso dataframe
• Os dados normalizados nos permitem ver a evolução em % dos ativos. Perceba que todos valores se iniciam com valor no eixo y = 1.
Sem a normalização a diferença entre valores absoluto dificultaria muito a análise conjunta em um único gráfico
– Criando Valor da Carteira e Puxando Ibovespa
A primeira parte é a mesma que já fizemos anteriormente. Puxar do Yahoo Finance usando o pandas.reader(definido como web nesse exemplo) para realizar a importação dos dados. Nosso objetivo é comparar a rentabilidade entre a Bovespa e nossa carteira. Já aprendemos como calcular essa rentabilidade anteriormente, mas consideramos que todos os ativos possuíam a mesma quantidade, o que dificilmente é realidade em um caso real.
Portanto, vamos precisar incorporar a quantidade dos ativos a nossa análise.
Para isso, vamos criar um novo dataframe chamado valor_investido conforme apresentado ao lado, onde a quantidade do ativo apresentada no dataframe carteira é multiplicada pelo valor da cotação do ativo no dataframe cotacoes_carteira.
Vamos entender um pouco melhor este código na próxima página
cotacao_ibov = web.DataReader('^BVSP', data_source='yahoo', start='2020-01-01', end='2020-11-10')
display(cotacao_ibov)
_____________________

Vamos utilizar a mesma estrutura de for utilizada anteriormente para “preencher” nosso novo dataframe valor_investido. A parte que é menos intuitiva nesse caso é como buscar as informações do nosso dataframe carteira. Como podemos ver no extrato apresentado abaixo, a orientação do nosso dataframe é diferente. Os ativos não são colunas e sim parte dos dados que são apresentados em linhas.
Assim, usaremos o .loc para acessar os dados. A informação desejada, SEMPRE, estará na coluna Qtde, e o que nos permite chegar no valor certo da coluna e o nome do ativo. Assim, usaremos a estrutura abaixo para acessar os dados.
valor_investido = pd.DataFrame()
for ativo in carteira['Ativos']:
valor_investido[ativo] = cotacoes_carteira[ativo] * carteira.loc[carteira['Ativos']==ativo, 'Qtde'].values[0]
display(valor_investido)
• carteira: nome do dataframe;
• carteira[‘Ativos’]==ativo: o valor da coluna ‘Ativos’ do df carteira que for IGUAL ao valor de ativo nesta iteração do for;
• ‘Qtde’: Coluna que desejamos
• .values[0] = indica que queremos o valor do df conforme as condições dos itens anteriores.
– Comparando a Carteira com Ibovespa
Agora que temos o valor investido por carteira, vamos descobrir o valor total da carteira.
Para isso, vamos criar uma coluna de TOTAL no nosso dataframe valor_investido.
Vamos calculá-la utilizando o método .sum(). No entanto, esse método por padrão soma colunas e não linhas... Vamos precisar fornecer um argumento para especial para nosso método que nos permita somar as linhas que representarão o valor total da carteira/dia.
Esse argumento será axis=1.
valor_investido['Total'] = valor_investido.sum(axis=1)
• Criação de uma coluna [‘Total’] no dataframe valor_investido.
• axis=1 permite somar linhas ao invés de colunas (axis=0) que é a configuração padrão do método sum().
Criada nossa coluna Total, podemos replicar os conhecimentos das páginas anteriores realizando as etapas abaixo:
1) Normalizar valores para plotagem dos gráficos;
2) Plotar gráfico acrescentando as labels necessárias para identificação;
3) Utilizando a fórmula abaixo, calcular o retorno:
Ú𝑙𝑡𝑖𝑚𝑎 𝑐𝑜𝑡𝑎çã𝑜 𝑑𝑜 𝑝𝑒𝑟í𝑜𝑑𝑜
𝑅𝑒𝑡𝑜𝑟𝑛𝑜 =________________________ _ 1
𝑃𝑟𝑖𝑚𝑒𝑖𝑟𝑎 𝑐𝑜𝑡𝑎çã𝑜 𝑑𝑜 𝑝𝑒𝑟í𝑜𝑑𝑜
Após a realização das etapas acima teremos o gráfico apresentado ao lado assim como os retornos indicados na parte inferior.
Podemos perceber que os gráficos parecem relacionados e vamos aproveitar isso para aprender mais um método do PANDAS, o .corr().
valor_investido['Total'] = valor_investido.sum(axis=1)
valor_investido_norm = valor_investido / valor_investido.iloc[0]
cotacao_ibov_norm = cotacao_ibov / cotacao_ibov.iloc[0]
valor_investido_norm['Total'].plot(figsize=(15, 5), label='Carteira')
cotacao_ibov_norm['Adj Close'].plot(label='IBOV')
plt.legend()
plt.show()
_______________________________

retorno_carteira = valor_investido['Total'][-1] / valor_investido['Total'][0] - 1
retorno_ibov = cotacao_ibov['Adj Close'][-1] / cotacao_ibov['Adj Close'][0] - 1
print('Retorno da Carteira: {:.2%}'.format(retorno_carteira))
print('Retorno IBOV: {:.2%}'.format(retorno_ibov))
________________________
Retorno da Carteira: 1.93%
Retorno IBOV: -11.15%
Os valores de correlação, variam sempre entre -1 e 1. Valores próximos de 1 indicam que existe uma relação forte e diretamente proporcional, ou seja, se um índice sobe, o outro também sobe. Valores próximos de -1 indicam que existe uma relação forte mas inversamente proporcional, ou seja, se um índice sobe, o outro desce.
Na imagem ao lado apresentamos a correlação alcançada no nosso exemplo utilizando o método .corr().
Como já era esperado pela nossa análise gráfica, podemos ver que esta correlação é bastante forte e de proporcionalidade positiva.
correlacao = valor_investido['Total'].corr(cotacao_ibov['Adj Close'])
print(correlacao)
_____________________
0.8879301020686045
Nenhum comentário:
Postar um comentário