Otama's Playground

AIで遊んだ結果などをつらつら載せていきます。

ブラック・リッターマン法による投資ポートフォリオ最適化: 基本概念とPythonでの実践

今日はブラック・リッターマン法という手法を使って、投資ポートフォリオの資産配分を最適化する方法を解説します。この方法では、市場のデータと投資家の見解を組み合わせて、期待リターンを計算します。具体的には、マーケットの均衡リターンに投資家の予測をブレンドすることで、より精度の高いポートフォリオを作成します。この記事では、実際にPythonコードを使用してブラック・リッターマン法を適用し、その結果を確認していきます。

ブラック・リッターマン法

ブラック・リッターマン法 is 何

ブラック・リッターマン法(Black-Litterman Model)は、投資ポートフォリオの資産配分を最適化するためのモデルで、フィッシャー・ブラックとロバート・リッターマンによって開発されました。このモデルは、マーケットのデータ(例えば、株価や債券の利回り)と投資家の見解(アナリストの予測など)を組み合わせて、期待リターンを計算します。この期待リターンを用いて平均分散最適化を行えば、投資家の見解を踏まえたポートフォリオを作成することが可能になります。

ブラック・リッターマン法の基本概念・単語など

項目 説明
市場の均衡リターン(Equilibrium returns) マーケットの期待リターン。市場全体の評価基準として使用。
投資家の見解 投資家が持つ予測や見解をモデルに反映。特定の資産や資産グループのリターンに対する期待値や確信度に基づく。
リスク許容度(Risk Aversion) 投資家がリスクを嫌う程度を表す指標。これは通常、経済学や金融の分野で使用され、投資家がどの程度リスクを取ることを嫌がるかを数値で示す。

リスク許容度(risk aversion)について

ここを理解してないと大事故になりそうなので説明を挟みます。

一般的には、risk aversionは以下のように表されます。(0より小さい値は理論上あり得ません)

  • 0 < delta < 1: 非常にリスク許容度が高い(リスクをあまり恐れない)
  • 1 < delta < 10: 通常の範囲でのリスク許容度
  • delta > 10: 非常にリスク回避的(リスクを非常に嫌う)

ブラック・リッターマン法を使うステップ

  1. マーケットポートフォリオから均衡リターンを求める
  2. 投資家の見解を得る
  3. ブラック・リッターマン方程式を使って、均衡リターンに投資家の見解をブレンドする

ステップ1: マーケットポートフォリオから均衡リターンを求める

「均衡リターン」と呼ばれる、何も特別な予測がない場合に資産の期待リターンがどれくらいになるかを計算します。ここでマーケットポートフォリオという各資産にそれぞれの時価総額の比率に応じて投資したと仮定したポートフォリオを使用します。マーケットポートフォリオを使うと何が嬉しいのか、などは以下の記事に整理してあります。 マーケットポートフォリオの基本と計算方法:投資リスクを減らす秘訣 - Otama's Playground

均衡リターンは以下の式を用いて求めます。

 \Pi = \lambda \cdot \Sigma \cdot w


\begin{align*}
\Pi & : \text{均衡リターン} \\
\lambda & : \text{risk aversion(リスク回避度)} \\
\Sigma & : \text{共分散行列(各資産のリスクの関係を示す行列)} \\
w & : \text{マーケットポートフォリオの資産配分}
\end{align*}

今回は実際のデータを直接反映するような計算方法にしましたが、ここで代わりにCAPMを使用すると、より理論に基づいた計算が可能になります。CAPMの詳細は以下の記事で紹介してるので興味がある方は読んでみてください

CAPMのメリットとデメリット:投資判断に役立つモデル - Otama's Playground

ステップ2: 投資家の見解を取り入れる

次に、投資家やアナリスト(自分のでも良い、機械学習でもよい誰か)の見解を考慮します。例えば、特定の企業の株価が上がると予測している場合、その予測をモデルに組み込みます。

  • 投資家の予測: どの資産がどれくらいのリターンを上げるかの予測を設定します。
  • 不確実性の設定: その予測がどれくらい正確か(どれくらいの確信があるか)を設定します。

ここで取得した値についてはステップ3の計算で使用します。

ステップ3: ブラック・リッターマン方程式を使って、各資産の期待リターンを計算

