ディープラーニングでビットコインの価格予想

###やりたいこと
Bitcoinの価格をAIに予測させて金儲けできないものか？


というなんとも不純な動機から

Pythonの深層学習ライブラリのkerasを用いて、RNN(Recurrent Neural Network)、特に、LSTM(Long-Short Term Memory)を実装して、Bitcoinの価格が予測してみます。

###まず、RNNとLSTM　てなに？
まず、RNNとは、deeplearningの一つの手法であり、従来のニューラルネットワークとは異なり、系列データを扱う再帰型のニューラルネットワークです。

音声、言語、動画などの順番に意味のあるデータを扱うことが得意であるとされてる。

LSTMとは、依存関係を学習することのできる、RNNの特別な一種で、長期の時系列を学習可能にしたことが重要な予測モデルである。

詳しく知るには、[こちら](https://qiita.com/KojiOhki/items/89cd7b69a8a6239d67ca)がとても参考になります。

##1.データを用意する
[investing.com](https://www.investing.com/currencies/btc-jpy)さんのデータを利用させていただきました。

登録すれば、csvファイルでデータを得られます。

ありがとうございます!!

##２．データの用意
さあ、コードを書いていきましょう。

データの用意で楽したので、使わないデータもきれいにします。

先ほどいただいたCSVファイルはカレントディレクトリに置きました。

padasを用いて操作します。

```python

from sklearn.preprocessing import scale
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
#jupyter上で表示するためのおまじない
%matplotlib inline

#csvファイルを読み込む
price_df = pd.read_csv('BTC_JPY.csv')

#不要な行を削除し、逆順に並び替える
price_df = price_df.sort_index(ascending=False)[2::]

#datetimeオブジェクトに変換
price_df['日付け'] = pd.to_datetime(price_df['日付け'], format='%Y年%m月%d日')

#コンマを削除して、int型に変換、標準化処理
size = price_df.shape
for i in ['終値', '始値', '高値', '安値']:
    price_df[i] = price_df[i].apply(lambda x: x.replace(',','')).astype(int)
    price_df[i] = scale(price_df[i])

#出来高のKを削除、1000倍、標準化
price_df['出来高'] = price_df['出来高'].apply(lambda x : x.replace('K','')).astype(float)
price_df['出来高'] = price_df['出来高'] * 1000
price_df['出来高'] = scale(price_df['出来高'])

#float型に変換
price_df['前日比%'] = price_df['前日比%'].astype(float)

#index番号をつけなおす
price_df = price_df.reset_index(drop=True)
```

ここまでで、DataFrameをきれいにしたところで、学習に使えるように整形していきます。
LSTMの入力データは3次元であることが要求されるので定義した関数で要求が満たされるように注意します。

```python

def load_data(data, n_prev):
    X, y = [], []
    for i in range(len(data) - n_prev):
    　#7日分ひとまとまりのデータを作る
        X.append(data.iloc[i:(i+n_prev)].as_matrix())
        y.append(data.iloc[i+n_prev].as_matrix())
    arr_X= np.array(X)
    arr_y= np.array(y)
    return arr_X, arr_y

#古い順に８割を学習データに使う
split_pos = int(size[0] * 0.8)

#2014-09-17から2017-07-11までがtrain用
X_train, y_train = load_data(price_df[['終値', '出来高']].iloc[0:split_pos], length_of_sequences)

#2017-07-12から2018-02-10までがtest用
X_test, y_test = load_data(price_df[['終値', '出来高']].iloc[split_pos:], length_of_sequences)
```

##3．モデルを作成し、学習する
予測したい日までの1週間分のデータを用いて価格を予想するようなモデルを設計します。
また、終値と出来高の2つの要素を通して学習できるようにしています。
最初の入力層では入力データの形式が求められるので、必ず指定してあげましょう。

```python

from keras.models import Sequential
from keras.layers.core import Dense, Activation
from keras.layers.recurrent import LSTM

#一日単位のデータを使うので、
#何日分のデータを振り返って学習するか
#１週間分=7日にしてみる
length_of_sequences = 7
#学習データの要素数
in_out_neurons = 2
#隠れ層の数
hidden_neurons = 300

#モデルの定義
model = Sequential()

model.add(LSTM(hidden_neurons,
batch_input_shape=(None, length_of_sequences,
in_out_neurons), return_sequences=False))

model.add(Dense(in_out_neurons))
model.add(Activation("linear"))
model.compile(loss="mape", optimizer="adam")

model.fit(X_train, y_train, batch_size=10, nb_epoch=100)
```

##４．モデルから予測し、出力を得る
実際のデータが赤、予測値が青になって表示されるように指定してあげます。
軸の値に関しては、うまく設定できませんでした。勉強しておきます!!

```python

#あらかじめ分けておいたデータを用いて予測します
predicted = model.predict(X_test)

y_test = pd.DataFrame(y_test)[0]
result = pd.DataFrame(predicted)

#表示するためのコード
plt.plot(y_test, c='r')
plt.plot(result[0], c='b')
plt.title('BTC/JPY')
plt.xlabel('Day')
plt.ylabel('Price')
plt.legend(['actual', 'predict'])
plt.show()
```

出力結果として以下のように得られました。

2017-07-12から2018-02-10の期間の予測結果(青)と実際の価格(赤)です。

![2.png](https://qiita-image-store.s3.amazonaws.com/0/203921/1a8410ca-1d01-ff98-bd84-bf366d8a1a9c.png)


推移に関してはおおむねあっているように見えますが、誤差はありますね...
お金儲け!!　は無理そう...


##5．考察
上記の結果から本当に推移が正確なのか見てみようと思います。
前日の価格と比べて上がっているか、下がっているかだけでもあっていれば、使えるのでは？
ということで以下のコードで前日比の上下の整合性を確かめます。

```python

#空のリストを作成
y_list = []
re_list = []

#上がったら1, 下がったら0を代入
for i in range(len(result[0]) - 1):
    if i == 0:
        continue
    if y_test[i - 1] < y_test[i]:
　    y_list.append(1)
　else:
　　y_list.append(0)

　if X_test[i][0][0] < result[0][i]:
        re_list.append(1)
    else:
        re_list.append(0)

num = 0

for k, v in zip(y_list, re_list):
    if k == v:
        num += 1
score = num / len(y_list)

print(score)

```

結果は、0.53.....

前日比上下の正答率は53%




ダメじゃん 
ってことで、世の中そんなに甘くない!!!

しかし、機械学習を用いた自動取引ツールを開発している方も多いようなので、精度が高められるように勉強していきます。