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

前回の記事

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

<実行環境>

  • 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とモメンタムの併用

プログラミングの独学はとても難しい


プログラミングは小学校の義務教育にも導入され始めており、これから社会人として生きていく上でプログラミングはもはや出来て当たり前、出来なれば論外というエクセルレベルの必須スキルになりつつあります。そしてそういう話を聞いて参考書なりを購入して独学でプログラミング勉強しようと思っている人も少なくないでしょう。しかしプログラミングを独学で勉強し始めようと思うものの



・「分からない箇所で詰まって挫折してしまった」

・「勉強する時間が足りない」

・「ネットの記事だと情報が断片的でよくわからない」

・「コードのエラーの原因が分からない」



という壁にぶち当たって、プログラミングの勉強を止めてしまう方が少なくありません。独学でプログラミングを勉強してる時間のほとんどはつまづいている時間です。実際僕も最初のころ独学でプログラミングを勉強していた頃はエラーの原因が分からず丸1日を不意にしてしまった・・・そんな苦い経験がありました。それで僕は一度はプログラミングの学習を諦めてしまいましたが、就活で現実を知る中で



「プログラミングを勉強して、いずれフリーランスとして自由な生き方がしたい」

「エンジニアとして若いうちから高収入を得たい」



という強い気持ちから一念発起して「侍エンジニアのwebサービスコース」に申し込み、プロのエンジニアの方に対面でマンツーマンでPythonによるWebサービス作り方とWeb技術の基本を教えてもらい、ようやくプログラミングが理解でき、今ではエンジニアとしてそこそこの暮らしができるようになりました。





侍エンジニアでは、とりあえずプログラミングやインターネットの基本を知っておきたい人から、HTML・cssなどでWebサイトやWebアプリを作ってみたい人やPythonを勉強してデータサイエンティストやAIエンジニアになりたい人まで幅広いニーズに応えた様々なコースが用意されています。



IT業界と言ってもエンジニアの仕事はプログラミング言語次第でサーバーから機械学習・ディープラーニングまで多種多様ですし、侍エンジニアの無料レッスン(カウンセリング)を受けてみて、自分のやりたいITの仕事は何なのか?を見つけるのがエンジニアへの第一歩になります。ちなみに今侍エンジニアの無料レッスンを受けると1000円分のAmazonギフト券がもらえるので、試しに受けてみるだけもお得です。


自分は半端に独学やオンラインスクールで勉強して金と時間を無駄にするくらいなら、リアルのプログラミングスクールに通ってしっかりプログラミングを勉強した方がいいと思います。ちなみに今、侍エンジニアに申し込むと、25歳以下の学生の方であれば、受講料が20%OFFになるので超お得です。


そして、プログラミングは大勢で授業を受けたり漫然とオンライン学習をするよりも自分が分からない箇所をピンポイントでプロの講師に直接質問して、ちゃんと納得するというスタイルの方がお金は確かに少し掛かりますが、独学で学ぶよりも絶対にモノになります。


シェアする

  • このエントリーをはてなブックマークに追加

フォローする

   侍エンジニア塾       
侍エンジニアの無料体験レッスンを予約する -->