ブラック・リッターマン方程式を使って、マーケットの情報と投資家の見解を組み合わせた期待リターンを計算します。この方程式は以下のような形をとります:


E(R) = \left( (\tau \cdot \Sigma)^{-1} + P^T \cdot \Omega^{-1} \cdot P \right)^{-1} \left( (\tau \cdot \Sigma)^{-1} \cdot \Pi + P^T \cdot \Omega^{-1} \cdot Q \right)



\begin{align*}
&E(R): \text{最終的な資産の期待リターン} \\
&\tau: \text{スケーリングファクター(通常、0.025などの小さい値)} \\
&\Omega: \text{見解の不確実性を表す行列(通常、対角行列として設定)} \\
&Q: \text{投資家の見解による期待リターン} \\
&P: \text{見解行列(投資家の見解が影響する資産を示す行列)} \\
\end{align*}

式が複雑で少し吐きそうになりますが、パーツに分けて考えるとまあそうなのかなって感じになるかと思うので、パーツ毎の解説もしておきます。(さらに吐きそうになったら申し訳ないです...)

左半分は、市場の均衡リターンと投資家の見解の不確実性を統合し、市場情報と投資家の見解を統合した全体的な情報の信頼度を計算しています

  •  (\tau\Sigma)^{-1}
    • 最終的な信頼度のうち市場均衡リターンの不確実性が寄与する分を計算します。
    • 共分散行列 \Sigmaに市場均衡リターンの不確実性 \tauを掛けます
  •  P^{T} \Omega^{-1} P: 投資家の見解の信頼度の寄与
    • 最終的な信頼度のうち投資家の見解の不確実性が寄与する分を計算します。
    • 見解マトリックス( P)とその不確実性を表す共分散行列( \Omega)で計算
  •  \left( \left( \tau \Sigma \right)^{-1} + P^{T} \Omega^{-1} P \right)^{-1}: 全体の逆行列
    • 市場均衡リターンの信頼度と投資家の見解の信頼度を加算したものの逆行列
    • 事前の市場均衡リターンと投資家の見解の信頼度を統合した新しい情報の信頼度を表します

右半分は、事前の市場情報と投資家の見解を統合した新しい期待リターンを計算しています。

  •  (\tau\Sigma)^{-1} \pi:
    • 最終的な期待リターンの内、市場均衡リターンが寄与する分を計算します
    • 均衡リターンへの重みづけ (\tau\Sigma)^{-1} \pi (均衡リターン)をかけています。
  •  P^{T} \Omega^{-1} Q: 投資家の見解の寄与
    • 最終的な期待リターンの内、投資家の見解が寄与する分を計算します
    • 投資家の見解ベクトル( Q)に P^{T} \Omega^{-1} (見解の重み)をかけています
  • [tex: \left( (\tau \Sigma)^{-1} \pi + PT \Omega^{-1} Q \right)]: 全体
    • 市場均衡リターンと投資家の見解を統合して、新しい期待リターンを計算しています

最終的に、 \text{(ブレンドされた不確実性)} \times \text{(ブレンドされた期待リターン)}を計算することで最終的な期待リターンが得られます。ここら辺はベイズ統計の原理に基づいているみたいです。

※ベイズ統計とは、事前の知識(事前分布)と新しいデータ(観測データ)を統合して、更新された知識(事後分布)を導出する方法

実際にPythonで計算してみる

簡単のためかなり簡易化した形で計算します。

  • マーケットポートフォリオに全世界株式と全世界債券のみがあるとする

ステップ1: マーケットの情報を集める

以下のように仮定します。(本来はCAPMとかを使用して頑張って計算する)

全世界株式と全世界債券の期待リターンが5%と2%
全世界株式と全世界債券の割合が60%:40%
 
\text{共分散行列} = \begin{pmatrix}
0.1 & 0.02 \\
0.02 & 0.08
\end{pmatrix}

このとき均衡リターンを計算するスクリプトは以下のようになります。

import numpy as np

# 市場データの仮定
expected_market_returns = np.array([0.05, 0.02])  # 株式と債券の期待リターン
market_weights = np.array([0.60, 0.40])  # 株式と債券の割合
cov_matrix = np.array([[0.1, 0.02], 
                       [0.02, 0.08]])  # 共分散行列

