QuantBrasil

Baixando Cotações e Plotando Médias Móveis com Python

Rafael Quintanilha
Por Rafael Quintanilha
30 outubro, 2020
Compartilhar:

Jupyter Notebooks permitem que análises de Data Science sejam feitas de forma dinâmica e colaborativa. Aliados com o poder do pandas para manipulação de dados em grandes quantidades, e matplotlib para rápida e fácil visualização, Notebooks são a ferramenta ideal para quem deseja fazer suas próprias análises.

O objetivo do QuantBrasil é compartilhar essas análises, aprendendo e ensinando sobre mercado financeiro e programação durante o processo. Mesmo que você não seja familiar com a tecnologia, fique por aqui! Queremos ser didáticos o suficiente para engajar pessoas com pouco ou nenhum conhecimento técnico, e ainda assim trazer valor com nossas análises mesmo que você seja experiente com análise quantitativa ou programação em Python.

Nota sobre Notebooks

Os posts desse blog são, eles mesmos, Jupyter Notebooks. Todo o código fonte pode ser acessado diretamente no Github. A forma mais simples de reproduzir o que é discutido nesses posts é através do Google Colab, um ambiente Jupyter online, onde você pode rodar suas análises sem precisar baixar nada.

No entanto, para projetos mais completas ou para mais performance, recomendamos a instalação de um ambiente local. Uma sugestão para quem deseja mais recursos é a instalação do Anaconda, que, além do Jupyter, também conta com várias outras ferramentas para Data Science.

Esqueleto de uma Análise

A maior parte dos nossos artigos será composto por três partes:

  1. Aquisição de dados
  2. Manipulação de dados
  3. Análise e/ou Apresentação de resultados

O primeiro post desse site unirá o básico dos 3 — aprenderemos a baixar cotações das empresas via Yahoo Finance e plotaremos as primeiras médias móveis.

1. Aquisição de Dados

Existem várias formas de se conseguir as cotações históricas dos papeis. A melhor, claro, vai depender do contexto e de sua necessidade. A forma mais fácil é através da API do Yahoo Finance, que permite baixar os dados com bastante confiança e de forma muito rápida.

O primeiro passo é instalar a biblioteca:

# %%capture means we suppress the output
%%capture

!pip install yfinance 
import yfinance as yf

Com a biblioteca instalada, baixar os dados é tão simples quanto:

data = yf.download("VALE3.SA", start="2019-01-01", end="2019-12-31")
data
OpenHighLowCloseAdj CloseVolume
Date
2019-01-0250.00999851.36999949.79000151.09000047.77407517319600
2019-01-0350.79999950.93999948.40000249.00000045.81972530120000
2019-01-0449.82000052.45000149.82000052.18999948.80268143360100
2019-01-0752.86999953.65000251.72000151.91000048.54085520998900
2019-01-0852.20000152.79999951.61999952.41000049.00840419925600
.....................
2019-12-2054.77000054.99000254.15000254.79000151.23393242124200
2019-12-2354.90000254.98000054.40000254.58000251.03756310225700
2019-12-2654.81000155.00000054.50999854.79000151.23393220410000
2019-12-2753.99000254.00000053.41999853.59999851.44928713920400
2019-12-3053.65000253.86000153.20000153.29999951.16132711928100

247 rows × 6 columns

Pronto! Nós baixamos as cotações da VALE3 do ano de 2019 e armazenamos numa estrutura chamada dataframe. Um dataframe é uma espécie de tabela que permite acesso e manipulação das linhas e colunas de forma eficiente (vetorial), tornando-se ideal para análises de datasets muito grandes.

Caso nosso interesse seja apenas no valor de fechamento, nós podemos acessar colunas específicas do nosso dataframe:

all_closes = data["Adj Close"]
print(all_closes)

Date 2019-01-02 47.774075 2019-01-03 45.819725 2019-01-04 48.802681 2019-01-07 48.540855 2019-01-08 49.008404 ... 2019-12-20 51.233932 2019-12-23 51.037563 2019-12-26 51.233932 2019-12-27 51.449287 2019-12-30 51.161327 Name: Adj Close, Length: 247, dtype: float64

Repare que quando selecionamos apenas uma coluna, o retorno é uma instância da classe Series. Series são fundamentalmente diferentes de dataframes — elas podem ser entendidas como vetores unidimensionais. Explorar a diferença entre dataframes e series está além do escopo deste post, mas é importante entender que nem todos os métodos que aplicam-se a um, funcionará no outro.

Caso você deseje explicitamente manipular um dataframe de apenas uma coluna, uma alternativa possível é a seguinte:

df = data[["Adj Close"]]
df
Adj Close
Date
2019-01-0247.774075
2019-01-0345.819725
2019-01-0448.802681
2019-01-0748.540855
2019-01-0849.008404
......
2019-12-2051.233932
2019-12-2351.037563
2019-12-2651.233932
2019-12-2751.449287
2019-12-3051.161327

247 rows × 1 columns

2. Manipulação de Dados

De posse do nosso dataset, o próximo passo é manipular os dados de acordo com a análise desejada. Nesse post introdutório, iremos calcular duas médias móveis — uma aritmética e outra exponencial.

Usando nosso dataset reduzido, vamos calcular a média móvel de 21 períodos:

