Como os mercados de Bitcoin se comportam? Quais são as razões do aumento e queda repentinos dos preços das criptomoedas? Existe uma conexão estreita e inseparável entre os mercados de altcoin ou eles são praticamente independentes um do outro? Como podemos prever o que acontecerá no futuro?
Abordagem analítica da informação para o raciocínio de criptomoeda
Artigos dedicados a criptomoedas como Bitcoin e Ethereum abundam em raciocínio e teorias. Centenas de especialistas autoproclamados defendem tendências que eles acreditam que aparecerão em breve. O que muitas dessas análises carecem com certeza é uma base sólida na forma de dados e estatísticas que podem suportar certas declarações.
O objetivo deste artigo é fornecer uma introdução simples à análise de criptomoedas usando Python. Nele, examinaremos passo a passo um script Python simples para receber, analisar e visualizar dados em várias criptomoedas. No decorrer do trabalho, descobriremos uma tendência interessante no comportamento dos mercados voláteis e descobriremos quais mudanças ocorreram neles.

Este post não será dedicado a explicar o que são criptomoedas (se você precisar de uma explicação dessas, eu recomendaria essa excelente
revisão ). Não haverá discussão sobre quais moedas específicas aumentarão ou diminuirão de valor. Em vez disso, o guia se concentrará em obter acesso a dados brutos e brutos e em encontrar o histórico oculto sob camadas de números.
Etapa 1. Equipamos nosso laboratório
Este guia é destinado a uma ampla gama de entusiastas, engenheiros e profissionais de processamento de dados, independentemente do seu nível de profissionalismo. Com base nas habilidades, você precisará apenas de um conhecimento básico do Python e das habilidades mínimas de linha de comando necessárias para configurar o projeto.
A versão completa do trabalho realizado e todos os seus resultados estão disponíveis
aqui .
1.1 Instalar o Anaconda
A maneira mais fácil de instalar dependências do zero para este projeto é usar o Anaconda, um ecossistema python e gerenciador de dependências que contém todos os pacotes necessários para trabalhar com dados e analisá-los.
Para instalar o Anaconda, eu recomendaria usar as instruções oficiais disponíveis
aqui .
Se você é um usuário avançado e o Anaconda não gosta, não é necessário instalá-lo. Nesse caso, acho que você não precisa de ajuda para instalar as dependências necessárias e pode ir diretamente para o segundo estágio.1.2 Configurando o ambiente do projeto no Anaconda
Assim que o Anaconda estiver instalado, queremos criar um novo ambiente para organizar o trabalho com dependências.
Digite o comando
conda create --name cryptocurrency-analysis python=3
para criar um novo ambiente Anaconda para o nosso projeto.
Em seguida, insira a
source activate cryptocurrency-analysis
e (no Linux / macOS) ou
activate cryptocurrency-analysis
(no Windows) para ativar o ambiente.
E, finalmente, o
conda install numpy pandas nb_conda jupyter plotly quandl
instalará as dependências necessárias no ambiente. Esse processo pode levar alguns minutos.
Por que usamos o ambiente? Se você planeja trabalhar simultaneamente com muitos projetos Python no seu computador, é útil colocar as dependências (bibliotecas e pacotes de software) separadamente para evitar conflitos. Dentro de cada projeto, o Anaconda cria um diretório especial para dependências no ambiente, que permite separá-las das dependências de outros projetos e organizar o trabalho com elas.1.3 Iniciando o notebook interativo Jupyter Notebook
Depois que o ambiente e as dependências estiverem instalados, digite
jupyter notebook
no console para iniciar o kernel do iPython e abra o link
http: // localhost: 8888 / no navegador. Crie um novo notebook Python, verificando se ele usa o kernel
Python [conda env:cryptocurrency-analysis]
.

