アセットマネージャーのためのファイナンス機械学習:テストデータのオーバーフィッティング ファミリーワイズエラー率

ネイマンピアソンの仮説検定において、帰無仮説$${H_0}$$が真であれば、確率$${\alpha}$$でしか起こり得ない現象を観察した時には、帰無仮説$${H_0}$$は確信度$${(1-\alpha)}$$で棄却される。この時、$${H_0}$$を誤って棄却するタイプ$${{\rm I}}$$のエラー確率は、$${1-(1-\alpha)=\alpha}$$となる。これを多重テストの場合に適用すると、K回の独立施行で、$${H_0}$$は確信度$${(1-\alpha)^K}$$で棄却される。
 よって、このK回の試行全体(ファミリー)の偽陽性率は$${\alpha_K=1-(1-\alpha)^K}$$で、これがファミリーワイズエラーとなる。$${(1-\alpha)^K}$$はK回全てで陽性が真である可能性であり、ファミリーワイズエラーは、少なくとも一回は陽性が偽の可能性でもある。
 一回毎の確率に直せば、結果が偽陽性でない確率は$${(1-\alpha_K)^{1/K}}$$となるから、一回毎の偽陽性の確率は$${\displaystyle{1-(1-\alpha_K)^{1/K} \sim \frac{\alpha_K}{K}}}$$である。これをシダックの補正と呼ぶ。

多重テストでのタイプ$${{\rm I}}$$エラー

サイズTのリターン系列の投資戦略を、推定シャープレシオ$${\widehat{SR}}$$を用いて、($${H_0: SR=0, H_1:SR>0}$$の仮設検定を行い、複数回検定を行った場合の偽陽性率を求める。
 真のシャープレシオが与えられた閾値$${SR^\ast}$$を超える確率は、
$${\widehat{DSR}=\displaystyle{Z\left[ \frac{(\widehat{SR}-E[ \max_k\{\widehat{SR}_k\}])\sqrt{T-1}}{\sqrt{1-\hat{\gamma}_3\widehat{SR} +\frac{\hat{\gamma}_4-1}{4}\widehat{SR}^2} }\right] }}$$
であったことを思い出せば、

真のシャープレシオが$${SR^\ast}$$に等しい場合、統計量$${\hat{z}[SR^\ast]}$$は標準正規分布に漸近分布して、
$${\hat{z}[SR^\ast]=\displaystyle{\frac{(\widehat{SR}-E[ \max_k\{\widehat{SR}_k\}])\sqrt{T-1}}{\sqrt{1-\hat{\gamma}_3\widehat{SR} +\frac{\hat{\gamma}_4-1}{4}\widehat{SR}^2} } \to^{a} Z}}$$
となる。
 $${\widehat{SR}}$$は非年率換算の推定シャープレシオである。
 よって、ファミリーワイズのタイプ$${{\rm I}}$$エラー確率は、
$${P[\max_k\{ \hat{z}[0]_k\},k=1,\dots,K > z_\alpha | H_0]=1-(1-\alpha)^K=\alpha_K}$$
と与えられる。これは、$${\max_k\{ \hat{z}[0]_k\},k=1,\dots,K > z_\alpha}$$である時、帰無仮説$${H_0}$$は、確信度$${(1-\alpha_K)=1-(1-(1-\alpha)^K))=(1-\alpha)^K}$$で棄却されることを意味している。$${Z[.]}$$を単独テストで結果が真である確率の標準正規分布密度関数として、$${z_\alpha=Z^{-1}[1-\alpha]=Z^{-1}[(1-\alpha_K)^{1/K}]}$$で与えられる。

多重テストのタイプ$${{\rm I}}$$エラーは、複数戦略の多重テストのクラスタリングを用いても推定できる。

試行の相関行列にクラスタリングを適用し、クラスタのリターン時系列と$${E[K]}$$を推定する。これから、選択されたクラスタのリターンについて、$${\max_k\{\hat{z}[0]_k\},k=1,\dots,K}$$を推定し、単一テストのタイプ$${{\rm I}}$$エラー$${\alpha=1=Z[\hat{z}[0]]}$$を得る。よって、$${\alpha_K=1-(1-\alpha)^K=1-Z[\hat[z[0]]]^{E[K]}}$$となる。

タイプ$${{\rm I}}$$エラーの数値例の計算法はスニペット8.3で与えられている。

def getZStat(sr, t, sr_=0, skew=0, kurt=3):
    z = (sr-sr_)*(t-1)**.5
    z /= (1-skew*sr+(kurt-1)/4.*sr**2)**.5
    return z
    
def type1Err(z, k=1):
    #false positive rate
    alpha = ss.norm.cdf(-z)
    alpha_k = 1-(1-alpha)**k #multi-testing correction
    return alpha_k

t, skew, kurt, k, freq=1250, -3, 10, 10, 250
sr = 1.25/freq**.5
sr_ = 1./freq**.5
z = getZStat(sr, t, 0, skew, kurt)
alpha_k = type1Err(z, k=k)
print(alpha_k)

$${\alpha_k=0.060760}$$

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