最近筆者はUMPCが欲しくなってきている状況ですが、必要性を考えるとiPadとかタブレットで十分だと何度も自分に言い聞かせて我慢しています。まあ、もし買っても結局はHackintoshしたり、Linux入れちゃうと思いますがネ(笑

さて今回の更新はとっても久しぶりなPythonでBitocoinネタ。
本日は久しぶりに100万超えしましたネ。

そんなわけでこちらも以前からストップしてしまったので、研究を進めようということで再度勉強を継続。
これまではbitflyerのAPIを利用してリアルタイムで約定データは取得してMySQLにデータ取り込みするものの、自動売買を実行させるにしても、いつどのタイミングで売買すべきなのか、結局は決めた金額上限での売買を自動化するしかないのか、仮に予測するにしても何に基づいて予測判断すればよいのか、ここの自動化は難しいと思っていました。

が、しかし、予測ライブラリがあるなら話は別ですね、また一歩前進しそうなので実装に取り組んでみました。

環境の準備

まず利用環境はLinux(elementaryOS5.1)
利用するツールはFacebookの開発したfbprophetというpythonのライブラリを使わせてもらいます。
アプリケーションの各バージョンはPython(3.6.9)、fbprophet (0.5)、pandas: 0.25.3、numpy: 1.18.1

アプリケーションのインストールですが、pythonはOSインストール時に導入されますので以下を追加します。

pip3 install fbprophet --user

上記実施時にはfbprophet以外にも必要なモジュールがインストールされますが、plotlyというグラウ画像の出力ライブラリが不足しておりましたので、以下も追加で実行します。

pip3 install plotly

そして検証に使った元データはblockchain.comからCSVを出力ダウンロード。
ファイル名はmarket-price.csvになります。
ファイルの中身は以下のような形式。

2019-11-01 00:00:00,9147.238333333335
2019-11-04 00:00:00,9266.700833333334
2019-11-07 00:00:00,9241.038333333334
2019-11-10 00:00:00,8896.403333333334
2019-11-13 00:00:00,8748.408333333333
2019-11-16 00:00:00,8472.404166666667
2019-11-19 00:00:00,8124.803333333333
2019-11-22 00:00:00,7347.075833333333
2019-11-25 00:00:00,6946.524166666667
2019-11-28 00:00:00,7522.524999999999
2019-12-01 00:00:00,7360.544166666667
2019-12-04 00:00:00,7288.243333333335
2019-12-07 00:00:00,7532.746666666667
2019-12-10 00:00:00,7300.618333333332
2019-12-13 00:00:00,7226.490833333333
2019-12-16 00:00:00,7046.698333333333

参考にしたコードのサンプルデータとデータ形式を合わせるために「00:00:00」の部分だけ除外したかったので、pythonで以下のコードを書いて除外して別ファイルに書き出しました。

(2020/1/21追記:上記のデータのまま、解析が可能でした。最初の1行目に”ds”,”y”を含める必要があります。)

filename = 'market-price.csv'
with open(filename,'r') as f:
        fileText = f.read()
        after = fileText.replace(' 00:00:00','')
        print(after)

上記をfconv.pyというファイル名で保存し、実行します。

python3 fconv.py>bitocoin.csv

すると、以下の形式で出力されます。

"ds","y"
2019-11-01,9147.238333333335
2019-11-04,9266.700833333334
2019-11-07,9241.038333333334
2019-11-10,8896.403333333334
2019-11-13,8748.408333333333
2019-11-16,8472.404166666667
2019-11-19,8124.803333333333
2019-11-22,7347.075833333333
2019-11-25,6946.524166666667
2019-11-28,7522.524999999999
2019-12-01,7360.544166666667
2019-12-04,7288.243333333335
2019-12-07,7532.746666666667
2019-12-10,7300.618333333332
2019-12-13,7226.490833333333
2019-12-16,7046.698333333333

最初の1行目に”ds”,”y”を含めます。

コードの実行編

fbprophetのサンプルや他の方のブログを参考に以下のコードを書いてみました。

import pandas as pd
import numpy as np
from fbprophet import Prophet
#
df = pd.read_csv('bitcoin.csv')
#
df['y'] = np.log1p(df['y'])
m = Prophet()
m.fit(df)

future = m.make_future_dataframe(periods=365)
future.tail()

forecast = m.predict(future)
forecast[['ds','yhat','yhat_lower','yhat_upper']].tail()

m.plot(forecast).savefig('1.png');
m.plot_components(forecast).savefig('2.png');

上記を実行して出力された結果の画像は以下になります。

コードの実行結果

2009年から2019年までのデータを元に2020年の予測は以下になります。

予測ライブラリを実行してみての感想

さてさて、お楽しみの予測としては今後もbitcoinの価値は長期的には微増を継続しそうな予測が出ました。
また別の視点でWeeklyでは一週間のうち金曜が底値になりやすく火曜日が高音になりやすいようですから、火曜に売って金曜に買うと良いかもしれません。
年間を通してみると、10月が底値、7月が高値ということも見えてきましたね。

ただyearyグラフは何やらフォントが一部おかしいですし、他のパラメータも細かいチューニングはまだ必要ですが、基本的な使い方が理解できました。

今後は、リアルタイムで取得したデータサンプルで短期間の予測の自動化実装をしたり、bitcoin以外の他のサンプルデータ(地震情報など)を元に様々な予測をしてみようと思います。

ハマったポイント、その1

サンプルの状態だと「divide by zero encountered in log python」というエラーで実行できませんでした。
そのため、以下のように変更しております。

変更前

df['y'] = np.log(df['y'])

変更後

df['y'] = np.log1p(df['y'])

ハマったポイント、その2

別の環境からリモートでssh接続して実行すると以下のようなエラーが出力されて実行できませんでした。

Gdk-CRITICAL **: 10:24:53.506: gdk_cursor_new_for_display: assertion 'GDK_IS_DISPLAY (display)' failed

上記エラーは出力先のディスプレイ情報が何かしら必要なのではと思いました。
以下コマンドで現在のディスプレイ変数の情報をみると空っぽでした。

echo $DISPLAY

よって以下コマンドを実施してみます。

export DISPLAY=:0

上記後はエラー出力されず、実行完了。無事に問題解決しました。ssh接続の場合は毎回コマンド入力するか、面倒ならば.bashrcなどに記載しておくと良いでしょう。

誰かの参考になることがあれば幸いです。
それでは、Happyハックライフを!!