1.4 Importando dependências para a parte superior do notebook
Assim que você vir um log Jupyter limpo, primeiro precisará importar as dependências necessárias.
import os import numpy as np import pandas as pd import pickle import quandl from datetime import datetime
Além disso, você deve importar o Plotly e ativar o modo offline para ele.
import plotly.offline as py import plotly.graph_objs as go import plotly.figure_factory as ff py.init_notebook_mode(connected=True)
Etapa 2. Obtendo dados de preços do Bitcoin
Agora que todas as configurações estão completas, estamos prontos para começar a receber informações para análise. Primeiro de tudo, precisamos solicitar dados de preços do Bitcoin usando a
API gratuita do
Bitcoin API Quandl .
2.1 Definir uma função auxiliar do Quandl
Para ajudar na aquisição de dados, definiremos uma função que baixa e armazena em cache os conjuntos de dados do Quandl.
def get_quandl_data(quandl_id): '''Download and cache Quandl dataseries''' cache_path = '{}.pkl'.format(quandl_id).replace('/','-') try: f = open(cache_path, 'rb') df = pickle.load(f) print('Loaded {} from cache'.format(quandl_id)) except (OSError, IOError) as e: print('Downloading {} from Quandl'.format(quandl_id)) df = quandl.get(quandl_id, returns="pandas") df.to_pickle(cache_path) print('Cached {} at {}'.format(quandl_id, cache_path)) return df
Para converter os dados baixados e salvá-los em um arquivo, usaremos
pickle
. Isso impedirá que os mesmos dados sejam baixados novamente sempre que executarmos o script. A função retornará dados como um quadro de dados do
Pandas . Se você não estiver familiarizado com os quadros de dados, poderá apresentá-los na forma de planilhas muito poderosas.
2.2 Tomamos dados de preços da bolsa Kraken
Para começar, vamos extrair os dados históricos sobre a taxa de câmbio do Bitcoin da bolsa
Kraken .
# Pull Kraken BTC price exchange data btc_usd_price_kraken = get_quandl_data('BCHARTS/KRAKENUSD')
Podemos verificar as 5 primeiras linhas do quadro de dados usando o método
head()
.
btc_usd_price_kraken.head()

Em seguida, vamos gerar um gráfico simples para verificação visual rápida da correção dos dados.
# Chart the BTC pricing data btc_trace = go.Scatter(x=btc_usd_price_kraken.index, y=btc_usd_price_kraken['Weighted Price']) py.iplot([btc_trace])

Para visualização,
Plotly é usado
aqui . Essa é uma abordagem menos tradicional em comparação com as bibliotecas de visualização em python mais autoritativas, como o
Matplotlib , mas, na minha opinião, o Plotly é uma excelente opção, pois permite criar gráficos totalmente interativos usando o
D3.js. Como resultado, você pode obter bons diagramas visuais na saída sem nenhuma configuração. Além disso, o Plotly é fácil de aprender e seus resultados são facilmente inseridos em páginas da web.
Obviamente, você deve sempre lembrar a necessidade de comparar as visualizações resultantes com gráficos de preços de criptomoedas disponíveis ao público (por exemplo, no Coinbase) para uma verificação básica da confiabilidade dos dados baixados.2.3 Solicitar dados de preços de outras trocas BTC
Você deve ter notado discrepâncias neste conjunto: o gráfico diminui em vários lugares para zero, especialmente no final de 2014 e no início de 2016. Essas quedas são encontradas no conjunto de dados Kraken e, obviamente, não queremos que elas sejam refletidas em nossa análise final de preços.
A natureza das trocas de bitcoin é tal que os preços são determinados pela oferta e pela demanda e, portanto, nenhuma das trocas existentes pode alegar que suas cotações refletem o único preço verdadeiro e de referência do Bitcoin. Para levar em conta essa desvantagem, bem como para eliminar o subsidência de preços no gráfico, provavelmente devido a erros técnicos ou de conjunto de dados, coletaremos adicionalmente dados de três outras grandes trocas de bitcoins para calcular o índice de preços agregado para bitcoin.
Para começar, vamos baixar os dados de cada troca em um dicionário de quadros de dados.
# Pull pricing data for 3 more BTC exchanges exchanges = ['COINBASE','BITSTAMP','ITBIT'] exchange_data = {} exchange_data['KRAKEN'] = btc_usd_price_kraken for exchange in exchanges: exchange_code = 'BCHARTS/{}USD'.format(exchange) btc_exchange_df = get_quandl_data(exchange_code) exchange_data[exchange] = btc_exchange_df
2.4 Combinando todos os dados de preços em um quadro de dados
A seguir, definiremos uma função simples que combina as colunas semelhantes de cada quadro de dados em um novo quadro combinado.
def merge_dfs_on_column(dataframes, labels, col): '''Merge a single column of each dataframe into a new combined dataframe''' series_dict = {} for index in range(len(dataframes)): series_dict[labels[index]] = dataframes[index][col] return pd.DataFrame(series_dict)
Agora, vamos combinar todos os quadros de dados com base na coluna Preço Ponderado.
# Merge the BTC price dataseries' into a single dataframe btc_usd_datasets = merge_dfs_on_column(list(exchange_data.values()), list(exchange_data.keys()), 'Weighted Price')
Por fim, observe as últimas cinco linhas usando o método
tail()
para garantir que o resultado do nosso trabalho pareça normal.
btc_usd_datasets.tail()

