Quem trabalha com análise de dados sabe que o trabalho de análise começa apenas após o tratamento adequado dos dados. Quando se assume o compromisso de montar e manter a sua própria base de dados, o trabalho de preparar os dados para análise é grande, e quando se conta com dados disponibilizados por terceiros (em grande parte distribuídos em planilhas, arquivos textos em formatos bizarros ou ainda disponíveis na web) este se torna um trabalho hercúleo, pois além da transformação dos dados para um formato estrutura, ainda é necessária a transformação pertinente à análise.

Dessa maneira, eu divido o trabalho de pré-análise em três etapas:

  1. aquisição dos dados brutos
  2. transformação dos dados em um formato estruturado
  3. transformação dos dados estruturados para a análise

Aí um incauto pode se perguntar, mas porque eu não coloco de uma vez os dados no formato final em que eu já quero analisar? Bem, por que eu a priori eu não sei como vou atacar o problema, em geral eu acredito que os dados brutos são úteis para o problema que eu quero abordar, mas certeza mesmo só tenho em relação a minha sexualidade. Outro fator é que estes dados podem ser úteis em outra análise e mantê-los em um estado preliminar, mas útil, é mais interessante do que mantê-los em um formato final, onde em alguns casos pode haver perda de informação. Por isso que além de manter os dados estruturados eu também gosto de manter os dados brutos, por que afinal o seguro morreu de velho e no futuro eu posso resolver estruturar estes dados de outra maneira e eu prefiro voltar a prancheta e partir dos dados brutos.

Pois bem, por sorte existem indivúduos de bom coração cuja missão é tornar a vida de milhares de pessoas menos miserável. Um grande indivíduo é o sr. Tammer Kamel fundador do Quandl, um site que armazena e disponibiliza dados de forma estruturada.

Hoje, 30 de março de 2014, o Quandl conta com aproximadamente 9 milhões de datasets referentes a diversos paises. Obviamente a maior parte é relacionada aos Estados Unidos, mas tem bastante coisa útil do Brasil. Boa parte dos dados do sistema de séries temporais do Banco Central estão lá e são atualizados diariamente. Só por manter os dados estruturados e atualizados, o Quandl já demostra grande valor, no entanto, ele ainda disponibiliza um API online para download dos dados em formatos estruturados como: XML, JSON, CSV, HTML, que também apresenta diversas funções para ordenação, tranformação e filtragem dos dados. Através da API é possível especificar o intervalo de datas para aquisição dos dados, a frequência dos dados: diária, semanal, mensal, anual, ..., e realizar calculos no dataset como a diferença entre os dados, a normalização para a indexação, entre outros. E além disso, ainda foram desenvolvidas bibliotecas, pela própria equipe do Quandl e por outros desenvolvedores pelo mundo, para customizar o download dos dados. Hoje constam bibliotecas para as seguintes linguagens/programas:

  • R
  • PYTHON
  • MATLAB
  • EXCEL
  • STATA
  • MAPLE
  • C#
  • JULIA
  • CLOJURE
  • EVIEWS
  • JAVA
  • .NET
  • C/C++

A grande vantagem dessas bibliotecas é que os dados já são transformados em uma estrutura de dados inerente a linguagem onde parte do esforço de formatação numérica (datas e números) já foi implementada. Vamos ver agora como utilizar o Quandl com Python para obter os dados estruturados.

Quandl com Python

Acredito que a biblioteca de Python foi uma das primeiras desenvolvidas para trabalhar com o Quandl. O projeto pode ser encontrado no github em quandl/Python o no PyPI. Eu fiz a instalação diretamente pelo pip install Quandl e não tive problemas. O Quandl precisa do numpy e do pandas para funcionar de forma que ele não disponibiliza os dados em estruturas de dados padrões do Python como dict e list e caso você queira os dados nestas estruturas sugiro utilizar diretamente a API online, escolher o formato JSON e utilizar o módulo json.

Bem, vamos meter a mão na massa, para utilizar o Quandl vamos começar importando o módulo Quandl.

In [1]:
import Quandl

Para obter os dados basta chamar a função get do módulo passando o ticker do dataset que se deseja baixar. No exemplo abaixo vamos utilizar o ticker GOOG/BVMF_PETR4 referente às ações da Petrobras negociadas na BM&FBovespa e disponibilizadas pelo Google Finance.