df['MM21'] = df["Adj Close"].rolling(21).mean()
df
Adj CloseMM21
Date
2019-01-0247.774075NaN
2019-01-0345.819725NaN
2019-01-0448.802681NaN
2019-01-0748.540855NaN
2019-01-0849.008404NaN
.........
2019-12-2051.23393248.456697
2019-12-2351.03756348.659301
2019-12-2651.23393248.834298
2019-12-2751.44928749.003519
2019-12-3051.16132749.187526

247 rows × 2 columns

Simples, não? O método rolling do dataframe retorna uma janela de período n (21 no nosso exemplo). O método mean() é utilizado para computar a média da janela.

Note que os primeiros valores do nosso dataframe são NaN, ou seja, nulos. Isso é esperado, uma vez que para o primeiro valor de média de n períodos só será possível ser calculado uma vez que haja n linhas. Podemos verificar isso analisando as primeiras 21 linhas do nosso dataframe:

df.head(21)
Adj CloseMM21
Date
2019-01-0247.774075NaN
2019-01-0345.819725NaN
2019-01-0448.802681NaN
2019-01-0748.540855NaN
2019-01-0849.008404NaN
2019-01-0950.205326NaN
2019-01-1049.653622NaN
2019-01-1148.980354NaN
2019-01-1449.186069NaN
2019-01-1548.952297NaN
2019-01-1649.232830NaN
2019-01-1750.710278NaN
2019-01-1851.205879NaN
2019-01-2151.692131NaN
2019-01-2251.505112NaN
2019-01-2352.038120NaN
2019-01-2452.505665NaN
2019-01-2839.610687NaN
2019-01-2939.966022NaN
2019-01-3043.575493NaN
2019-01-3142.54688648.167262

O cálculo da média exponencial é ligeiramente diferente, mas não menos simples:

df["MME9"] = df["Adj Close"].ewm(span=9, min_periods=9).mean()
df
Adj CloseMM21MME9
Date
2019-01-0247.774075NaNNaN
2019-01-0345.819725NaNNaN
2019-01-0448.802681NaNNaN
2019-01-0748.540855NaNNaN
2019-01-0849.008404NaNNaN
............
2019-12-2051.23393248.45669749.832455
2019-12-2351.03756348.65930150.073477
2019-12-2651.23393248.83429850.305568
2019-12-2751.44928749.00351950.534312
2019-12-3051.16132749.18752650.659715

247 rows × 3 columns

Dessa vez nós usamos o método ewm, ou Exponential Weighted Functions. Repare que, ao contrário de rolling, dessa vez nós precisamos explicatamente passar o tamanho da janela (span) e a quantidade mínima de dados até iniciarmos a computação (min_periods).

df.head(9)
Adj CloseMM21MME9
Date
2019-01-0247.774075NaNNaN
2019-01-0345.819725NaNNaN
2019-01-0448.802681NaNNaN
2019-01-0748.540855NaNNaN
2019-01-0849.008404NaNNaN
2019-01-0950.205326NaNNaN
2019-01-1049.653622NaNNaN
2019-01-1148.980354NaNNaN
2019-01-1449.186069NaN49.031055

3. Apresentação de Resultados

Nossa simples manipulação de dados está pronta, o que significa que a etapa final da análise é apresentar os resultados. Hoje, iremos simplesmente explicar como fazer uma rápida plotagem dos dados, de forma a simplificar a visualização.

A ferramenta mais comumente utilizada se chama matplotlib, uma robusta biblioteca de visualização gráfica para Python. Hora de importar a biblioteca e plotar o nosso primeiro gráfico:

import matplotlib.pyplot as plt

df["Adj Close"].plot()

E nada mais! Com apenas uma linha de código conseguimos plotar uma coluna do nosso dataframe como um gráfico de linha. E se quisermos adicionar mais linhas?

df[["Adj Close", "MME9", "MM21"]].plot()

Novamente simples, como o esperado. Passando um array de colunas ["Adj Close", "MME9", "MM21"] somos capazes de, em uma linha, plotar os 3 valores e automaticamente adicionar uma legenda.

Melhorando a Apresentação do Gráfico

O último ponto que cobriremos nesse post introdutório é como melhorar a visualização do gráfico. Afinal, uma visualização de dados bem-feita precisa ser intuitiva para o leitor.

Para isso, vamos usar cores diferentes para cada linha, além de aumentarmos sua espessura e o tamanho da imagem:

plt.figure(figsize=(16,8))
plt.plot(df["Adj Close"])
plt.plot(df["MM21"], color="green", lineWidth=3)
plt.plot(df["MME9"], color="magenta", lineWidth=3)
plt.legend(df)
plt.show()

Embora pareça mais complicado, todas as linhas são bastante diretas. Vamos explicá-las uma a uma:

  • plt.figsize determina o tamanho da imagem em polegadas. Nesse caso, nossa figura será 16"x8";
  • plt.plot, separadamente, permite que você customize a linha que está sendo plotada. Embora não façamos nenhuma mudança na linha inicial, repare que alteramos a cor e a espessura das médias;
  • plt.legend permite que você tenha mais controle sobre a legenda do gráfico;
  • Finalmente, plot.show finaliza a customização e exibe a imagem.

Conclusão

Análises quantitativas são uma ferramenta muito poderosa para qualquer projeto de Data Science. Em particular, no mundo do mercado financeiro, elas podem literalmente lhe custar ou gerar dinheiro. Hoje apresentamos a base do que utilizaremos para fazer análises mais complexas no futuro. Espero que o conteúdo tenha sido relevante e que de certa forma seja um incentivo para que você inicie seus estudos na área!