import numpy as np
import pandas as pd
from bokeh.io import output_notebook
from bokeh.plotting import figure, show
import scipy.optimize as sco
output_notebook()
https://qiita.com/ryoshi81/items/b323a363e5442a15db6d
https://www.wealthnavi.com/image/WealthNavi_WhitePaper.pdf
rtns = np.array([0.065, 0.075, 0.085, 0.019, 0.023, 0.039, 0.058]) # 収益率(年率)
rsks = np.array([0.124, 0.148, 0.184, 0.028, 0.048, 0.179, 0.149]) # リスク(年率)
corrs = np.array([
[1.0, 0.9, 0.8, -0.1, 0, 0, 0.7],
[0.9, 1.0, 0.8, -0.1, 0.1, 0.1, 0.6],
[0.8, 0.8, 1.0, 0.1, 0.2, 0.3, 0.6],
[-0.1, -0.1, 0.1, 1.0, 0.8, 0.4, 0.4],
[0, 0.1, 0.2, 0.8, 1.0, 0.5, 0.4],
[0, 0.1, 0.3, 0.4, 0.4, 1.0, 0.1],
[0.7, 0.6, 0.6, 0.4, 0.4, 0.1, 1.0]
]) # 相関
p = figure(width= 800, height = 500, title='各資産のリスクリターン')
p.cross(rsks, rtns, size=20)
p.xaxis.axis_label='リスク'
p.yaxis.axis_label='リターン'
show(p)
# 相関行列と標準偏差から共分散行列を作成
# 相関係数(x, y) = 共分散 / (標準偏差(x) * 標準偏差(y) )
# 共分散 = 相関係数(x, y) * (標準偏差(x) * 標準偏差(y))
# これを作る部分が難しい。なんか簡単な方法ないのかなぁ。
a1 = []
a2 = []
a3 = []
a4 = []
a5 = []
a6 = []
a7 = []
def testi(r = 0.065, box = a1, volls = rsks):
for i in range(len(rsks)):
box.append(np.dot(r ,rsks[i]))
return np.array(box)
b1 = testi()
b2 = testi(r = rsks[1], box = a2)
b3 = testi(r = rsks[2], box = a3)
b4 = testi(r = rsks[3], box = a4)
b5 = testi(r = rsks[4], box = a5)
b6 = testi(r = rsks[5], box = a6)
b7 = testi(r = rsks[6], box = a7)
SIgma = [b1 * np.array(corrs[0]), b2 * np.array(corrs[1]), b3 * np.array(corrs[2]), \
b4 * np.array(corrs[3]), b5 * np.array(corrs[4]), b6 * np.array(corrs[5]), b7 * np.array(corrs[6])]
# 目的関数
def min_func_var(weights):
return np.dot(weights.T, np.dot(SIgma, weights))
# 初期解
x0 = [1.0 / len(rtns)] * len(rtns)
# 目標リターン(各資産の最高、最低で作る。レバレッジを掛けない限り採用資産のリターンの最高がポートフォリオのリターンの上限となる)
max_ret = rtns.max()
min_ret = rtns.min()
trets = np.linspace(min_ret, max_ret, 100)
# 投資比率制限(空売りを出来なくする)
bnds = [(0, None)] * len(rtns)
tvols = []
for tret in trets:
cons = [{'type': 'eq', 'fun': lambda x: np.sum(x) - 1},
{'type': 'ineq', 'fun': lambda x: np.sum(rtns * x) - tret}]
res = sco.minimize(fun=min_func_var, x0 = x0, method = 'SLSQP', bounds = bnds, constraints = cons)
tvols.append((np.sqrt(res['fun'])))
tvols = np.array(tvols)
p = figure(width = 800, height=500, title='ポートフォリオのリスクリターン')
p.line(tvols, trets, line_color='blue', line_width=3)
p.cross(rsks, rtns, size = 20)
p.xaxis.axis_label='ポートフォリオのリスク'
p.yaxis.axis_label = 'ポートフォリオのリターン'
show(p)
corrs2 = np.array([
[1.0, 0.2, 0.1, -0.1, 0, 0, 0.7],
[0.2, 1.0, 0.1, -0.1, 0.1, 0.1, 0.6],
[0.1, 0.1, 1.0, 0.1, 0.2, 0.3, 0.6],
[-0.1, -0.1, 0.1, 1.0, 0.8, 0.4, 0.4],
[0, 0.1, 0.2, 0.8, 1.0, 0.5, 0.4],
[0, 0.1, 0.3, 0.4, 0.4, 1.0, 0.1],
[0.7, 0.6, 0.6, 0.4, 0.4, 0.1, 1.0]
])
# 最初の
corrs = np.array([
[1.0, 0.9, 0.8, -0.1, 0, 0, 0.7],
[0.9, 1.0, 0.8, -0.1, 0.1, 0.1, 0.6],
[0.8, 0.8, 1.0, 0.1, 0.2, 0.3, 0.6],
[-0.1, -0.1, 0.1, 1.0, 0.8, 0.4, 0.4],
[0, 0.1, 0.2, 0.8, 1.0, 0.5, 0.4],
[0, 0.1, 0.3, 0.4, 0.4, 1.0, 0.1],
[0.7, 0.6, 0.6, 0.4, 0.4, 0.1, 1.0]
]) # 相関
c1 = []
c2 = []
c3 = []
c4 = []
c5 = []
c6 = []
c7 = []
d1 = testi(r = rsks[0], box = c1)
d2 = testi(r = rsks[1], box = c2)
d3 = testi(r = rsks[2], box = c3)
d4 = testi(r = rsks[3], box = c4)
d5 = testi(r = rsks[4], box = c5)
d6 = testi(r = rsks[5], box = c6)
d7 = testi(r = rsks[6], box = c7)
SIgma2 = [d1*np.array(corrs2[0]), d2*np.array(corrs2[1]), d3*np.array(corrs2[2]), d4*np.array(corrs2[3]), \
d5*np.array(corrs2[4]), d6*np.array(corrs2[5]), d7*np.array(corrs2[6])]
SIgma2
[array([ 0.015376 , 0.0036704, 0.0022816, -0.0003472, 0. , 0. , 0.0129332]), array([ 0.0036704, 0.021904 , 0.0027232, -0.0004144, 0.0007104, 0.0026492, 0.0132312]), array([ 0.0022816, 0.0027232, 0.033856 , 0.0005152, 0.0017664, 0.0098808, 0.0164496]), array([-0.0003472, -0.0004144, 0.0005152, 0.000784 , 0.0010752, 0.0020048, 0.0016688]), array([ 0. , 0.0007104, 0.0017664, 0.0010752, 0.002304 , 0.004296 , 0.0028608]), array([ 0. , 0.0026492, 0.0098808, 0.0020048, 0.0034368, 0.032041 , 0.0026671]), array([ 0.0129332, 0.0132312, 0.0164496, 0.0016688, 0.0028608, 0.0026671, 0.022201 ])]
def min_func_var2(weights):
return np.dot(weights.T, np.dot(SIgma2, weights))
tvols2 = []
for tret in trets:
cons = [{'type': 'eq', 'fun': lambda x: np.sum(x) - 1},
{'type': 'ineq', 'fun': lambda x: np.sum(rtns * x) - tret}]
res = sco.minimize(fun=min_func_var2, x0 = x0, method = 'SLSQP', bounds = bnds, constraints = cons)
tvols2.append((np.sqrt(res['fun'])))
tvols2 = np.array(tvols2)
p = figure(width=800, height = 500, title='ポートフォリオのリスクリターン')
p.line(tvols, trets, line_color='blue', line_width=3, legend='高相関')
p.line(tvols2, trets, line_color='red', line_width=3, legend='低相関')
p.cross(rsks, rtns, size=20)
p.xaxis.axis_label ='ポートフォリオのリスク'
p.yaxis.axis_label = 'ポートフォリオのリターン'
p.legend.location = 'top_left'
show(p)