GPIFによるデータ
GPIF(年金積立金管理運用独立行政法人)は、厚生年金と国民年金の積立金の管理・運用を行っている団体です。 この団体は、定期的に各金融商品のリスクとリターン、相関係数について評価しており、それらをもとに積立金の運用のためのポートフォリオを決定しています。 ただし、ここでの金融商品とは、会社ごとの株式などではなく、TOPIXや日経225などに代表される、株式市場の株価指数を指すこMとに注意してください。
GPIFは、金融商品を
- 国内債券
- 国内株式
- 海外債権
- 海外株式
の4つに分けて評価をおこなっており、それぞれのリターン、リスク、相関係数の値は2016年公開のこちらの資料によると、つぎのようになっています。
リターン(リスクプレミアムなし)
国内債券 | 国内株式 | 海外債権 | 海外株式 |
---|---|---|---|
2.3 | 5.9 | 3.6 | 6.3 |
リスク
国内債券 | 国内株式 | 海外債権 | 海外株式 |
---|---|---|---|
4.2 | 25.23 | 11.82 | 26.76 |
相関係数
国内債券 | 国内株式 | 海外債権 | 海外株式 | |
---|---|---|---|---|
国内債券 | 1.000 | -0.230 | -0.040 | -0.090 |
国内株式 | -0.230 | 1.000 | 0.060 | 0.660 |
海外債権 | -0.040 | 0.060 | 1.000 | 0.550 |
海外株式 | -0.090 | 0.660 | 0.550 | 1.000 |
今回はこれらの金融商品に加えて、「定期預金」も考慮したポートフォリオを最適化したいと思います。 ここで、定期預金のリターンは0.1、リスクは0、他の金融商品との相関係数は全て0としました。 いくつかの資料によれば、ポートフォリオを最適化するにあたって、リスク資産と無リスク資産は分けて考えるのが定石のようです。 しかしながら自分には「無リスク資産をリスク0のリスク資産としてみなす」ことが、何故まずいことなのかよく理解できなかったので、今回は「定期預金」もポートフォリオに加入してみた次第です。 このあたりに詳しい方がおられましたら、ぜひご教授ください……
CVXOPTを用いた最適化
さて、以上のデータを用いて前回紹介した2次計画問題を解くために、Pythonでスクリプトを作成しました。 作成したスクリプトの中では、CVXOPTというソルバー(問題を自動で解いてくれるツール)を用いています。 CVXOPTの使い方は、こちらの記事が参考になります。
ソースコード
import numpy
import cvxopt
from cvxopt import matrix
import matplotlib.pyplot as plt
mu = numpy.array([[2.3,5.9,3.6,6.3,0.1]])
Sigma = numpy.diag([4.2,25.23,11.82,26.76,0])
R = numpy.array([[1.000,-0.230,-0.040,-0.090,0.000],
[-0.230,1.000,0.060,0.660,0.000],
[-0.040,0.060,1.000,0.550,0.000],
[-0.090,0.660,0.550,1.000,0.000],
[0.000,0.000,0.000,0.000,1.000]])
Cov = Sigma@R@Sigma
print(numpy.linalg.matrix_rank(Cov))
P = matrix(Cov)
q = matrix(numpy.zeros((5,1)))
Id = numpy.identity(5)
G = matrix(-numpy.concatenate((Id,mu), axis=0))
A = matrix(numpy.ones((1,5)))
b = matrix(100*numpy.ones((1,1)))
Return_bound = numpy.linspace(0,6.7,50)
Return = numpy.array([])
Risk = numpy.array([])
Allocations = numpy.array([])
for re_bound in Return_bound:
h = matrix(numpy.array([0.0,0.0,0.0,0.0,0.0,-re_bound*100]))
sol = cvxopt.solvers.qp(P,q,G,h,A,b)
Sol = sol["x"]
Allocations = numpy.append(Allocations,Sol)
re = Sol.T@mu.T/100
Return = numpy.append(Return,re)
ri = (Sol.T@Cov@Sol/10000)**0.5
Risk = numpy.append(Risk,ri)
print(Risk)
print(Return)
fig = plt.figure()
plt.plot(Risk,Return)
plt.xlabel("予想リスク(標準偏差)")
plt.ylabel("期待リターン [%]")
plt.show()
Allocations = Allocations.reshape(Return_bound.size,5)
Allocations = Allocations.T
fig = plt.figure()
wd = 5/Return.size
p1 = plt.bar(Return, Allocations[0], width = wd, color = "red", label = "国内債権")
p2 = plt.bar(Return, Allocations[1], width = wd, bottom=Allocations[0], color = "orange", label = "国内株式")
p3 = plt.bar(Return, Allocations[2], width = wd, bottom=sum(Allocations[0:2,:]), color = "yellow", label = "海外債権")
p4 = plt.bar(Return, Allocations[3], width = wd, bottom=sum(Allocations[0:3,:]), color = "green", label = "海外株式")
p5 = plt.bar(Return, Allocations[4], width = wd, bottom=sum(Allocations[0:4,:]), color = "blue", label = "預金")
plt.legend()
plt.xlabel("期待リターン [%]")
plt.ylabel("資産配分 [%]")
plt.xlim([0.1,6.7])
plt.ylim([0,100])
plt.show()
plt.close('all')
実行結果
まず、期待リターンに対しての最小リスクを示した図を示します。 「ハイリスク・ハイリターンの原則」に従い、リターンに対してリスクが単調に増加していることがわかります。
つぎに期待リターンを実現するポートフォリオを見てみましょう。 期待リターンが小さいうちは定期預金が支配的ですが、徐々にリスク資産にとって代わります。 期待リターン4%くらいまでは海外株式が必要ないという解釈もできそうですね。
今後の課題
他の団体が公開している指標を使って最適化するとどうなるか、得られたポートフォリオで運用シミュレーションをおこなうとどれくらい良好な結果が出るか、などを見てみたいです。 また、今回はGPIFが公開しているデータセットを使いましたが、将来的には、自分が購入する投資信託の商品の時系列データから、リスクやリターン、相関係数を同定できるようになりたいです。