Os preços parecem os esperados: eles estão dentro de limites semelhantes, mas há pequenas diferenças com base na relação oferta / demanda em cada troca individual.
2.5 Visualizar conjuntos de dados de preços
O próximo passo lógico é visualizar a comparação dos conjuntos de dados resultantes. Para isso, definimos uma função auxiliar que fornece a capacidade de gerar um gráfico com base em um quadro de dados usando um comando de linha única.
def df_scatter(df, title, seperate_y_axis=False, y_axis_label='', scale='linear', initial_hide=False): '''Generate a scatter plot of the entire dataframe''' label_arr = list(df) series_arr = list(map(lambda col: df[col], label_arr)) layout = go.Layout( title=title, legend=dict(orientation="h"), xaxis=dict(type='date'), yaxis=dict( title=y_axis_label, showticklabels= not seperate_y_axis, type=scale ) ) y_axis_config = dict( overlaying='y', showticklabels=False, type=scale ) visibility = 'visible' if initial_hide: visibility = 'legendonly' # Form Trace For Each Series trace_arr = [] for index, series in enumerate(series_arr): trace = go.Scatter( x=series.index, y=series, name=label_arr[index], visible=visibility ) # Add seperate axis for the series if seperate_y_axis: trace['yaxis'] = 'y{}'.format(index + 1) layout['yaxis{}'.format(index + 1)] = y_axis_config trace_arr.append(trace) fig = go.Figure(data=trace_arr, layout=layout) py.iplot(fig)
Por uma questão de brevidade, não entrarei em detalhes sobre o funcionamento de uma função auxiliar. Se você estiver interessado em aprender mais sobre isso, consulte a
documentação do
Pandas e
Plotly .
Podemos facilmente gerar um gráfico para dados de preços de bitcoin.
# Plot all of the BTC exchange prices df_scatter(btc_usd_datasets, 'Bitcoin Price (USD) By Exchange')

2.6 Limpando e combinando dados de preços
Podemos ver que, apesar de todas as quatro séries de dados se comportarem aproximadamente da mesma maneira, existem vários desvios da norma neles que precisam ser eliminados.
Vamos remover todos os valores zero do quadro, pois sabemos que o preço do bitcoin nunca foi zero dentro do período que estamos considerando.
# Remove "0" values btc_usd_datasets.replace(0, np.nan, inplace=True)
Tendo construído o gráfico novamente, obtemos uma curva mais limpa, sem quedas acentuadas.
# Plot the revised dataframe df_scatter(btc_usd_datasets, 'Bitcoin Price (USD) By Exchange')

E agora podemos calcular uma nova coluna contendo o preço médio diário do bitcoin com base nos dados de todas as trocas.
# Calculate the average BTC price as a new column btc_usd_datasets['avg_btc_price_usd'] = btc_usd_datasets.mean(axis=1)
Esta nova coluna é o nosso índice de preços Bitcoin! Vamos plotá-lo para garantir que pareça normal.
# Plot the average BTC price btc_trace = go.Scatter(x=btc_usd_datasets.index, y=btc_usd_datasets['avg_btc_price_usd']) py.iplot([btc_trace])

