アセットマネージャーのためのファイナンス機械学習:ポートフォリオの構築 練習問題 デトーニング処理後の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))