0. はじめに
2017年頃から一気に流行り始めて、一時bitcoinが2万ドルを付けました。2018年は6~7000ドル程度まで下がり始めているとはいえ、まだまだ根強い人気がありますね。様々な人が統計・機械学習手法を用いて解析をしていると思うけれど、私もWSL(Windows Subsystem for Linux)でちょっとやってみた。
参考サイト(引用)は下記です。
Analyzing Cryptocurrency Markets Using Python:
https://blog.patricktriest.com/analyzing-cryptocurrencies-python/
1. 仮想環境構築
1.1 Anacondaとは
Anacondaはデータサイエンスのプラットフォームで最も有名。Python単独だと、必要なパッケージをインストールしなければならないが、Anacondaだと機械学習や可視化等のパッケージは標準インストールできる。
Anacondaのインストール- https://www.continuum.io/download
$ wget https://repo.anaconda.com/archive/Anaconda3-5.2.0-Linux-x86_64.sh
$ chmod u+x Anaconda3-5.2.0-Linux-x86_64.sh
$ ./Anaconda3-5.2.0-Linux-x86_64.sh
上記コマンドでインストール用のスクリプトを取得して実行できる。
1.2 構築
はじめに仮想環境を構築する。作成はconda create
で行う。デフォルトでは、condaディレクトリのenvs
下に作成される。仮想環境を作り、アクティベートする。
conda create --name cryptocurrency-analysis python=3.6
source activate cryptocurrency-analysis
有効を解除するには、Linux/Macでは
source deactivate
にてできる。詳しくは、ユーザーガイド参照
次に、環境に必要なパッケージをインストールする。
conda install numpy pandas nb_conda jupyter plotly quandl
numpy
は科学技術における数値処理操作に特化したパッケージ。pandas
はデータ処理や解析に、nb_conda
はanaconda上ではjupyter notebookを動かすために必要。jupyter
は解析結果をブラウザ上で表示するためのノートブックとして使用する。plotly
は可視化用。matplotlibでもよいが、時系列データの可視化はploylyやdygraphsの方がキレイだし、なによりplotly
はHTML, CSS, JS取得できる。qundl
は金融・経済などの数値データの検索できるAPI。これでデータを取得する。
仮想環境は、ソフトウェアのライブラリやパッケージの依存関係解いったコンフリクトを避けることができるのメリット。
仮想環境の確認は次のコマンド。
$ conda info -e
# conda environments:
#
base * /home/user/anaconda3
cryptocurrency-analysis /home/user/anaconda3/envs/cryptocurrency-analysis
1.3 Jupyter Notebook
Pythonによる実行結果をブラウザ上で表示できる。起動するためには、jupter notebook
とするとlocalhost上でブラウザから起動できる。
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)
2. Bitcoin価格の取得
データはQuandlのBitcoin APIから取得する。
2.1 データを得るためのHelp関数定義
def get_quandl_data(quandl_id):
''' Quandlの時系列データのキャッシュを取得'''
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
APIから得られたデータをpickleでシリアライズし、ファイルとしてデータを保存する。スクリプトを実行させるたびに同じデータを再ダウンロードするのを防げる。Pandasをデータフレームとしてデータを返す。
下記のpickleの記事がわかりやすい。https://www.lifewithpython.com/2013/05/pickle.html
2.2 Kraken為替レートの取得。
krakenからビットコインのレートを取得することできる。実際に、'BCHARTS/KARKENUSD'としてデータをシリアライズする。
btc_usd_price_kraken = get_quandl_data('BCHARTS/KRAKENUSD')
#Downloading BCHARTS/KRAKENUSD from Quandl
#Cached BCHARTS/KRAKENUSD at BCHARTS-KRAKENUSD.pkl
Pandasのデータフレームなので、head()
を実行すると
In [1] : btc_use_price_kraken.head()
Out[1] :
Open High Low Close Volume (BTC) Volume (Currency) Weighted Price
Date
2014-01-07 874.67040 892.06753 810.00000 810.00000 15.622378 13151.472844 841.835522
2014-01-08 810.00000 899.84281 788.00000 824.98287 19.182756 16097.329584 839.156269
2014-01-09 825.56345 870.00000 807.42084 841.86934 8.158335 6784.249982 831.572913
2014-01-10 839.99000 857.34056 817.00000 857.33056 8.024510 6780.220188 844.938794
2014-01-11 858.20000 918.05471 857.16554 899.84105 18.748285 16698.566929 890.671709
データフレームとして時刻、始値、高値、安値、終値、ボリュームなど得られている。この時系列データをプロットしよう。まずは単純にx軸にはindex (Date), y軸にはWeighted Price値を指定する。
# 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])
2017年付近から2018年7月までのチャート。2017年の時に買って、年末売っていれば億り人でしたね・・・
2.3 他の交換所のビットコインレートを取得する
上記の画像では表示させていないが、Krakenのビットコインはスパイクデータが多数あるため、他の交換所のデータもプルする。取得したデータをデータフレームのカラムに追加して、それらの平均をとっておく。
# 他の交換所のレートを取得する
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):
'''データフレームへ新しいカラムを追加する'''
series_dict = {}
for index in range(len(dataframes)):
series_dict[labels[index]] = dataframes[index][col]
return pd.DataFrame(series_dict)
btc_usd_datasets = merge_dfs_on_column(list(exchange_data.values()), list(exchange_data.keys()), 'Weighted Price')
# 各交換所のビットコインレートの平均をとる。
btc_usd_datasets['avg_btc_price_usd']=btc_usd_datasets.mean(axis=1)
3. アルトコインの価格データを取得する
3.1 Poloniex API
仮想通過のデータを取ってくるために、Poloniex APIを使用する。アルトコインデータを取得のために、このAPIからJSONデータをダウンロードしキャッシュする関数を定義する。初めにURLからJSONデータを得るget_json_data
を定義する。
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 requestsを生成する関数を定義し、続いて、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
3.2 Poloniexから取引データをダウンロードする
ほとんどのアルトコインはドルで直接購入できない。これらのコインを購入するためにはビットコイン建ての必要がある。そのため、それぞれのコインの価格はBTCを用いてUSDへと変換する。
altcoins = ['ETH','LTC','XRP','ETC','STR','DASH','SC','XMR','XEM']
def get_altcoin():
altcoin_data = {}
for altcoin in altcoins:
coinpair = 'BTC_{}'.format(altcoin)
crypto_price_df = get_crypto_data(coinpair)
altcoin_data[altcoin] = crypto_price_df
return(altcoin_data)
3.3 Convert Prices to USD
BTC/ALTの為替レートが得られたので、USD/BTCレートからそれぞれのアルトコインの価格が計算できる。
\text{ALT/USD = ALT/BTC * BTC/USD}
# それぞれのアルトコインのデータフレームへ新しいカラムとしてUSDの価格を計算する
for altcoin in altcoin_data.keys():
altcoin_data[altcoin]['price_usd'] = altcoin_data[altcoin]['weightedAverage'] * btc_usd_datasets['avg_btc_price_usd']
# 単一のデータフレームへ統合する。
combined_df = merge_dfs_on_column(list(altcoin_data.values()), list(altcoin_data.keys()), 'price_usd')
# データフレームへBTC価格を追加
combined_df['BTC'] = btc_usd_datasets['avg_btc_price_usd']
3.4 各通貨の相関解析
ピアソンの相関係数を計算してみる。
combined_df_2018 = combined_df[combined_df.index.year == 2018]
combined_df_2018.pct_change().corr(method='pearson')
2018年度の相関係数を見ると、ほとんど全ての通貨に相関がある。これはヘッジファンドの影響だとか。
3.5 散布図
散布図を見てみると次のようなる。
altcoins = ['ETH','LTC','XRP','ETC','STR','DASH','SC','XMR','XEM', 'BTC']
traced = go.Splom(dimensions=[dict(label=altcoin, values=combined_df_2018[altcoin]) for altcoin in altcoins],
marker=dict(#color=color_vals,
size=5,
#colorscale=pl_colorscaled,
line=dict(width=0.5,
color='rgb(230,230,230)') ),
#text=textd,
diagonal=dict(visible=True))
fig = dict(data=[traced]) #, layout=layout)
py.iplot(fig, filename='large')
上記のように相関係数はほとんどが0.7以上なので、散布図を見ても相関関係があるのが一目でわかる。
4. Your Turn
他の方も試してみてくださいとのこと。アイデアは下記の通り。
-
より仮想通貨を追加して解析してみる。
-
トレンドの時間軸、粒度を変更して相関解析をしてみる。
-
取引量やブロックチェーンマイニングデータセットのトレンドを検索してみる。売/買量の比率は生データよりも将来の変動を予測したいなら関係性がある可能性が高い。
-
株やコモディティなどのデータを追加して、それらと仮想通貨の関係性をみてみる。
-
Event Registry, GDELTやGoogle Trendsを利用して、特定の仮想通貨まわりのバズを量的化してみる。
-
機械学習モデルを利用して明日の価格を予測してみる。もし、より野心があるなら、再帰的ニューラルネットワーク(RNN)を試してみる。
-
例えばPoloniex or CoinbaseのAPIを使って自動化された取引Botを作るために解析を利用してみる。ただし、貧弱に最適化されたbotはお金を直ぐに減らすだけ。
-
発見を共有しよう! ビットコインのベストの部分は、仮想通貨一般として、脱中央主義の特性から他のアセットよりもより自由。解析をオープンソースにして、コミュニティに参加して、ブログに投稿しよう
所感
時系列データの場合は、自己相関をみて自己回帰,移動平均などで解析をしますがどうなんでしょうか。引用元にも記述されていますがRNN, LSTMも試してみたいですね。
時系列解析ですが、prophetを使って解析してみました。ぜひご覧になってください。
ProphetとRで仮想通貨を時系列解析してみた
参考
Analyzing Cryptocurrency Markets Using Python:
https://blog.patricktriest.com/analyzing-cryptocurrencies-python/