Sim, parece bom. Usaremos a série de preços combinados no futuro para converter as taxas de câmbio de outras criptomoedas em dólar americano.
Etapa 3. Obtenção dos dados de preços do altcoin
Agora que temos uma série temporal confiável de preços para bitcoin, solicitamos alguns dados para criptomoedas que não sejam bitcoin, que geralmente são chamadas de altcoins.
3.1 Definindo funções auxiliares para trabalhar com a API Poloniex
Para obter dados de altcoin, usaremos
a API Poloniex . Duas funções auxiliares que baixam e armazenam em cache os dados JSON passados para esta API nos ajudarão nisso.
Primeiro, definimos
get_json_data
, que fará o download e armazenará em cache os dados JSON na URL fornecida.
def get_json_data(json_url, cache_path): '''Download and cache JSON data, return as a dataframe.''' try: f = open(cache_path, 'rb') df = pickle.load(f) print('Loaded {} from cache'.format(json_url)) except (OSError, IOError) as e: print('Downloading {}'.format(json_url)) df = pd.read_json(json_url) df.to_pickle(cache_path) print('Cached {} at {}'.format(json_url, cache_path)) return df
Em seguida, definimos uma função que gera solicitações HTTP para a API do Poloniex e, em seguida, chama
get_json_data
, que, por sua vez, armazena os dados solicitados.
base_polo_url = 'https://poloniex.com/public?command=returnChartData¤cyPair={}&start={}&end={}&period={}' start_date = datetime.strptime('2015-01-01', '%Y-%m-%d') # get data from the start of 2015 end_date = datetime.now() # up until today pediod = 86400 # pull daily data (86,400 seconds per day) def get_crypto_data(poloniex_pair): '''Retrieve cryptocurrency data from poloniex''' json_url = base_polo_url.format(poloniex_pair, start_date.timestamp(), end_date.timestamp(), pediod) data_df = get_json_data(json_url, poloniex_pair) data_df = data_df.set_index('date') return data_df
Ela pega uma sequência que indica o par de criptomoedas (por exemplo, BTC_ETH) e retorna um quadro de dados contendo dados históricos em sua taxa de câmbio.
3.2 Fazendo download de dados comerciais com o Poloniex
A maioria das altcoins não pode ser comprada diretamente por dólares americanos. Para adquiri-los, as pessoas costumam comprar bitcoins e trocá-los por altcoins em bolsas. Portanto, baixamos as taxas de câmbio do BTC para cada moeda e usamos os dados ao preço do BTC para calcular o custo das altcoins em USD.
Fazemos o download dos dados de estoque das nove criptomoedas mais populares -
Ethereum ,
Litecoin ,
Ripple ,
Ethereum Classic ,
Stellar ,
Dashcoin ,
Siacoin ,
Monero e
NEM .
altcoins = ['ETH','LTC','XRP','ETC','STR','DASH','SC','XMR','XEM'] altcoin_data = {} for altcoin in altcoins: coinpair = 'BTC_{}'.format(altcoin) crypto_price_df = get_crypto_data(coinpair) altcoin_data[altcoin] = crypto_price_df
Agora, temos um dicionário de 9 quadros de dados, cada um dos quais contém dados históricos sobre os pares de preços médios diários de troca de altcoins e bitcoin.
Mais uma vez, verificaremos as últimas cinco linhas da tabela de preços do Ethereum para garantir que tudo esteja em ordem.
altcoin_data['ETH'].tail()

