GPIFによるデータ

GPIF(年金積立金管理運用独立行政法人)は、厚生年金と国民年金の積立金の管理・運用を行っている団体です。 この団体は、定期的に各金融商品のリスクとリターン、相関係数について評価しており、それらをもとに積立金の運用のためのポートフォリオを決定しています。 ただし、ここでの金融商品とは、会社ごとの株式などではなく、TOPIXや日経225などに代表される、株式市場の株価指数を指すこMとに注意してください。

GPIFは、金融商品を

  • 国内債券
  • 国内株式
  • 海外債権
  • 海外株式

の4つに分けて評価をおこなっており、それぞれのリターン、リスク、相関係数の値は2016年公開のこちらの資料によると、つぎのようになっています。

リターン(リスクプレミアムなし)

国内債券国内株式海外債権海外株式
2.35.93.66.3

リスク

国内債券国内株式海外債権海外株式
4.225.2311.8226.76

相関係数

国内債券国内株式海外債権海外株式
国内債券1.000-0.230-0.040-0.090
国内株式-0.2301.0000.0600.660
海外債権-0.0400.0601.0000.550
海外株式-0.0900.6600.5501.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')

実行結果

まず、期待リターンに対しての最小リスクを示した図を示します。 「ハイリスク・ハイリターンの原則」に従い、リターンに対してリスクが単調に増加していることがわかります。

リスクvsリターン

つぎに期待リターンを実現するポートフォリオを見てみましょう。 期待リターンが小さいうちは定期預金が支配的ですが、徐々にリスク資産にとって代わります。 期待リターン4%くらいまでは海外株式が必要ないという解釈もできそうですね。

リターンvsポートフォリオ

今後の課題

他の団体が公開している指標を使って最適化するとどうなるか、得られたポートフォリオで運用シミュレーションをおこなうとどれくらい良好な結果が出るか、などを見てみたいです。 また、今回はGPIFが公開しているデータセットを使いましたが、将来的には、自分が購入する投資信託の商品の時系列データから、リスクやリターン、相関係数を同定できるようになりたいです。