理系的な戯れ

理工学系とくにロボットやドローンに関する計算・プログラミング等の話題を扱って、そのようなことに興味がある人たちのお役に立てればと思っております。

現代ポートフォリオ理論(MPT)

現代ポートフォリオ理論アイキャッチ

はじめに

ついに満50歳を迎えたこうへいですが、生家が商売をしていて常々いつか商売に失敗して 「何もかんも無くなる無くなる」と育てられたせいか、 お金については使う時はパッと使いますが割とシビアに計画的だったりします。 ちなみに言われてた通り生家は家も土地も全てなくしてしまいました。(育った家は既に人のもの(T_T)) そんなんで、身ぐるみはがされず、好きなことしてのんびりと面白く生きていけるように結構慎重に資産形成を考えています。

今はあと10年ぐらいで定年できればいいなと嫁さんともども「目指せ1○円!」を合言葉にガシガシ働いております。

そのうちテック系の人にFPみたいにアドバイスできたらいいなあと夢を見つつ、 けっこう堅実に積み上げていくのは最近自信を持てるようになってきました。 堅実に積み上げるのは若いと果てしなく感じて中々うまくできないのですが、 今の1万円の積み上げが大事です。人生積分、お金も積分です。 そして福利で少し増やす。これ!です。

微分積分は資産形成にも役立つのです。 と言うのは言い過ぎなのかもしれませんが自分は真剣にそう思っているのです。

今日は資産をどういう風に配分するのがいいのかを考えるのに役立つ 現代ポートフォリオ理論(Modern Portfolio Theory)略してMPTを取り上げます。

中身自体はほとんどWikipediaにお任せしてしまってますので表面をなぞるだけですが 自分もこれを参考に資産配分してるので自分のためにもまとめておきます。

まずはWikipediaを参照してほしいと思います。

現代ポートフォリオ理論 - Wikipedia

ポートフォリオの期待値と分散そして相関

いろんな種類の金融資産、例えば株とか債権とかを組み合わせて自分で保有しているセットをポートフォリオと言います。

それぞれの金融資産にはそれぞれ一年でどのくらい収益率になるかという期待収益率という収益率の期待値があります。 また年ごとにどのくらいばらつくかというのがその資産の分散です。

分散の平方根が標準偏差ですが、そちらをリスクと言います。金融ではリスクは危ないという意味合いよりも、ばらつきという意味合いです。

リスクを取らなければリターンは無いといいますが、これは全く変動しないことを選べば、損することもありませんが、得することも無いということです。

期待収益率が判ればいいのですが、実はわかりません。これがきっちり推定できれば大金持ちになれますが、できないので大金持ちにはなれません。 分散については過去のデータに基づく値がそこそこ当てになると言われています。 しかし、過去のデータの平均は期待収益率としては当てにならないと言われています。 去年まで絶好調だった会社が突然コロナで倒産みたいなこともあり得るからです。 倒産まで行かなくても、そこから下がる一方という事もあり得、過去のデータは実は未来の事を語っていないという事になります。

ただし、一つの銘柄ではなく多くの会社の株を全て集められたら良いも悪いも平均化されて、 少し期待値の予想がよくなるかもしれません。

つまり日本の会社の株をほとんどを買うということができれば、それは日本国の経済にベット(賭ける)するということです。

日本の将来が暗いと思ったら、アメリカや中国にベットします。あるいは全世界にベットすることもできます。

今はいろんな金融商品があるので、全世界の会社の株を全部買うお金を持っていなくても、そういうことも簡単にできます。

そうすると、ある国または全世界の成長率にわりと即した期待値になるかもしれないわけです。

でも当然、今回のコロナとか世界大戦とかがおこると悪化してしまいますが・・・・

僕らの戦略は「国規模や世界規模ならそこそこ期待値も予想の範疇にくるんじゃないか!?」戦略です。

予想は誰にもできませんが、みんなが経済をよくしよう、裕福になろうと頑張っているので、経済は上がっていくことは信じておかないと投資はできないわけです。

話が横道にそれましたが、ある年の各金融資産の収益率をR_iとして、 その期待収益率E(R_i)、その標準偏差を\sigma_iとします。

