ファイナンス機械学習:金融データ構造 練習問題 ボリンジャーバンドとCUSUM
E-mini S&P 500先物ドルバーに対し、移動平均周り5%のボリンジャーバンドを計算し、価格がバンドの内側から外側へ移行する回数を数え、その時をイベントとし、価格系列をサンプリングする。ここでは移動平均のスパンを20バーと取っている。
def getBBand2(data_df, span, alp):
BB_df=data_df
BB_df['TP']=(data_df['High']+data_df['Low']+ddf['Close'])/3
BB_df['SMA'] = data_df['TP'].rolling(window=span).mean()
sig = pd.Series(data_df['SMA']).rolling(span, min_periods=span).std()
BB_df['BB_u'], BB_df['BB_d'] = (data_df['SMA']*(1+alp)), (data_df['SMA']*(1- alp))
return BB_df.dropna()
def countCross(BB):
BBcross=[]
count=0
for i in range(1,len(BB)):
if( BB['Close'][i]>BB['BB_u'][i] and
BB['Close'][i-1]<BB['BB_u'][i-1] ):
count+=1
BBcross.append(BB.index[i])
if( BB['Close'][i-1]>BB['BB_d'][i-1] and
BB['Close'][i]<BB['BB_d'][i]):
count+=1
BBcross.append(BB.index[i])
return count,BBcross
ddf_BB=get_BB_band2(ddf,20,0.05)
count, BBcrossId=countCross(ddf_BB)
BB_price=ddf_BB.loc[BBcrossId]['Close']
同じドルバーに対し、CUSUMフィルタを使用し、$${y_t}$$をリターンとして、$${h=0.05}$$とする。
def getTEvents(gRaw, h) :
tEvents, sPos, sNeg = [], 0, 0
diff = gRaw.diff()
for i in diff.index[1:]:
sPos, sNeg = max(0, sPos + diff.loc[i]), min(0, sNeg + diff.loc[i])
if sNeg < -h:
sNeg = 0
tEvents.append(i)
elif sPos > h:
sPos = 0
tEvents.append(i)
return pd.DatetimeIndex(tEvents)
ddf_rtn = ddf['Close'].pct_change().dropna()
events=getTEvents(ddf_rtn, 0.05)
CUSUM_price=ddf.loc[events]['Close']
ボリンジャーバンド、CUSUMでのイベント数は、以下の通りである。
![](https://assets.st-note.com/img/1696614547822-Sc1f5AUP5O.png?width=1200)
この二つのサンプル系列の移動標準偏差を計算する。スパンは25とした。
plt.plot(CUSUM_price.rolling(25).std().dropna()[datetime(2012, 8, 1):], label='CUSM')
plt.plot(BB_price.rolling(25).std().dropna(),label='BB 5%')
plt.legend()
![](https://assets.st-note.com/img/1696614682092-7vhRoJnyWl.png?width=1200)
CUSUMの偏差の方が小さく、不均一性が小さいとわかる。