アセットマネージャーのためのファイナンス機械学習:ポートフォリオの構築 練習問題 デトーニング処理後のNCO

NCOアルゴリズム中、相関クラスタリングの前に共分散行列のノイズ除去を行っていたスニペット7.3へ、デトーニング処理を加えて、NCOをポートフォリオの最終結果に影響が出るか調べる。
スニペット7.3への変更は以下のようになる。

nBlocks, bSize, bCorr = 2, 2, .5
q = 10.0
np.random.seed(0)
mu0, cov0 = MP.formTrueMatrix(nBlocks, bSize, bCorr)
cols = cov0.columns

corr0=MP.cov2corr(cov0)
eVal0,eVec0=MP.getPCA(corr0)
dt_corr=MP.detonedCorr(corr0,eVal0, eVec0)
dt_cov=MP.corr2cov(dt_corr,np.diag(cov0)**.5)

cov1 = MP.deNoiseCov(dt_cov, q, bWidth=.01) 
cov1 = pd.DataFrame(cov1, index=cols, columns=cols)
corr1 = MP.cov2corr(cov1)
corr1, clstrs, silh = NC.clusterKMeansBase(corr1, 
                                           maxNumClusters=int(corr0.shape[0]/2),n_init=10)
clstrs
デトーニング後のクラスタリング

デトーニングとは、全体に影響を及ぼす強い雑音(トーン)を除く意味で、最も大きい固有値を一つ取り除いた共分散行列を生成する。これを元に、最少分散ポートフォリオを求めると以下の結果になった。

デトーニング後のクラスタリングを用いた最少分散ポートフォリオ

デトーニングなしのクラスタリングを用いた最少分散ポートフォリオの結果は上記の記事にある。

実験と同じサイズのブロック数10、ブロックサイズ5、ブロック間相関0.5の共分散行列にデトーニングとノイズ除去した後に、最少分散ポートフォリオと最大シャープレシオのポートフォリオを計算する。

def PortExp_DTN(mu0,cov0,q=10.0,bWidth=.01,
            nObs=1000, nSims=1000, shrink=False, minVarPortf = True):

    print("Detone + Denoize of cov")

    w1 = pd.DataFrame(0, index=range(0, nSims),
                  columns=range(0, cov0.shape[0]),dtype='float64')
    w1_d = pd.DataFrame(0, index=range(0, nSims),
                    columns=range(0, cov0.shape[0]),dtype='float64')
    for i in range(0, nSims):

        mu1, cov1 = MP.simCovMu(mu0, cov0, nObs, shrink=shrink)
        cols = cov0.columns

        corr1=MP.cov2corr(cov1)
        eVal1,eVec1=MP.getPCA(corr1)
        dt_corr=MP.detonedCorr(corr1,eVal1, eVec1)
        dt_cov=MP.corr2cov(dt_corr,np.diag(cov1)**.5)

        cov1 = MP.deNoiseCov(dt_cov, q, bWidth=bWidth)
        cov1 = pd.DataFrame(cov1, index=cols, columns=cols)

        if minVarPortf:
             mu1 = None

        w1.loc[i] = MP.optPort(cov1, mu1).flatten()
        w1_d.loc[i] = optPort_nco(cov1, mu1, int(cov1.shape[0]/2)).flatten()
    return w1, w1_d

雑音を入れる前の元のデータからの最少分散ポートフォリオと最大シャープレシオポートフォリオとの二乗誤差を計算する。

def main():

    nBlocks, bSize, bCorr = 10, 5, .5
    q=10.0

    np.random.seed(0)
    mu0, cov0 = MP.formTrueMatrix(nBlocks, bSize, bCorr)

    minVarPortf=True

    w1, w1_d=PortExp_DTN(mu0=mu0,cov0=cov0,minVarPortf = minVarPortf)

    w0 = MP.optPort(cov0, None if minVarPortf else mu0)
    w0 = np.repeat(w0.T, w1.shape[0], axis=0)

    print('minVar Markowitz RMSE: ',
          round(np.mean((w1-w0).values.flatten()**2)**.5,4))
    print('minVar NCO RMSE:',
          round(np.mean((w1_d-w0).values.flatten()**2)**.5,4))

    minVarPortf=False
    w1, w1_d=PortExp_DTN(mu0=mu0,cov0=cov0,minVarPortf = minVarPortf)

    w0 = MP.optPort(cov0, None if minVarPortf else mu0)
    w0 = np.repeat(w0.T, w1.shape[0], axis=0)

    print('maxSR Markowitz  RMSE: ',
          round(np.mean((w1-w0).values.flatten()**2)**.5,4))
    print('maxSR NCO RMSE:',
          round(np.mean((w1_d-w0).values.flatten()**2)**.5,4))
デトーニングとノイス除去後の各ポートフォリオの二乗誤差


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