見出し画像

[MLbot] 特徴量の定常性を確認するADF検定のコードメモ

こんにちは、仮想通貨の機械学習bot (通称MLbot) を作成しているmizuomochiと申します。機械学習には必須の特徴量の加工について、私が始めたての時に躓いた点を残しておこうと思います。

Richmanbtcさんのチュートリアルでも言及されているとおり、仮想通貨の機械学習bot (通称MLbot)では、特徴量の定常性が重要になります。

本記事は特徴量の定常性を確認する方法としてよく用いられる、拡張ディッキーフラー検定 (ADF検定) のコードメモになります。

ちなみに、ADF検定は「データ系列に単位根が存在する」を帰無仮説とする検定で、厳密には「帰無仮説を棄却:単位根が存在するとはいえない」=「定常性がある」ではありません。
しかし、価格系列においては両者はイコールで扱われることが多いため、このあたりの議論は割愛します。

例としてtimeperiod=5における終値の単純移動平均と、移動平均乖離率の定常性を調べてみます。
データセットはBTC/JPY (2018.10~2022.07) の価格系列を使用しています。


import pandas as pd
from tqdm import tqdm
from statsmodels.tsa.stattools import adfuller
pd.set_option('display.min_rows', 100)

# ADF検定
def apply_ADF(df, features):
    df = df.dropna(how='any')
    res = []
    for i in tqdm( range(len(features)) ):
        adf = adfuller( df[features[i]] )
        print("特徴量:{0}, ADF統計量:{1}, p-values:{2}, ラグ数{3}, データ数{4}, 棄却域{5}, AIC値{6}".format( features[i], adf[0], adf[1], adf[2], adf[3], adf[4], adf[5] ))
        res.append( [features[i], adf[0], adf[1], adf[2], adf[3], adf[4], adf[5]] )
    
    dfRes = pd.DataFrame(res)
    dfRes.columns = ['feature', 'ADF statistic', 'p-value', 'usedlag', 'data', 'critical value', 'AIC']
    dfRes = dfRes.reset_index(drop=True)
    dfRes = dfRes.sort_values('p-value')
    dfRes.to_csv("ADF_result.csv") # csvに結果を出力

# 使用するohlcvデータ
df = pd.read_csv( "my_ohlcv.csv", float_precision="high" )

# 特徴量
features = [
    "SMA_5", # 移動平均
    "SMA_5_ratio", # 移動平均乖離
]

# 特徴量の計算
def calc_features(df):
    df["SMA_5"] = df["close"].rolling(5).mean() # 移動平均
    df["SMA_5_ratio"] = ( df["close"]-df["SMA_5"] ) / df["SMA_5"] # 移動平均乖離
    return df

df = calc_features(df)

apply_ADF(df, features)

結果は以下のようになりました。

上が単純移動平均、下が移動平均乖離率のADF検定結果

p-values=0.05を基準とすると、単純移動平均は定常性が無く、乖離率は定常性が認められました。

試しに両者をプロットしてみます。

import matplotlib.pyplot as plt

# plot
plt.figure(figsize=(10, 5))
df["SMA_5"].plot(label='SMA_5')
plt.title("SMA_5", fontname="MS Gothic")
plt.legend(bbox_to_anchor=(1.05, 1))
plt.show()

plt.figure(figsize=(10, 5))
df["SMA_5_ratio"].plot(label="SMA_5_ratio")
plt.title("SMA_5_ratio", fontname="MS Gothic")
plt.legend(bbox_to_anchor=(1.05, 1))
plt.show()
←単純移動平均、→乖離率

移動平均乖離率は全期間において、0を中心とした分布になっていることが分かります。

基本的に無次元数の特徴量であれば定常性を持つことが多いとは思いますが、モデルの作成に移る前に定常性をチェックしてみるとよいかもしれません。

この記事が気に入ったらサポートをしてみませんか?