In [2]:
petr4 = Quandl.get("GOOG/BVMF_PETR4")
print petr4.index
print petr4.head()
No authentication tokens found: usage will be limited.
See www.quandl.com/api for more information.
Returning Dataframe for  GOOG/BVMF_PETR4
<class 'pandas.tseries.index.DatetimeIndex'>
[2003-06-02 00:00:00, ..., 2014-03-28 00:00:00]
Length: 2682, Freq: None, Timezone: None
            Open  High   Low  Close    Volume
Date                                         
2003-06-02  6.58  6.68  6.54   6.56   7481600
2003-06-03  6.56  6.56  6.50   6.55   6329600
2003-06-04  6.62  6.78  6.58   6.75   9747200
2003-06-05  6.72  6.81  6.71   6.74  10420000
2003-06-06  6.78  6.88  6.77   6.79   7205600

[5 rows x 5 columns]

Note que petr4 é um DataFrame pandas, caso não queira ou não goste de trabalhar com pandas é possível obter os dados em um numpy array.

In [3]:
petr4_np = Quandl.get("GOOG/BVMF_PETR4", returns='numpy')
print petr4_np.shape
print petr4_np
No authentication tokens found: usage will be limited.
See www.quandl.com/api for more information.
(2682,)
[('2003-06-02', 6.58, 6.68, 6.54, 6.56, 7481600.0)
 ('2003-06-03', 6.56, 6.56, 6.5, 6.55, 6329600.0)
 ('2003-06-04', 6.62, 6.78, 6.58, 6.75, 9747200.0) ...,
 ('2014-03-26', 14.55, 14.69, 14.35, 14.4, 29462600.0)
 ('2014-03-27', 14.39, 15.57, 14.32, 15.57, 77279000.0)
 ('2014-03-28', 15.57, 15.77, 15.2, 15.66, 42202400.0)]

A formatação do numpy é mais pobre, no entanto tudo depende do que se queira fazer com os dados, de forma que a opção está aí e cada um utiliza como for conveniente.

Como sempre falo para olhar os dados, em ambas saídas podemos observar que temos 5 colunas e 2682 registros (ou linhas) ordenadas de forma ascendente. Como peguei os dados referentes às ações Petrobras, em geral estes dados vem no formato OHLC (Open, High, Low, Close e Volume). No DataFrame isso fica evidente, já no numpy array é necessário um conhecimento prévio deste fato, pra pelo menos saber o que é o que.

Baixando multiplos ativos

Uma coisa legal é poder baixar diversos ativos em um único request, como fazemos abaixo:

In [4]:
petr_bova = Quandl.get(["GOOG/BVMF_PETR4.4", "GOOG/BVMF_BOVA11.4"])
print petr_bova.index
print petr_bova.head()
No authentication tokens found: usage will be limited.
See www.quandl.com/api for more information.
Returning Dataframe for  [u'GOOG.BVMF_PETR4.4', u'GOOG.BVMF_BOVA11.4']
<class 'pandas.tseries.index.DatetimeIndex'>
[2003-06-02 00:00:00, ..., 2014-03-28 00:00:00]
Length: 2682, Freq: None, Timezone: None
            GOOG.BVMF_PETR4 - Close  GOOG.BVMF_BOVA11 - Close
Date                                                         
2003-06-02                     6.56                       NaN
2003-06-03                     6.55                       NaN
2003-06-04                     6.75                       NaN
2003-06-05                     6.74                       NaN
2003-06-06                     6.79                       NaN

[5 rows x 2 columns]

Como a série da Petrobrás é maior do que a do BOVA11 (BOVA11 é um ETF) a maior série é preservada e os dados incompletos vem com NaN.

Baixando intervalos de datas específicos

Querendo evitar os NaN vamos limitar o request às datas em que temos informação do BOVA11, que é a partir de 2012-11-22.

In [5]:
petr_bova = Quandl.get(["GOOG/BVMF_PETR4.4", "GOOG/BVMF_BOVA11.4"], trim_start='2012-11-22')
print petr_bova.index
print petr_bova.head()
No authentication tokens found: usage will be limited.
See www.quandl.com/api for more information.
Returning Dataframe for  [u'GOOG.BVMF_PETR4.4', u'GOOG.BVMF_BOVA11.4']
<class 'pandas.tseries.index.DatetimeIndex'>
[2012-11-22 00:00:00, ..., 2014-03-28 00:00:00]
Length: 333, Freq: None, Timezone: None
            GOOG.BVMF_PETR4 - Close  GOOG.BVMF_BOVA11 - Close
