アセットマネージャーのためのファイナンス機械学習:金融データのラベリング 練習問題 固定ホライズン法
E-mini S&P 500先物時系列から、固定ホライズン法を用いて1分のタイムバーでラベルを作成する。閾値の$${\tau}$$は1分間リターンの標準偏差の2倍とする。
ファイナンス機械学習のバーとラベリングのコード、Labels, Barsをインポートする。
import pandas as pd
import numpy as np
from datetime import datetime
import Labels as labels
import Bars as bars
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import confusion_matrix
from sklearn.metrics import roc_curve,auc
from sklearn.metrics import classification_report
import matplotlib.pyplot as plt
%matplotlib inline
S&Pのティックデータを読み込む。
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')]
固定時間バーを作成し、一分毎のリターンの分散の2倍を閾値とし、ラベリングする。
Hbar=bars.getTBars(SP_data,'Min')
Hbar['RTN']=Hbar['Close'].pct_change().dropna()
Hbar=Hbar.dropna()
thred=2.*Hbar['RTN'].std()
low=Hbar[Hbar['RTN'] < -thred].index
high=Hbar[Hbar['RTN'] > thred].index
stable=Hbar[np.abs(Hbar['RTN']) < thred].index
Hbar.loc[low, 'FxLbl'] = -1
Hbar.loc[stable, 'FxLbl'] = 0
Hbar.loc[high, 'FxLbl'] = 1
このラベルの全体での割合は次のとおり。
一日の1時間毎のラベルの分布のグラフを描く。
H_Hours=Hbar.groupby(pd.Grouper(level=0, freq='H'))['FxLbl'].value_counts(normalize=True).unstack()
H_Hours.columns=['Down','Stable','UP']
H_Hours['Time']=H_Hours.index.time
H_Hours.index=H_Hours.index.date
H_hours=H_Hours.groupby(by=["Time"]).mean()
H_hours.plot.bar(width=1.0,ylabel='the average percentage of labels')
UPとDOWNのラベリングは、マーケットが開いている時間の九時から大きくなり、2時にはピークが来ていることがわかる。
同じことを、リターン原列ではなく、1時間前の分散で標準化されたリターンについて行い、ラベリングの分布を見る。
from datetime import timedelta
groups = Hbar.groupby(pd.Grouper(level=0, freq='H'))['RTN']
mean = groups.transform("mean")
std = groups.transform("std")
mean.index=mean.index+timedelta(hours=1)
std.index=std.index+timedelta(hours=1)
Normed=pd.concat({'RTN':Hbar['RTN'],'Mean':mean,'STD':std},axis=1).dropna()
Normed['Norm']=(Normed['RTN']-Normed['Mean'])/Normed['STD']
Normed=Normed.dropna()
low=Normed[Normed['Norm'] < -thred].index
high=Normed[Normed['Norm'] > thred].index
stable=Normed[np.abs(Normed['Norm']) < thred].index
Normed.loc[low, 'Label'] = -1
Normed.loc[stable, 'Label'] = 0
Normed.loc[high, 'Label'] = 1
標準化リターンによるラベリングの全体分布は以下の通り。
ラベルの時間分布をグラフ化する。
N_Hours=Normed.groupby(pd.Grouper(level=0, freq='H'))['Label'].value_counts(normalize=True).unstack()
N_Hours.columns=['Down','Stable','UP']
N_Hours['Time']=N_Hours.index.time
N_Hours.index=N_Hours.index.date
N_hours=N_Hours.groupby(by=["Time"]).mean()
N_hours.plot.bar(width=1.0,ylabel='the average percentage of labels')
ボリュームバーを作成し、これにトリプルバリアを適用し、ラベリングする。水平バリアはリターンの標準偏差の2倍とし、垂直バリアは1日とする。
vv=100
Vbar=bars.getVolumeBars(SP_data,vv)
bar= Vbar['Close'].groupby(pd.Grouper(level=0, freq='D')).count().mean()
minRet = .0005
ptsl=[2,2]
span0=20
price=Vbar['Close']
Daily_vol=labels.getDailyVol(price,span0)
VbarRtn = price.pct_change().dropna()
thred=VbarRtn.std()
Events=bars.getTEvents(VbarRtn[DailyVol.index[0]:], thred) #CUSUM
t1 = labels.addVerticalBarrier(price, Events, numDays=1)
TPevents=labels.getEventsML(price,Events,ptsl,DailyVol,minRet,t1=t1,side=None)
TPlabels=labels.getBinsTUML(TPevents,price,t1)
トリプルバーによるラベリングの全体分布は以下のようになる。
固定時間ホライズン法のラベリングの意味とは違い、”1”は上バリアに、”ー1”は下バリア、”0”は垂直バリアに触れたことを表している。
ラベリングの時間分布をグラフ化する。
マーケットの開閉に関わらず分布はほぼ一定であり、下バリアに触れない時間帯、上バリアに触れない時間帯、垂直バリアにしか当たらない時間帯の存在が顕著である。
トレンドスキャンを固定ホライズン法に適用する。
import BetSize as bz
Trnd = bz.getBinsFromTrend(Hbar.index, Hbar['Close'], [10,30,2])
TR_Hours=Trnd.groupby(pd.Grouper(level=0, freq='H'))['bin'].value_counts(normalize=True).unstack()
TR_Hours.columns=['Down','UP']
TR_Hours['Time']=TR_Hours.index.time
TR_Hours.index=TR_Hours.index.date
TR_hours=TR_Hours.groupby(by=["Time"]).mean()
TR_hours.plot.bar(width=1.0,ylabel='the average percentage of labels')
同様に、ボリュームバーにトレンドスキャン法を適用し、ラベリングの分布をプロットした。
VTrnd=bz.getBinsFromTrend(Vbar.index, Vbar['Close'], [2,10,2])
VTR_Hours=VTrnd.groupby(pd.Grouper(level=0, freq='H'))['bin'].value_counts(normalize=True).unstack()
VTR_Hours.columns=['Down','UP']
VTR_Hours['Time']=VTR_Hours.index.time
VTR_Hours.index=VTR_Hours.index.date
VTR_hours=VTR_Hours.groupby(by=["Time"]).mean()
VTR_hours.plot.bar(width=1.0,ylabel='the average percentage of labels')