ファイナンス機械学習 ラベリング:練習問題 E-mini S&P 500にトリプルバリアを適用する

金融データ構造の記事と同じくE-mini S&P500の2009年以降のティックデータを使い、ドルバーを構築する

import pandas as pd
import numpy as np
from datetime import datetime

import Bars as bars

  金融データ構造で作成したコードをBars.pyにまとめて、コードにインポートしている。
 ティックデータの読み込みでは、分割注文による同時取引を取引高を足し合わせ、重複をなくした。

SP_data = pd.read_csv('SP.csv')
SP_data = SP_data[SP_data['volume'] > 0]
SP_data['datetime'] = SP_data['date'] + "/" + SP_data['time']
SP_data['datetime'] = SP_data['datetime'].apply(lambda dt: datetime.strptime(dt, '%m/%d/%Y/%H:%M:%S.%f'))
SP_data=SP_data[SP_data['datetime'] >= datetime(2009, 1, 1)]
SP_data.index=SP_data['datetime']
SP_data.drop(['date','time'],axis=1, inplace=True)
SP_data.drop(['datetime'],axis=1, inplace=True)
SP_data['volume']=SP_data.groupby(SP_data.index)['volume'].sum()
SP_data = SP_data[~SP_data.index.duplicated(keep='first')]

dv=200_000
ddf=bars.getDollarBars(SP_data,dv)

閾値が日次収益の標準偏差な対称CUSUMフィルターを、このドルバーに適用し、垂直バリアを保有期間1日として、垂直バリアに触れた時間t1を加える。日次収益標準偏差のEWMのウィンドウは20とした。

span0=20
daily_vol=getDailyVol(ddf['Close'],span0)
h=daily_vol.mean()
ddf_rtn = ddf['Close'].pct_change().dropna()
events=bars.getTEvents(ddf_rtn.loc[daily_vol.index[0]:], h)  #CUSUM
t1 = addVerticalBarrier(ddf['Close'], events, numDays=1)

サイドが未知な状態であるため、利食いと損切りを対称に$${[1,1]}$$にとり、トリプルバリア法を適用する。

ptsl=1.0
minRet=0.0005 # minimal return to apply triple barrier
close=ddf['Close']
TPevents=getEventsML(close,events,[ptsl,ptsl],daily_vol,minRet,t1=t1,side=None)
TPevents

この結果にgetBinを適用し、どのバリアに触れたかをラベリングする。

labels=getBinsTUML(TPevents,close,t1)
print(labels.bin.value_counts())


垂直バリアに触れた(保有期間中に上下バリアに触れない)イベント件数が2004、損切りバリアに触れたイベントが561件、利食いバリアに触れたイベントが575件ある。
このラベリングの結果から、出現回数の少ないラベルを排除する。

def dropLabels(events, minPct=.05):
    # apply weights, drop labels with insufficient examples
    while True:
        df0=events['bin'].value_counts(normalize=True)
        if df0.min()>minPct or df0.shape[0]<3:break
        print('dropped label: ', df0.argmin(),df0.min())
        events=events[events['bin']!=df0.argmin()]
    return events

clean_labels = dropLabels(labels)
print(clean_labels.bin.value_counts())

ここでは、出現頻度の少なさで落とされるラベルはないが、ドルバーの閾値によっては、落とされるラベルも出てくる。
この操作は、機械学習分類器にとって、分析対象のクラスが過度に不均衡であるとうまく機能できないからであり、滅多に現れないケースよりも、出現頻度の高いケースに限った方が学習がしやすいからである。
 

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