ある金融資産iとある金融資産jの収益率の相関を\rho_{ij}とします。

収益率の相関というのは同じように上がったりさっがたりするかの度合いを表します。 相関1は完全に上がり下がりが一致しているということです。−1なら完全に逆に動きます。

相関が−1同士の金融資産を持っていると、世の中の動きに影響されず変動しないポートフォリオになります。 ま、これでは儲けることができないので意味はないのですが。 しかし、この相関を利用してうまく組み合わせることが大事になってきます。

MPTには共分散という言葉も出てきます。 共分散は二つのデータのそれぞれのデータの平均との偏差の掛け算の平均なのです。 後ほど、複数の銘柄からなるポートフォリオの分散を求める際に、この共分散が再び登場します。

さて今、それぞれの金融資産を割合w_iで持っているポートフォリを所有しているとします。w_iの合計は1になります。

ポートフォリオの期待値

それでは個々の資産の期待値や分散がわかり資産同士の相関もわかっているとしたらポートフォリオの期待値はどのように表すことができるでしょうか。

ポートフォリオの収益率をR_pとしますと、ポートフォリオの期待収益率は以下のようになります。


\begin{eqnarray}
E(R_p)=\sum_{i=1}^N w_i E(R_i)\\
\\
\end{eqnarray}

結局、ポートフォリオの収益率は各期待収益率に割合をかけて足すだけです。

ポートフォリオの分散

ポートフォリオの分散を\sigma_{p}^2とすると


\begin{eqnarray}
\sigma_p^2&=&\sum_{i=1}^N \sum_{j=1}^N w_i w_j \sigma_i \sigma_j \rho_{ij}\\
\\
\end{eqnarray}

意味を説明するのは難しいのですが、2銘柄からなるポートフォリオを例にしてお話してみます。

先ほどの期待収益率の計算からポートフォリオの分散はポートフォリオの各年の収益率からポートフォリオの平均を引いて2乗したものの平均になり、以下のように表すことができます。 ただし、集計したデータはn年分とします。


\begin{eqnarray}
\sigma_p^2&=&\frac{1}{n} \sum_{i=1}^n \left\{  w_1 {R_1}_i + w_2 {R_2}_i - \left(  w_1 E(R_1) + w_2 E(R_2) \right)\right\}^2 \\
&=&\frac{1}{n} \sum_{i=1}^n \left\{  w_1 ( {R_1}_i -  E(R_1) )  + w_2  ( {R_2}_i - E(R_2) ) \right\}^2 \\
&=&\frac{1}{n} \sum_{i=1}^n \left\{  {w_1}^2 ( {R_1}_i -  E(R_1) )^2  + {w_2}^2  ( {R_2}_i - E(R_2) )^2 \\ +2 w_1  w_2 ( {R_1}_i -  E(R_1) )  ( {R_2}_i - E(R_2) )\right\} \\
&=& {w_1}^2 {\sigma_1}^2 + {w_2}^2 {\sigma_2}^2 + 2 w_1  w_2 \sigma_{12}\\
\\
\end{eqnarray}

ここで\sigma_{12}と言うのは、2銘柄の共分散とです。共分散は銘柄の相関\rho_{12}を使うと、以下のように表せます。


\begin{eqnarray}
\sigma_{12}=\rho_{12} \sigma_1  \sigma_2 
\\
\end{eqnarray}

したがって


\begin{eqnarray}
\sigma_p^2&=& {w_1}^2 {\sigma_1}^2 + {w_2}^2 {\sigma_2}^2 + 2 w_1  w_2 \sigma_1  \sigma_2 \rho_{12} \\
\\
\end{eqnarray}

これは先ほど示した、複数の銘柄の分散を計算する式を2銘柄に限定して展開したものと同じになります。

この様に複数の銘柄の分散は分散の定義に戻って計算を進めることによって導くことができます。

ポートフォリオの期待値と分散の行列計算表現

ポートフォリをの各割合が列挙された縦ベクトルを\vec w、ポートフォリオの各資産の期待収益率が列挙された縦ベクトルを\vec Eとすると。ポートフォリオの期待値E(R_p)は次の式で計算できます。これはベクトルの内積を計算するのと同じです。


