今回はビットコインの価格を
予測してみたいと思います。

解説動画はこちら



さてここからはGoogleColaboratoryを使って
コードを実行していきましょう。

データをダウンロードする

最初はビットコインの価格データの
ダウンロードからです。

ビットコインの価格データは
ここにあります。
ダウンロードはここ
csvファイル名は bitflyerJPY.csv.gz


colab上で実行する場合は
!wget --no-check-certificate https://api.bitcoincharts.com/v1/csv/bitflyerJPY.csv.gz
これでファイルがダウンロードされ
デフォルトのフォルダに置かれます。


データを見てみる

次はライブラリの読み込みです。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import plotly
import plotly.graph_objects as go
%matplotlib inline
早速データを読み込んでみましょう。

データフレームの作成
df = pd.read_csv('bitflyerJPY.csv.gz')
df.columns = ['datetime', 'price', 'amount']
データ量が多いので時間が掛かります。

データ量を見てみると
df.shape
(63655790, 3)
非常に多いことがわかると思います。

データはこんな形になっています。
df.head()
datetimepriceamount
01499155298296016.00.600000
11499155299296016.00.018600
21499155302296550.00.050000
31499155310296558.00.050000
41499155319296539.00.229197


日付、価格、取引量
というデータの様ですが
日付がUnixTimeStampなので
分かる形になおします。


Unixtimestampを日付に直す
df['datetime'] = pd.to_datetime(df['datetime'],unit='s')
インデックスをdatatimeindexに直す
df = df.set_index('datetime')
df.tail()
priceamount
datetime
2021-03-20 01:10:136385001.00.06000
2021-03-20 01:10:176386760.00.00101
2021-03-20 01:10:176386760.00.00499
2021-03-20 01:10:176386101.00.00100
2021-03-20 01:10:206389000.00.00100

これで見える様になりましたね。
20210320のデータまでありました。
データは秒単位で入っている様ですね。


直近のデータを可視化してみましょう。
matplotlibで終わりの1万行分を
可視化してみます。


matplotlibで可視化
plt.figure(figsize=(10,6))
df['price'].tail(10000).plot()
plt.show()
download

数時間分のデータですが
かなりの値動きがあることが分かります。


plotlyを使って可視化する

ここからはplotlyを使って
もっと細かく見ていきましょう。

plotlyでローソク足を表示させてみましょう。
データとしては
初値、高値、安値、終値
この4つが必要です。

pandasで簡単に集計できます。

resampleで集計間隔を決め
ohlcで四本値を計算できます。


日別の4本値に集計する
data=df['price'].resample('1D').ohlc()
可視化
fig = go.Figure(
         data= [go.Candlestick(
                   x = data.index, 
                   open=data['open'],
                   high=data['high'],
                   low=data['low'],
                   close=data['close'])
         ]
)
fig.show()
スクリーンショット 2021-03-20 16.25.16
plotlyはグリグリ動かせるので
ズームしたりして色々遊べます。

これでみると2017年くらいからのデータで
2019年あたりに欠損があるようです。





予測モデルを作ってみる

ここからは予測モデルを作っていきましょう。
今回使用するのはFaceBookの
Prophetというライブラリで
時系列データの予測を行うことができます。


FacebookProphetライブラリの読み込み
from fbprophet import Prophet
import warnings
warnings.simplefilter('ignore')


学習用のデータを作成します。
学習には予測値(y)と日付(ds)という
2列分のデータが必要です。

ここでは終値をyに日付をdsに
置き換えて学習データを作成しています。


予測用の学習データの用意
model_df = data[['close']].tail(365)
model_df = model_df.reset_index()
model_df = model_df.rename(columns={'datetime':'ds','close':'y'})
model_df.head()
dsy
02020-03-21688958.0
12020-03-22647262.0
22020-03-23719267.0
32020-03-24752500.0
42020-03-25741720.0



これで準備できました。
学習は簡単に行えます。

予測モデルの学習
model = Prophet()
model.fit(model_df)

予測は何日先まで予測するかの
数値を入れてあげるだけです。

ここでは7日先までを予測します。

予測と可視化
future_df = model.make_future_dataframe(7)
forecast = model.predict(future_df)
model.plot(forecast)
downloadのコピー

はい
結果が出ました。

1年分のデータを用いての予測は
上昇傾向が続くという結果のようです。

予測結果の部分をみてみましょう。


予測結果
forecast_df = forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']]
forecast_df = forecast_df.set_index('ds')
forecast_df.tail()
yhatyhat_loweryhat_upper
ds
2021-03-236.375499e+066.065328e+066.667189e+06
2021-03-246.443882e+066.149507e+066.721009e+06
2021-03-256.480789e+066.192598e+066.773611e+06
2021-03-266.522106e+066.250351e+066.805741e+06
2021-03-276.572089e+066.278178e+066.857975e+06

ここを可視化してみます。

forecast_df.tail(10).plot()
plt.show()
download

yhatが予測値
upperとlowerが上限下限です。

だいたいこの間に収まるだろうという予測です。

1年という長い期間を用いた場合は
上昇傾向が続く形になりました。

もっと短い期間ではどうでしょうか?
次は1ヶ月でやってみましょう。

予測用のデータの日数を
変えるだけです。


過去30日から次の日の価格を予想する
# 過去30日の値から次の日を予想する
model_df = data[['close']].tail(30)
model_df = model_df.reset_index()
model_df = model_df.rename(columns={'datetime':'ds','close':'y'})
model = Prophet()
model.fit(model_df)
future_df = model.make_future_dataframe(1)
forecast = model.predict(future_df)
model.plot(forecast)
download-2

最初落ち込みが激しいですが
これも上昇傾向ですね。

7日だとどうでしょうか?
download-1
これもやや上昇傾向にあるように思えます。




まとめ

トレンドが続くものとした予測であれば
良さそうな感じです。

ただしこれは参考値にしかなりません。

トレンドの変化があるところでの
予測は難しいと思うので
短い期間で学習、予測という形で
価格を予想する際の参考に
していただければと思います。

今回はこれまでです
それでは。