アセットマネージャーのためのファイナンス機械学習:ノイズ除去 練習問題2-b

平均10%、標準偏差10%の正規分布する100個のベクトルを使い、100資産の効率的フロンティアを計算する。
 まず、100本の正規乱数ベクトルを作成する。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

np.random.seed(0)

# 期待リターン

mean = 0.1
std_dev = 0.1

# 期待リターンベクトルを生成する
n_assets = 100
nObs=1000
mu=0.1
corr=0.1

return_mat = pd.DataFrame(np.random.normal(mu, corr, size=(nObs, n_assets)))

 これから、平均期待リターンベクトル、共分散行列を計算する。

return_mean=return_mat.mean()
return_cov=return_mat.cov()

解析解を求める。

ones=np.ones(n_assets)

return_cov_inv=pd.DataFrame(np.linalg.pinv(return_cov.values), return_cov.columns, return_cov.index)

A=np.dot(return_mean.T, np.dot(return_cov_inv, ones))
C=np.dot(ones.T, np.dot(return_cov_inv, ones))
B=np.dot(return_mean.T, np.dot(return_cov_inv, return_mean))
D=B*C-A*A

mean_high = return_mean.max()
rets = np.linspace(A/C, mean_high, 50)
vols = []

for ret in rets:
    var2=C/D*(ret-A/C)**2+1/C
    vol=np.sqrt(var2)
    vols.append(vol)
    
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 6))
plt.scatter(vols,rets,c=rets/vols, marker='o',label='analytical')
plt.grid(True)
plt.xlabel('expected volatility')
plt.ylabel('expected return')
plt.legend()
efficient frontier (analytical)

最小化関数を使う

scikit-learnのminimize関数を使う。

from scipy.optimize import minimize

#ポートフォリオの期待収益率の分散の定義
def min_func_var(weights):
    return np.dot(weights.T, np.dot(cov, weights))

#空売り無し条件
#bnds = [(0, None)] * n_assets 


mean_high = return_mean.max().round(3)
mean_low = return_mean.min().round(3)
rets = np.linspace(mean_low, mean_high, 50)
vols = []
cov=return_cov

x0 = [1. / n_assets] * n_assets

for ret in rets:
    constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1},
               {'type': 'eq', 'fun': lambda x: np.sum(return_mean*x) - ret})
    res = minimize(fun=min_func_var, x0=x0, method='SLSQP', constraints=constraints)
    if(res['success']): vols.append(np.sqrt(res['fun']))
vols= np.array(vols)

import matplotlib.pyplot as plt
plt.figure(figsize=(10, 6))
plt.scatter(vols,rets,c=rets/vols, marker='o',label='optimize')
plt.grid(True)
plt.ylim([0.10,None])
plt.xlabel('expected volatility')
plt.ylabel('expected return')
plt.legend()
efficient frontier optimize

いいなと思ったら応援しよう!