\begin{eqnarray}
E(R_p)={\vec w}^T \vec E
\\
\end{eqnarray}

また、ポートフォリオの共分散行列を\Sigmaとします。

共分散行列というのは行列のi行、j列の成分が以下のように与えられている行列を言います。


\begin{eqnarray}
E[(R_i-E(R_i)(R_j-R(R_j)]
\\
\end{eqnarray}

先ほど説明した、共分散の行列だということがわかります。

共分散行列と重みベクトルを用いると、以下のようにポートフォリオの分散が求められます。


\begin{eqnarray}
{\sigma_p}^2={\vec w}^T \Sigma \vec w
\\
\end{eqnarray}

最適な組み合わせをどう求めるか

投資家つまり我々は同じ期待収益率ならば最も標準偏差(リスク)が小さいくなるポートフォリオを選ぶのが効率的です。

これは、ポートフォリをで所定の期待収益率を設定し、最も小さな分散になるような各資産の割合を求める最小化問題となります。

しかし、最小化問題を理解するのは大変なため、もっと直感的な方法で最適値を見つけようと思います。

ランダムに割合の組み合わせを作り出す

多数の割合の組み合わせを試して、期待値と標準偏差をグラフ上にプロットすることができれば、最小化問題を解かなくても最小値を満たす何かが見えてくるかもしれません。

色々な割合のポートフォリオをランダムに作り出すには次のようにします。

  1. 資産の数分の乱数を生成します
  2. 生成された乱数の総和を計算します
  3. 各乱数を総和で割ります

この様に生成されたのが割合になり全部足すと1になります。

計算例

実際にあるETFの過去10年のデータの平均と標準偏差をそれぞれの銘柄の期待収益率とリスクとして具体的に計算をしてみます。

各銘柄の期待収益率(リターン)、標準偏差(リスク)は以下のようになります。

銘柄 期待収益率 標準偏差
ETF-A 16.0 20.2
ETF-B 2.43 6.77
ETF-C 14.5 21.5

それぞれの銘柄同士の相関を以下の表のようにまとめてみました。

ETF-A ETF-B ETF-C
ETF-A 1.0 -0.27 0.67
ETF-B -0.27 1.0 -0.28
ETF-C 0.67 -0.28 1.0

以上の数値例を使って、ランダムに割合を生成して、多数の点をグラフ上にプロットすると次のようなものが出来上がります。

ポートフォリオのリスクとリターン
ポートフォリオのリスクとリターン

この青い領域は100万個の点群からなります。 今回使った数値例の3つのETFからなるポートフォリオは様々な割合で組み合わせると、どんな場合でもこの領域に収まるという事を表しています。

この図は横軸がリスク、縦軸がリターンです。投資家はこの領域内でリスクとリターンを自由に選ぶことができます。 選んだリスクとリターンを得るための割合の組み合わせが一つあり、その割合でポートフォリオを組むことで、長い時間をかければ望みのリスクとリターンが得られます。

では、どのリスクとリターンを選べばいいでしょうか。

効率的フロンティア

青い領域には上の境界と下の境界があるのが見て取れますが、同じリスクに対してリターンが最大になる場合と、最小になる場合の境界を表しています。 同じリスクなら、リターンが大きいほうがいいので、投資家は上の境界線上からしかポートフォリオを作りません。この上の境界線のことを「効率的フロンティア」と呼びます。

シャープレシオ

ポートフォリオを組む場合に、今までの様にリスクのある資産ばかりを組み合わせることはむしろ少なく、貯蓄や国債と言うリスクフリーの資産を組み合わせることの方が実際に近いはずです。 シャープレシオと言うのは単位リスク当たらりのリターンのことで

シャープレシオ=(リスク資産のポートフォリオのリターンー無リスク資産のリターン)÷ポートフォリオのリターン

で表すことができる指標で、投資家はシャープレシオを最大化することで、とったリスクに対して最適なリターンを得ることができたと考えることができます。

マーケットポートフォリオ

シャープレシオを最大にするポートフォリオを「マーケットポートフォリオ」と言います。 一般の家庭だと無リスク資産の代表は貯蓄で今は金利がほぼ0なのでリターン0と考えて良く、本記事で無リスク資産のリターンは0と考えます。 すると、マーケットポートフォリオはグラフの原点(リスク0、リターン0)から青い領域に引いた接線の接点という事になります。

もし、無リスク資産のリターンが0でないならば、リスク0の線上からそのリターンを切片とする接線を引いて接点を求めマーケットポートフォリオとします。

ポートフォリオのリスクとリターン
ポートフォリオのリスクとリターン

今回の数値例ではマーケットポートフォリオは

  • リスク 7%
  • リターン 6.8%

となりました。

またマーケットポートフォリオにおける、それぞれの銘柄の保有割合は

  • ETF-A 23%
  • ETF-B 65%
  • ETF-C 12%

この結果は、元の各ETFのリスクとリターンからみると各銘柄を組み合わせてポートフォリオを組むことで リスクを減らして堅実なリターンを得ることができることを示しています。

資本市場線

先ほど引いた接線を「資本市場線」と呼びます。

今回の計算例ではリスク資産のマーケットポートフォリオのリスクは7%、リターンは6.8%と計算できました。

資本市場線を使うと、無リスク資産とマーケットポートフォリオを組み合わせて得られる、リスクとリターンを見出すことができます。

もし、リスク資産にだけ100%保有した場合はマーケットポートフォリオのリスクとリターンが得られます。

もし、無リスク資産だけ保有したらリスクは0ですが、リターンも0になります。

リスク資産(マーケットポートフォリオでリスク資産を組み合わせたもの)の割合を50%、無リスク資産の割合を50%にしたら得られるリスクとリターンはどのくらいでしょうか?

それは、資本市場線のマーケットポートフォリオと原点との間のところの値になります。

つまり、リスク資産と無リスク資産の保有の割合を決めれば資本市場線に示されるリターンとリスクを自分で選べることになります。

リスク全開が100%リスク資産を保有した場合ですが、マーケットポートフォリオよりも右にも資本市場線は引かれています。 100%リスク資産以上があるのかと言うことですが、実は借金をしてリスク資産を買う事で、このマーケットポートフォリオより右側を選択可能です。 ハイリスクをとってハイリターンを得ることになります。

ポートフォリオの作成の具体例

仮に1万円持っているとします。

繰り返しになりますが

先の各ETF数値例だとマーケットポートフォリオのリスクは7%、リターンは6.8%でした。

そしてマーケットポートフォリをを実現するための各銘柄の保有割合は、ETF-A 23%、ETF-B 65%、ETF-C 12%でした。

そして自分は貯蓄に5000円投資し、リスク資産に5000円投資するとします。

資金を半分、半分にするということです。

この時、各ETFを次の様に購入します

  • ETF-A 1150円
  • ETF-B 3250円
  • ETF-C  600円

するとこのポートフォリオ全体において

  • リスク  7x0.5 = 3.5%
  • リターン 6.8x0.5= 3.4%

となります。かけている数値0.5はリスク資産の割合です。リスク資産を増減した場合はその割合に応じて0.5を変えてください。

これで1万円の元金から1年で350円の利益が得られることが期待できます。ばらつきが3.5%あるのでこれよりリターンが低くなる可能性も0ではありません。

ただし長いこと投資を継続すると期待値に収束しますので継続することが大事です。

また、税金が引かれるので実際はこれ以下になります。

おわりに

今回は現代ポートフォリオ理論の基本的なお話をしました。 また、現代ポートフォリオ理論によって計算された結果を利用して、いかにポートフォリオを組めばよいのかの基本的なお話もできたと思います。

今回はランダムな点群を使って最適値を求めてみました。 本当は最適化問題を解けばよいのですが、自分としてはその問題を追い切れてなかったので簡便だけど時間がかかる方法を選びました。

しかし、100万個の点を使っても計算時間はIntel Core i3 9thgen で20秒ぐらいです。 1000個なら一瞬ですが、結果はあまり変わらないみたいです。もちろん乱数なので場合によっては外れることもあります。

現代ポートフォリオ理論は期待収益率が判ればいいのですが、判らないので昨年までのデータで今年のポートフォリオを組み直すというやり方で果たして効果があるのか疑問な点があります。 実際自分はこのやり方で試していますが、実際のデータで検証していきたいと思っています。

過去のデータでもこの方法が有効かは試せるので、正直データを集めてプログラムにかけるのが面倒なのですが、お盆休みも近いのでできれば試そうと思います。

それにしても、毎年お盆休みに「あれやろう」「これやろう」と野望を描くのですが、ほとんどできないんですよね。

資産を増やすという観点では、以前こんな記事も書きました。当ブログでは人気のない記事ですが、よかったらどうぞ。

blog.rikei-tawamure.com

それでは、また!

参考文献

Wikipediaの他には以下の本も参考にしました。

道具としてのファイナンス

道具としてのファイナンス

  • 作者:石野雄一
  • 発売日: 2014/03/14
  • メディア: Kindle版

付録

今回のグラフ作りに使用したコードです。各銘柄の10年間のデータはこちらを見るとわかります。

%matplotlib inline
#from tqdm import tqdm
import pandas as pd
import numpy as np
from numpy import random
import matplotlib.pyplot as plt
from tqdm.notebook import tqdm as tqdm


def _mpt(e, sigma, rho, N):
    '''
    リターン(期待値)numpy配列
    リスク(標準偏差)numpy配列
    相関numpy配列
    '''
    length=e.size

    Risks=[]
    Returns=[]
    Weights=[]


    for k in tqdm(range(N)):
        w=random.rand(length)
        w=w/w.sum()
        e_sum=0
        sigma_sum=0
        for i in range(length):
            e_sum+=w[i]*e[i]
            for j in range(length):
                sigma_sum+=w[i]*w[j]*sigma[i]*sigma[j]*rho[i,j]
        Risks.append(np.sqrt(sigma_sum)*100)
        Returns.append(e_sum*100)
        Weights.append(w)
    
    return Risks, Returns, Weights 

def mpt(df, N):
    e=np.array(df.mean()/100)
    sigma=np.array(df.std()/100)
    tmp=df.corr()
    length=e.size
    rho=np.zeros((length,length))

    #相関のnumpy配列作成
    for i in range(length):
        for j in range(length):
            rho[i,j]=tmp.iloc[i,j]
    
    return _mpt(e, sigma, rho, N)


#10年分の各銘柄の年ごとの収益率
data={
      'ETF-A':[ 7.5,  -2.8, 27.2, 60.5, 31.8,  1.2,  6.4, 16.8,  -7.9, 19.4],
      'ETF-B':[ 6.3,  15.0,  3.7, -6.6,  8.4,  1.0, -7.0,  0.8,  -2.2,  4.9],
      'ETF-C':[33.4, -22.3, 40.1, 40.4, 29.1, -5.1,  9.5, -7.1,  10.8, 16.0]
     }
    
df=pd.DataFrame(data)


Risks, Returns, Weights = mpt(df, 1000000)

plt.rcParams["font.size"] = 18
plt.figure(figsize=(12,7))    
plt.plot(Risks,Returns,'.', ms=1)
plt.xlim(0,max(Risks))
ymin=(min(Risks) if min(Returns)<0 else 0)
plt.ylim(ymin, max(Returns)*1.1)
plt.xlabel('Risk')
plt.ylabel('Return')
plt.grid()

sharp=np.array(Returns)/np.array(Risks)
maxsharp=sharp.max()
maxindex=sharp.argmax()


plt.plot([0, Risks[maxindex]*100], [0, Returns[maxindex]*100])
plt.plot(Risks[maxindex], Returns[maxindex], 'o', ms=8, c='r')
print('Risk={:.2f}, Return={:.2f}'.format(Risks[maxindex], Returns[maxindex]))
print('{}'.format(Weights[maxindex]*100))
print('#R={:.2f}'.format(maxsharp))
#print('E=', Returns[maxindex]*100)
#print('Sigma=', Risks[maxindex]*100)
plt.show()