Date                                                         
2012-11-22                    18.65                     55.31
2012-11-23                    19.17                     56.49
2012-11-26                    18.82                     55.65
2012-11-27                    18.51                     55.10
2012-11-28                    18.65                     55.50

[5 rows x 2 columns]

Poderiamos pegar apenas o ano de 2013 fazendo

In [6]:
petr_bova = Quandl.get(["GOOG/BVMF_PETR4.4", "GOOG/BVMF_BOVA11.4"], trim_start='2013-01-01', trim_end='2013-12-31')
print petr_bova.index
print petr_bova.head()
No authentication tokens found: usage will be limited.
See www.quandl.com/api for more information.
Returning Dataframe for  [u'GOOG.BVMF_PETR4.4', u'GOOG.BVMF_BOVA11.4']
<class 'pandas.tseries.index.DatetimeIndex'>
[2013-01-02 00:00:00, ..., 2013-12-30 00:00:00]
Length: 248, Freq: None, Timezone: None
            GOOG.BVMF_PETR4 - Close  GOOG.BVMF_BOVA11 - Close
Date                                                         
2013-01-02                    19.69                     61.27
2013-01-03                    20.40                     61.92
2013-01-04                    20.48                     61.32
2013-01-07                    20.08                     60.75
2013-01-08                    19.50                     59.91

[5 rows x 2 columns]

Outras opções interessantes

Uma opção que eu acho muito legal é a opção de baixar os últimos n registros, pois pensando em processamento diário eu não precisaria ficar especificando as datas para download, sabendo sempre que a data atual é a referência. Para isso basta utilizar os parâmetros rows=n e sort_order='desc'. Vamos utilizar isso para baixar a última divulgação da taxa CDI da CETIP.

In [7]:
cdi = Quandl.get("BCB/4389", rows=1, sort_order='desc')
print cdi
No authentication tokens found: usage will be limited.
See www.quandl.com/api for more information.
Returning Dataframe for  BCB/4389
            Value
Date             
2014-03-27  10.55

[1 rows x 1 columns]

Outra opção interessante, que eu particularmente não uso muito, é a definição de frequência dos dados. No entanto, as vezes é interessante analisar as séries temporais em frequências menores como mensal ou anual. Vamos ver como baixar os dados do Índice Bovespa em cotação mensal.

In [8]:
bvsp = Quandl.get("YAHOO/INDEX_BVSP", collapse="monthly")
print bvsp.head(10)
No authentication tokens found: usage will be limited.
See www.quandl.com/api for more information.
Returning Dataframe for  YAHOO/INDEX_BVSP
            Open  High   Low  Close  Volume  Adjusted Close
Date                                                       
1993-04-30   237   242   237    241       0            24.1
1993-05-31   349   349   349    349       0            34.9
1993-06-30   529   542   529    537       0            53.7
1993-07-31   661   674   656    656       0            65.6
1993-08-31   998   998   963    964       0            96.4
1993-09-30  1474  1503  1465   1466       0           146.6
1993-10-31  1775  1852  1748   1844       0           184.4
1993-11-30  2765  2782  2700   2740       0           274.0
1993-12-31  3736  3786  3736   3755       0           375.5
1994-01-31  6892  7417  6892   7406       0           740.6

[10 rows x 6 columns]

Note que cada registro é referente ao fim de cada mês.

Encontrando os tickers

Uma coisa que não mencionei, mas é de toda a relevância é sobre como encontrar os tickers. Bem, essa é a coisa mais simples, basta fazer uma busca no próprio site do Quandl. Lá você encontra os datasets, os seus tickers, as datas de início e fim e outras informações pertinentes ao dataset.

Conclusão

Bem, é isso. Vimos aqui como obter dados estruturados em Python através de uma interface simples que elimina o risco operacional da aquisição de dados na web. Na prática este risco foi assumido pelo Quandl e ao utilizar a ferramenta você assume que eles lidam com este risco melhor do que você.

Uma dica importante é se registrar no site e realizar os downloads utilizando o token de autenticação. É possível realizar 50 downloads diários sem autenticação, e autenticando é possível realizar maiores taxas de download e caso você precise de grandes volumes diários entre em contato com o site e negocie, pois eles não cobram pelo serviço mas gostam de avaliar exceções uma a uma.