【Python】機械学習でビットコインの価格を予測する②

この記事は約9分で読めます。

 

 

前回の記事

 

 

 

今回も引き続き機械学習を行っていきます。

 

 

<実行環境>

  • Windows10
  • Python3.6
  • Jupyter Notebook

 

#ライブラリの読み込み
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
import pandas as pd
import time
import requests
import json
from datetime import datetime

def get_btcprice(ticker,max):
    url = ('https://api.coingecko.com/api/v3/coins/')+ticker+('/market_chart?vs_currency=jpy&days=')+max
    r = requests.get(url)
    r2 = json.loads(r.text)
    return r2


# jsonから価格データだけをPandasに変換して抽出する
def get_price(r2):
    s = pd.DataFrame(r2['prices'])
    s.columns = ['date', 'price']
    date = []
    for i in s['date']:
        tsdate = int(i / 1000)
        loc = datetime.utcfromtimestamp(tsdate)
        date.append(loc)
    s.index = date
    del s['date']
    return s


# ビットコインの全期間の価格データを取得する
r2 = get_btcprice('bitcoin', 'max')
btc = get_price(r2)

# 変化率の計算
change = btc['price'].pct_chnage()

 

 

機械学習のもとになるビットコインのデータはCoingeckoというビットコイン価格サイトからAPI経由で取得しています。APIの使い方は下記参照。

 

関連記事:【Python】CoinGeckoのAPIからビットコイン・アルトコインの価格データを取得する

 

 

価格データが取得できたら次はtalibというライブラリを使用してテクニカル指標を計算します。

 

# talibでテクニカル指標を計算する
import talib
price = btc['price']
momentam = round(talib.MOM(price, 5), 0)
macd = talib.MACD(price)
rsi = round(talib.RSI(price, timeperiod=7), 0)

 

※talibについては↓の記事で解説しています。

関連記事:【Python】テクニカル指標が簡単に計算できるTa-libの使い方

 

talibは少し癖があるので、インストールできないという人は計算式をPythonで実装してテクニカル指標を計算する必要があります。

 

関連記事:Pythonで移動平均(SMA)と指数移動平均(EMA)を計算する

 

 

テクニカル指標が計算出来たら、次はそのデータを扱いやすいようにデータフレームに格納します。

 

# 各データをつなぎ合わせてデータフレームを作成
df = pd.DataFrame({"date":btc.index, "price":change, "mom":momentam, "macd":round(macd[2], 0), "rsi":rsi})

 

 

そして、前日(t)の各テクニカル指標と翌日(t+1)のビットコインの価格変化率をスライスで同じ行に合わせていきます。

 

またAIが学習しやすいように変化率を0以上(価格上がった時)を1、変化率が0以下(価格が下がった時)を0と置き換えます。オサレに言い換えるとと「アノテーション」という作業です。

 

 

# 説明変数xと被説明変数yを決める
y = df['price'][35:]
x = df[['rsi', 'mom', 'macd']][34:-1]

# xとyの要素数が同じかを確認
print(len(x), len(y))

# 変化率を1と0のシグナルに変換する
signal = []
for i in y:
    if i > 0:
        signal.append(1)
    elif i < 0:
        signal.append(-1)

 

 

前回はここまででしたが、今回は精度をさらに上げるため、テクニカル指標の値も一定の閥値を境に1と-1に変換しておきます。

 

 

# macd momentumが0以上ならば1, 0以下ならば0に置き換える

x.loc[df['macd'] < 0, 'macd'] = -1
x.loc[df['macd'] >= 0, 'macd'] = 1
x.loc[df['mom'] < 0, 'mom'] = -1
x.loc[df['mom'] >= 0, 'mom'] = 1
x.loc[df['rsi'] < 50, 'rsi'] = -1
x.loc[df['rsi'] >= 50, 'rsi'] = 1

# データの確認
print(x.head())

 

 

次はScilit-learnの仕様に合わせてデータの次元を変換しておきます、アルゴリズムの実装を除けば、恐らくここが一番の難所。

 

 

# 機械学習用に次元を変換する
y2 = np.array(signal).reshape(-1,)

# xとyの要素数が同じか再確認
print(len(x), len(y2))

#データを9:1に分割する 
import sklearn 
from sklearn.model_selection import train_test_split
(X_train, X_test,y_train, y_test) = train_test_split(x, y2, test_size=0.1, random_state=0,shuffle=False)

print(X_train)


 

train_test_spilit の引数部分のrandom_state=0,shuffle=Falseは絶対に必要。これがないとデータセットの並びがぐちゃぐちゃになるので、並びに意味のある時系列データの機械学習の場合はこの設定が必須です。

 

ここからアルゴリズムにデータを読み込ませます。

今回はまず決定木を使います。

 

 

ライブラリの読み込み&クラス呼び出し&インスタンスの生成
from sklearn import tree
clf = tree.DecisionTreeClassifier(max_depth=5)

# 学習開始!
clf = clf.fit(X_train.values, y_train)

#作成した機械学習モデルをテストデータに当てはめる
predicted = clf.predict(X_test)

# モデルのテストデータに対する精度を確認
score = sum(predicted == y_test) / len(y_test)
print('モデルの精度は{}%です'.format(score * 100))


 

これでデータの機械学習は完了です。

 

スポンサーリンク

決定木を可視化する

 

一応決定木なので、アルゴリズムが何をもっと1と0を分類しているのか図にして可視化してみます。決定木の可視化はpydotplusまたはgraphvizが便利です

 

 

# 決定木を画像にして出力する
import pydotplus
from sklearn.externals.six import StringIO
from IPython.display import Image

dot_data = StringIO() 

# graphviz ver
tree.export_graphviz(clf, out_file=dot_data,feature_names=df.columns[-3:],) 

# pydotplus ver
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
Image(graph.create_png())

 

※実行結果

モデルの精度は60.775862068965516%です

 

 

 

今回の精度は61.63%(2019年10月時点)と前回より10%近く上昇しました。説明変数を1と0の2値に変換したのが効いているようです。

 

 

累積収益率の計算

 

今回は価格データなので、データの正解率だけではなく、その予測従って実際に取引した場合とホールドしていた場合と比較して有用性があるのかを検証します。

 

具体的には、最初に算出した変化率と[1・-1]の入ったAIの予測結果を掛け算し、.cumprod()で累積変化率(累積収益率)を計算します。

 

# 予測データの長さを計算する
length = len(predicted)

# 機械学習の予測結果に従ってトレードした場合のリターンを計算する
ai_return = (y[-length:] * predicted + 1).cumprod()

# 同じ期間ホールドしていた場合のリターンを計算する
hold_return = (y[-length:] + 1).cumprod()

# 各累積収益率をプロットする
ai_return.plot(label='ai_trade', legend=True)
hold_return.plot(label='hold', legend=True)

 

 

 

 

対して変わんねぇ・・・というオチでした。次はビットコインではなく日経やイーサリアムやリップルなどのアルトコインを題材にしてやっていきます。

 

 

 

 

 

関連記事:Pythonでディープラーニングを勉強するのにオススメな参考書3選

 

関連記事:【自動取引】トレード戦略のバックテスト①~MACDとモメンタムの併用

 

 

コメント

タイトルとURLをコピーしました