3.3 conversão de preços em dólares americanos
Agora podemos comparar os dados dos pares de preços com o nosso índice de preços de bitcoin para obter diretamente dados históricos sobre o valor das altcoins em dólares americanos.
# Calculate USD Price as a new column in each altcoin dataframe for altcoin in altcoin_data.keys(): altcoin_data[altcoin]['price_usd'] = altcoin_data[altcoin]['weightedAverage'] * btc_usd_datasets['avg_btc_price_usd']
Usando esse código, criamos uma nova coluna no quadro de dados de cada altcoin com os preços das moedas em dólares.
Além disso, podemos reutilizar a função definida anteriormente
merge_dfs_on_column
para criar um quadro de dados contendo preços em dólares para cada criptomoeda.
# Merge USD price of each altcoin into single dataframe combined_df = merge_dfs_on_column(list(altcoin_data.values()), list(altcoin_data.keys()), 'price_usd')
Assim mesmo. Agora, vamos também adicionar os preços do bitcoin à última coluna do quadro de dados combinado.
# Add BTC price to the dataframe combined_df['BTC'] = btc_usd_datasets['avg_btc_price_usd']
E agora temos um único quadro contendo preços diários em dólar para as dez criptomoedas que estamos estudando.
Vamos reutilizar a função
df_scatter
definida anteriormente para desenhar um gráfico comparativo das mudanças de preço das criptomoedas.
# Chart all of the altocoin prices df_scatter(combined_df, 'Cryptocurrency Prices (USD)', seperate_y_axis=False, y_axis_label='Coin Value (USD)', scale='log')

Ótimo! O gráfico permite avaliar claramente a dinâmica das taxas de câmbio de cada criptomoeda nos últimos anos.
Observe que usamos a escala de ordenadas logarítmicas, porque ela permite ajustar todas as moedas em um gráfico. Mas, se desejar, você pode tentar diferentes valores de parâmetros (como scale='linear'
) para examinar os dados de uma perspectiva diferente.3.4 Análise de Correlação
Você deve ter notado que as taxas de câmbio de criptomoedas, apesar de seus valores e volatilidade completamente diferentes, parecem ter alguma correlação entre elas. Especialmente se você observar o intervalo após o aumento de agosto, até pequenas flutuações ocorrem com tokens diferentes, como se fossem sincronizadas.
Mas uma premonição baseada em semelhança externa não é melhor do que um simples palpite até que possamos fazer backup com dados estatísticos.
Podemos testar nossa hipótese de correlação usando o método
corr()
do conjunto Pandas, usando-o para calcular o coeficiente de correlação de Pearson de todas as colunas do quadro em relação uma à outra.
Correção de 22/8/2017 - Esta parte do trabalho foi revisada. Agora, para calcular os coeficientes de correlação, em vez dos valores absolutos de preços, são usados os valores percentuais de suas alterações diárias.O cálculo das correlações diretamente entre séries temporais não estacionárias (como dados brutos de preços) pode levar a resultados tendenciosos. Nós corrigiremos esse defeito aplicando o método
pct_change()
, que converte o valor de cada célula de quadro de um valor absoluto em uma porcentagem de sua alteração diária.
Para começar, calculamos a correlação em 2016.
# Calculate the pearson correlation coefficients for cryptocurrencies in 2016 combined_df_2016 = combined_df[combined_df.index.year == 2016] combined_df_2016.pct_change().corr(method='pearson')

Agora temos chances em todos os lugares. Valores próximos a 1 ou -1 dizem que, entre as séries temporais, há uma forte correlação direta ou reversa, respectivamente. Coeficientes próximos de zero significam que os valores não se correlacionam e variam independentemente um do outro.
Para visualizar os resultados, precisamos criar outra função de visualização auxiliar.
def correlation_heatmap(df, title, absolute_bounds=True): '''Plot a correlation heatmap for the entire dataframe''' heatmap = go.Heatmap( z=df.corr(method='pearson').as_matrix(), x=df.columns, y=df.columns, colorbar=dict(title='Pearson Coefficient'), ) layout = go.Layout(title=title) if absolute_bounds: heatmap['zmax'] = 1.0 heatmap['zmin'] = -1.0 fig = go.Figure(data=[heatmap], layout=layout) py.iplot(fig)
correlation_heatmap(combined_df_2016.pct_change(), "Cryptocurrency Correlations in 2016")

