プロクラシスト

今日の寄り道 明日の近道

【Day-22】データ分析技術で仮想通貨の暴騰・暴落を捉えられるか


スポンサーリンク

f:id:imslotter:20171222012923p:plain

データ分析ガチ勉強アドベントカレンダー 22日目。

今日は、データ分析の練習も兼ねて、ちょっとした実験!! 対象は最近話題の仮想通貨。 乱高下の激しい通貨に対して、データ分析技術がどこまで通用するかと言うのを検証してみる。

使う技術 : Change Finder

change finder とは、データマイニングによる異常検知に出てくる、変化検知の技術。

ざっくりいうと、データをある時系列モデルで予測し、そこからの変化具合を評価する手法

全体の流れ

  1. 窓幅kで時系列モデル(ARモデル)を用意してSDARアルゴリズム(忘却型学習アルゴリズム)で学習する
  2. 上記の時系列モデルp_{t-1}に対して、時刻tでの異常値スコアを次のように算出
    • Score(x_{t})=-\ln{p_{t-1}(x_{t}})
    • もしくはヘリンジャースコア(参考)
  3. 幅Tのウィンドウを設けて、スコアの平均を計算する(smoothing)
  4. 平滑化された時系列データy_{t}に対して、再度ARモデルを用意してSDARアルゴリズムで学習する
    • 時刻t-kからt-1までの値で、それ以降の時系列を予測するモデルq_{t}が完成する
    • T'のウィンドウを設けて、スコアの平均を計算する(下式)
    • Score(x_{t})= \frac{1}{T'}\sum_{i=t-T'+1}^{t}\left(-\ln{q_{t-1}(y_{t}})\right)

ポイントは、2回学習しているところ。一回目のsmoothingで、ノイズに反応した外れ値の除去を行っている。 そのため、本質的な変動を捉えられるようになっている。

SDARで設定する忘却パラメータはかなり大事で、どのくらい過去の影響を重視するかに関わってくる。これについては後で見てみる。

ライブラリ

何気なく「changefinder python」で調べると、作っている素晴らしい人がいた。

changefinder - Argmax.jp

なので拝借。上記ページにも書かれているように、numpy, scipy, nose, statsmodelsは必要

pip install changefinder

で入る。二種類のアルゴリズムが用意されていて、通常のChangeFinderと、ARモデルをARIMAモデルに変更したChangeFinderARIMA *1

ChangeFinder

changefinder.ChangeFinder(r=0.5,order=1, smooth=7)

主要パラメータは下記の通り

  • r : 忘却パラメータ
  • smooth : 外れ値スコアをsmoothingするための区間
  • order : 時系列モデルの次数

実験に使うデータ

  • 12/13-12/21の仮想通貨の価格データ ((githubcoindata.csvに保管している))
  • 草コインも含めて868銘柄のデータを10分おきに保管している

データの集め方については以前記事にしたAPIを使っている。

コード

詳しくは、githubに上げている。 github.com

銘柄を指定し、changefinderにかけてグラフ表示するまで

コードをみる
%matplotlib inline
import changefinder
import pandas as pd 
from datetime import datetime as dt
import matplotlib.pyplot as plt
import numpy as np
import os


def str2datetime(tstr):
    if tstr.__class__.__name__ == "datetime":
        return tstr
    ts = tstr.split(".")[0]
    return dt.strptime(ts, "%Y-%m-%d %H:%M:%S")

def calc_cf(name, df, cf, threshold=30):
    values = df[name].values
    scores = np.array([cf.update(value) for value in values])
    print(scores)
    # 描画
    fig, ax1 = plt.subplots(figsize=(15,5))
    ax1.set_title(name)
    ax1.plot(df.index, scores,color="red")
    ax1.set_ylabel("anom_score")
    ax2 = ax1.twinx()  # 2つのプロットを関連付ける
    ax2.plot(df.index, df[name].values)
    ax2.set_ylabel("value")
    # しきい値越えリスト
    df["score"] = scores - threshold
    for i in range(1,len(df)):
        if df.iloc[i-1]["score"] < 0 and df.iloc[i]["score"] >= 0:
            print("time:{}".format(df.iloc[i]["timestamp"]))
            ax2.plot(df.index[i],df.iloc[i][name],"o")
    plt.show()
    return df

cf = changefinder.ChangeFinder(r=0.01, order=1, smooth=3)
df = pd.read_csv("coindata.csv").dropna()
df.index = df.timestamp.apply(str2datetime)
calc_cf(name="btc",df=df, cf=cf, threshold=15)

実行結果

r=0.01, order=1, smooth=3 で実行してみた。結果がコチラ

ふむ、一見よく捉えられているようにも見える。 でも、実際はそんなに簡単じゃない

パラメータによる違い。

r=0.01, 0.02, r=0.05で試してみる。結果は↓

r グラフ
0.01
0.02
0.05

忘却パラメータに関しては、与えるパラメータによってかなり変わってくる。 センシティブなので、ナゾの場所で変化検知する場合もあり、シビアな調整が必要そうだ。

また、r=0.01, order=1は固定で、smoothを3と18で比べてみた。

smoothing グラフ
3
18

やはり平滑化をしすぎると、反応は遅れるのだなという感じ。しかし、結構変化に敏感に反応はできているという印象を受けた。

注意したいのが、グラフの縦軸は全然値が変わっているところ。この辺のしきい値の調整もシビアそう。

結論

暴騰暴落を捉えられたか?

  • 正直微妙
  • ピークが捉えられたとして、少し反応が遅れると暴落に飲み込まれる
  • 後述するパラメータ調整がシビアすぎる印象

って感じ。正直、強いトレンドを見るならボリンジャーバンドでいいのでは?って思った。 そう思って、ボリンジャーバンドでもトレンド検知をしてみた。結果がこれ(赤が買いトレンド、青が売りトレンド)

若干ミスってはいるものの、トレンドを割と追従できてる気がする。真ん中の2点は要らないけど、超安定してたから仕方ない気もする。sigmaの絶対値でしきい値設ければ弾けそう。 これもパラメータ調整が難儀ではあるが、changefinderよりも直感的になので、やりやすそう。

モデルに関して

  • 特に忘却係数の調整がシビア
  • 基本的に反応は早めだが、smoothing次第で遅れる。ノイズとの兼ね合い
  • スコアもパラメータによって変わるので、相対的な判断が強いられる

あたりが難しそうだなと思ったところ。探索的に調べたが、なかなか直感にバシッと合うようなものは見つけられなかった。 パラメータの調整方法としては、Day15で書いたベイズ的最適化を使ってやってみるのも面白いと思うので、もうちょっと良いパラメータを見つけたいトコロ。

*1:ARIMAは計算が重い&非定常な時系列に対して時間窓を区切ってARIMAモデルを独立に作成しているので、モデルの妥当性は不明とのこと。

PROCRASIST