# リスク回避係数の設定
risk_aversion = 2.5  # リスク回避係数の仮定(適切に調整可能)

# 市場均衡ポートフォリオの期待リターン (\Pi)
pi = risk_aversion * np.dot(cov_matrix, market_weights)

print("市場均衡ポートフォリオの期待リターン (Pi):", pi)

実行結果

市場均衡ポートフォリオの期待リターン (Pi): [0.17 0.11]

現実の値とは離れてるかもしれませんが、仮定の話なので許して...

ステップ2: 投資家の見解を取り入れる

投資家の見解を設定します。ここでは、株式が10%、債券が3%のリターンを上げると予測します。

# 投資家の予測
investor_views = np.array([0.10, 0.03])

# 見解に対する不確実性(共分散行列)
omega = np.diag([0.04, 0.02])  # 予測の不確実性を反映

# 見解の影響を示す行列(株式と債券に関する予測)
P = np.array([[1, 0], 
              [0, 1]])

ステップ3: ブラック・リッターマン方程式を使って、各資産の期待リターンを計算

# スケーリングファクターの設定
tau = 0.025

# 最終期待リターンの計算
inv_cov_matrix = np.linalg.inv(tau * cov_matrix)
omega_inv = np.linalg.inv(omega)
PT_omega_inv_P = np.dot(np.dot(P.T, omega_inv), P)

middle_matrix = np.linalg.inv(inv_cov_matrix + PT_omega_inv_P)
part_one = np.dot(inv_cov_matrix, pi)
part_two = np.dot(np.dot(P.T, omega_inv), investor_views)
final_expected_returns = np.dot(middle_matrix, (part_one + part_two))

print("最終的な期待リターン:", final_expected_returns)

実行結果

最終的な期待リターン: [0.16418829 0.10199786]

ステップ1の結果と比べて、投資家の見解を踏まえて少し補正が入ってるのがわかると思います。

最終的なコード

import numpy as np

# 市場データの仮定
expected_market_returns = np.array([0.05, 0.02])  # 株式と債券の期待リターン
market_weights = np.array([0.60, 0.40])  # 株式と債券の割合
cov_matrix = np.array([[0.1, 0.02], 
                       [0.02, 0.08]])  # 共分散行列

# リスク回避係数の設定
risk_aversion = 2  # リスク回避係数の仮定(適切に調整可能)

# 市場均衡ポートフォリオの期待リターン (\Pi)
pi = risk_aversion * np.dot(cov_matrix, market_weights)

# 投資家の予測
investor_views = np.array([0.10, 0.03])

# 見解に対する不確実性(共分散行列)
omega = np.diag([0.04, 0.02])  # 予測の不確実性を反映

# 見解の影響を示す行列(株式と債券に関する予測)
P = np.array([[1, 0], 
              [0, 1]])

# スケーリングファクターの設定
tau = 0.025

# 最終期待リターンの計算
inv_cov_matrix = np.linalg.inv(tau * cov_matrix)
omega_inv = np.linalg.inv(omega)
PT_omega_inv_P = np.dot(np.dot(P.T, omega_inv), P)

middle_matrix = np.linalg.inv(inv_cov_matrix + PT_omega_inv_P)
part_one = np.dot(inv_cov_matrix, pi)
part_two = np.dot(np.dot(P.T, omega_inv), investor_views)
final_expected_returns = np.dot(middle_matrix, (part_one + part_two))

print("市場均衡ポートフォリオの期待リターン (Pi):", pi)
print("最終的な期待リターン:", final_expected_returns)

最後に

ここまででブラック・リッターマン法によって補正された期待リターンを求めることができました。この期待リターンを使用して平均分散最適化を行うことで、最適化された効率の良いポートフォリオを作成することができます。

計算自体は単純なのでそんなにコードは必要ありませんでした。今回は端折りましたが、どちらかというと均衡リターンを求める部分、投資家の見解を持ってくる部分が鬼門になるのかなと思います。気が向いたらそこらへんも調べてまとめてみようと思うので、見つけたらまた読みにきていただけると嬉しいです。

ポートフォリオ構築に関連する他のモデルを知りたい方は下記のリンク集をぜひご活用ください。

otama-playground.com