As células vermelhas escuras no gráfico indicam uma forte correlação (e cada uma das moedas obviamente se correlacionará consigo mesma o máximo possível), azul escuro - uma forte correlação inversa. Todas as cores azul, laranja, cinza e areia entre elas indicam diferentes graus de correlação fraca ou sua ausência.
O que esse gráfico nos diz? De fato, mostra que a relação estatisticamente significativa entre flutuações de preços de várias criptomoedas em 2016 é pequena.
E agora, para testar nossa hipótese de que as criptomoedas se tornaram mais correlacionadas nos últimos meses, vamos repetir o mesmo teste usando dados já para 2017.
combined_df_2017 = combined_df[combined_df.index.year == 2017] combined_df_2017.pct_change().corr(method='pearson')

Os coeficientes obtidos indicam a presença de uma correlação mais significativa. Ela é forte o suficiente para tirar proveito desse fato para investimento? Definitivamente não.
Porém, devemos prestar atenção ao fato de que quase todas as criptomoedas como um todo se tornaram mais correlatas.
correlation_heatmap(combined_df_2017.pct_change(), "Cryptocurrency Correlations in 2017")

E esta é uma observação bastante interessante.
Por que isso está acontecendo?
Boa pergunta Não tenho certeza.
O primeiro pensamento que vem à mente: a razão é que os fundos de hedge começaram recentemente a negociar abertamente nos mercados de criptomoedas. [
1 ] [
2 ] Esses fundos têm quantias muito maiores de capital do que os negociadores médios e, se se protegerem dos riscos, borrifando seus fundos em uma variedade de criptomoedas e usando estratégias de negociação semelhantes para cada um deles, com base em variáveis independentes (como fazem , por exemplo, no mercado de ações), uma conseqüência lógica dessa abordagem pode ser o surgimento de uma tendência para correlações crescentes.
Análise aprofundada: XRP e STR
Por exemplo, uma das tendências confirma indiretamente o raciocínio acima. XRP (Ripple token) está menos correlacionado com outras altcoins. Mas há uma exceção notável - STR (o token estelar, o oficial é chamado de “Lumens”), cujo coeficiente de correlação com o XRP é 0,62.
Curiosamente, Stellar e Ripple são plataformas fintech bastante semelhantes, cujas atividades visam simplificar o processo de pagamentos interbancários internacionais.
Vejo uma situação muito real na qual alguns jogadores ricos e fundos de hedge usam estratégias semelhantes para negociar fundos investidos no Stellar e Ripple, já que os dois serviços por trás desses tokens são de natureza muito semelhante. Essa suposição pode explicar por que o XRP está muito mais correlacionado com o STR do que com outras criptomoedas.
Sua vez
No entanto, essa explicação é em grande parte uma conclusão especulativa. Mas talvez você possa fazer melhor? A base que lançamos neste trabalho nos permite continuar o estudo de dados em várias direções.
Aqui estão algumas idéias para verificar:
- Adicione dados para mais criptomoedas à análise.
- Corrija o prazo e o grau de detalhe da análise de correlação, considerando as tendências em mais detalhes, ou vice-versa, em termos mais gerais.
- Procure tendências em volumes de negociação e / ou conjuntos de dados para mineração de blockchain. Os índices de vendas / compra são mais adequados para prever flutuações de preços do que dados brutos de preços.
- Adicione dados de preços de estoques, commodities e matérias-primas, moedas fiduciárias para descobrir quais desses ativos se correlacionam com as criptomoedas. (Mas lembre-se sempre do bom e velho ditado: "Correlação ainda não implica causalidade".)
- Quantifique a quantidade de hype em torno de criptomoedas usando Registro de Eventos , GDELT e Google Trends .
- Usando o aprendizado de máquina, treine um programa para analisar dados e prever tendências de preços. Se a ambição permitir, você pode tentar fazê-lo com uma rede neural recorrente.
- Use sua análise para criar uma negociação automatizada de comerciantes de bot em sites como Poloniex e Coinbase usando as APIs apropriadas. Mas tenha cuidado: um robô de negociação mal otimizado pode privá-lo rapidamente de todos os fundos disponíveis.
- Compartilhe suas descobertas! A melhor característica do Bitcoin e de outras criptomoedas em geral é que sua natureza descentralizada as torna mais livres e democráticas, em comparação com quase todos os outros ativos. , , , -.
HTML- python-
.
, , - , , , .
, , , - , . - ,
Github- .
, , , . , , , .
