文章中大部分的图片为Plotly制作的动态图片,博客功能有限,如果需要看原图,可以查看原文。
这篇文章的目标是提供一个介绍:使用Python进行加密货币(例如比特币)分析。我们将通过一个简单的Python脚本来检索、分析以及可视化不同加密货币上的数据。在这个过程中,我们将揭示波动剧烈的市场行为以及它们是如何演变的成一个有趣的趋势。在本教程中,我们关心的只是获取原始数据,揭示隐藏在数字中的秘密。
从头开始安装这个项目所需要的依赖关系的最简单方法是使用Anaconda,它是一个预先打包的Python数据科学生态系统和依赖项管理器。要设置Anaconda,我建议遵循正式的安装https://www.continuum.io/downloads。
如果你是高级玩家,并且你不想使用Anaconda,请跳到第2步。
安装了Anaconda,我们需要创建一个新的环境来保持我们的依赖关系。运行conda create --name cryptocurrency-analysis python=3
为我们的项目创建一个新的Anaconda环境。
接下来,运行source activate cryptocurrency-analysis
(在Linux / macOS上)或activate cryptocurrency-analysis
(在Windows上)来激活这个环境。
最后,运行conda install numpy pandas nb_conda jupyter plotly quandl
在环境中安装所需的依赖项。
PS:使用环境的好处是如果你计划在你的计算机上开发多个Python项目, Anaconda将为每个项目的依赖项创建一个特殊的环境目录,以保持其独立性。
一旦环境和依赖关系全部建立起来,运行jupyter notebook
启动iPython内核,然后打开浏览器http://localhost:8888/
。创建一个新的Python notebook,确保使用Python [conda env:cryptocurrency-analysis]
内核。
我们要做的第一件事就是导入所需的依赖关系。
import os
import numpy as np
import pandas as pd
import pickle
import quandl
from datetime import datetime
我们还将导入Plotly并启用离线模式。
import plotly.offline as py
import plotly.graph_objs as go
import plotly.figure_factory as ff
py.init_notebook_mode(connected=True)
接着,我们准备开始检索数据进行分析。首先,我们需要使用Quandl的免费比特币API获取比特币价格数据。
我们将定义一个函数来下载和缓存来自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
我们正在使用pickle
序列化并将下载的数据保存为文件,该函数将以Pandas数据框的形式返回数据。
首先,我们来介绍Kraken比特币交易所的历史比特币汇率。
# Pull Kraken BTC price exchange data
btc_usd_price_kraken = get_quandl_data('BCHARTS/KRAKENUSD')
我们可以使用head()
方法检查数据帧的前5行:
btc_usd_price_kraken.head()
接下来,我们将生成一个简单的图表,作为数据看起来正确的快速可视化验证。
# 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])
在这里,我们使用Plotly来生成我们的可视化。Plotly是一个不错的选择,因为它使用D3.js生成完全交互的图表,它也容易被嵌入到网页中。
你可能已经注意到了这个数据集有几个明显的下降峰值,特别是在2014年底和2016年初。比特币交易所的性质在于定价是由供求决定的,因此没有一个交易所包含比特币的真正“价格”。为了解决这个问题,我们将从另外三个比特币交易所获取数据,以计算总的比特币价格指数。
首先,我们将从每个交易所下载数据到一个数据框字典:
# 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
接下来,我们将定义一个简单的函数,将每个数据帧的公共列合并到一个新的组合数据框中。
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)
现在我们将把所有的数据框合并在“加权价格”列中。
# 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')
最后,我们可以使用tail()
方法预览最后五行的结果,以确保它看起来不错。
btc_usd_datasets.tail()
下一步是可视化这些数据集。我们将定义一个辅助函数来提供一个单行命令来从数据框中生成图形。
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)
为了简洁起见,我不过多介绍这些函数的工作原理。如果你想了解更多信息,请查阅Pandas和Plotly的文档。
# Plot all of the BTC exchange prices
df_scatter(btc_usd_datasets, 'Bitcoin Price (USD) By Exchange')
现在我们可以轻松地为比特币定价数据生成图表。
虽然这四个数据集走势大致相同,但是我们想要摆脱的是各种各样的违规行为,让我们从数据框中删除所有的零值。
# Remove "0" values
btc_usd_datasets.replace(0, np.nan, inplace=True)
当我们重新绘制数据框时,我们会看到一个更清晰的图表,没有降低峰值。
# Plot the revised dataframe
df_scatter(btc_usd_datasets, 'Bitcoin Price (USD) By Exchange')
现在我们可以计算一个新的列,其中包含所有交易所的平均每日比特币价格。
现在我们有了比特币价格的固定时间序列数据集,让我们为非比特币加密货币(通常称为altcoin)提供一些数据。
为了检索加密货币上的数据,我们将使用Poloniex API。我们将定义两个帮助函数来从这个API下载和缓存JSON数据。
首先,我们将定义get_json_data
,它将从提供的URL下载和缓存JSON数据:
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
接下来,我们将定义一个将生成Poloniex API HTTP请求的函数,并随后调用我们的新get_json_data
函数来保存结果数据。
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
我们将下载九个顶级加密货币:
Ethereum,Litecoin,Ripple,Ethereum classic,Stellar,Dash,Siacoin,Monero和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
我们可以预览Ethereum的价格表的最后几行,以确保可以使用。
altcoin_data['ETH'].tail()
由于大多数加密货币不支持美元或人民币直接交易,我们需要用比特币作为中介。现在我们可以将这个BTC-altcoin汇率数据与我们的比特币价格指数结合起来,直接计算出每个的BTC-altcoin对应的历史美元的价值。
# 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']
接下来,我们可以重新使用我们之前的merge_dfs_on_column
函数来为每个加密货币创建美元价格的组合数据框。
# 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')
最后,我们将比特币价格作为最后一列添加到组合数据框中。
# Add BTC price to the dataframe
combined_df['BTC'] = btc_usd_datasets['avg_btc_price_usd']
现在我们应该有一个包含我们正在用的十个加密货币的每日美元价格的数据框。
# 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')
你可能会注意到,加密货币尽管它们的价值和波动性非常不同,但看起来有些相关,因为统计数据的支持。
我们可以使用Pandas corr()
方法来测试我们的相关性假设,Pandas 中的方法是针对数据框中的每一列相对于每一列计算相关系数。
直接在时间序列(如原始价格数据)上计算相关性可以给出偏差的相关值。我们将通过应用pct_change()
方法来解决此问题,该方法将数据框中的每个单元格从绝对价格值转换为日收益率。
首先,我们计算一下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')
这些相关系数接近于1或-1的系数意味着该系列分别强相关或反相关,接近于零的系数意味着这些值不相关。
为了可视化这些结果,我们将创建一个辅助可视化函数:
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")
暗红色的数值代表强相关性(1)(注意,每种货币与其本身强相关),深蓝色的数值代表强逆相关性(-1)。浅蓝色/橙色/灰色/棕褐色代表不同程度的弱/不存在的相关性。
这张图表告诉我们什么?2016年不同加密电子货币的价格波动之间几乎没有显著的联系。
现在,为了验证我们最近几个月加密货币已经变得更加相关的假设,我们只用2017年的数据重复相同的测试。
combined_df_2017 = combined_df[combined_df.index.year == 2017]
combined_df_2017.pct_change().corr(method='pearson')
这些是更重要的相关系数。强大到足以作为投资的唯一基础?当然不是。
correlation_heatmap(combined_df_2017.pct_change(), "Cryptocurrency Correlations in 2017")
但值得注意的是,几乎所有的加密货币已经变得更加相互关联。
上图中一个值得注意的特征是XRP(Ripple的标记)是最不相关的加密货币。这里值得注意的例外是STR(Stellar的标志),与XRP的相关性最强(0.62)。
可以想象的是,由于使用每种货币的区块链服务的相似性,一些大资金玩家和对冲基金可能使用类似的交易策略来投资Stellar和Ripple。这可以解释为什么XRP与STR相比与其他加密货币有更强的相关性。
最后的一些想法和建议:
1.将更多加密货币的数据添加到分析中。
2.调整相关分析的时间框架和宽度,以获得更精确的趋势视图。
3.搜索交易量和/或区块链挖掘数据集的趋势。如果你想要预测未来的价格波动,则买入/卖出交易量比率可能比原始价格数据更相关。
4.训练机器学习模型以预测明天的价格。如果你有能力,你甚至可以尝试用循环神经网络(RNN)来做这件事。
5.使用你的分析,在交易网站(如Poloniex或Coinbase)上使用各自的交易API 创建一个自动化的“交易机器人” 。
6.分享你的发现!比特币和一般加密货币的最好的部分是它们的分散性使它们比任何其他资产更自由和民主。
希望本篇文章能够帮助到你!代码:https://github.com//triestpa/Cryptocurrency-Analysis-Python
如果你对此非常感兴趣,请参阅代码。
本文由北邮@爱可可-爱生活老师推荐,阿里云云栖社区组织翻译。
文章原标题《Analyzing Cryptocurrency Markets Using Python》,作者:Patrick Triest
全栈工程师,数据爱好者,贪得无厌的学习者,迷恋的建设者。
译者:虎说八道,审阅:
文章为简译,更为详细内容,请查看原文