アセットマネージャーのためのファイナンス機械学習:ノイズ除去 練習問題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()
最小化関数を使う
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()