ポートフォリオ最適化 : 平均・分散モデルについて

はじめに

本稿では,Markowitzの平均・分散モデルについて説明し,Pythonから使用できるポートフォリオ最適化ライブラリのPyPortfolioOptを用いてサンプルデータに対して解析を行う. なお,ポートフォリオ最適化の説明は文献[枇々木 16]を参考にしている.

準備

収益率

本節では,ある資産に対する「収益率」を定義する. まず,収益率$r$を$0$時点での価格$P _ 0$,$1$時点での価格$P _ 1$を用いて以下で定義する.

$$ \begin{align} r = \frac{P _ 1 - P _ 0}{P _ 0} = \frac{P _ 1}{P _ 0} - 1. \end{align} $$

よって,$r > 0$であれば,プラスの収益となっている.

ここで,$0$時点を現在,$1$時点を将来と考えた場合,$1$時点での価格$P _ 1$は不確実な値となる. よって,$P _ 1$は確率変数として取り扱う. このとき,$P _ 1$を用いて計算される収益率$r$も確率変数となる. 確定値の$r$と区別するため,確率変数としての収益率を以後$\tilde{r}$と表す.

ポートフォリオ収益率

本節では,前節で定義した「収益率」を用いて,ポートフォリオ全体の収益率を表す「ポートフォリオ収益率」を定義する. $n$個の資産でポートフォリオを構築することを考える. 資産$i$への投資金額を$X _ i$,投資金額合計を$X$とする(つまり$\sum _ {i=1}^n X _ i = X$). また,ポートフォリオの収益率を$\tilde{r} _ p$,資産$i$の収益率を$\tilde{r} _ i$とすると, ポートフォリオの損益は各資産と損益の合計となるため, $$ \begin{align} \tilde{r} _ p X = \sum _ {i=1}^n \tilde{r} _ i X _ i \end{align} $$ となる.両辺を$X$で割ることで, $$ \begin{align} \tilde{r} _ p = \sum _ {i=1}^n \tilde{r} _ i x _ i \end{align} $$ を得る.

ポートフォリオ収益率の分布をどう考えるか : リターン尺度(期待収益率)とリスク尺度(分散)

前節で定義されたポートフォリオ収益率は確率変数を含んでいるため,分布として捉えることが可能である. 本節では,分布に対する評価尺度として用いられる「リターン尺度(期待収益率)」,「リスク尺度(分散)」について具体的な計算式含めて解説を行う.

資産$i$の期待収益率を$\bar{r}_i$とすると,ポートフォリオの期待収益率$\bar{r}_p$は,

$$ \begin{align} \bar{r} _ p = \mathbb{E} [\tilde{r} _ p] = \mathbb{E} [\sum _ {i=1}^n \tilde{r} _ i x _ i] = \sum _ {i=1}^n \bar{r} _ i x _ i \end{align} $$ で計算できる.つまり,ポートフォリオ全体の期待収益率は,資産ごとの期待収益率を投資比率で加重和することで計算できる.

一方,資産$i$の収益率の標準偏差を$\sigma _ i$,資産$i$と$j$の収益率の共分散を$\sigma _ {ij}$とすると, ポートフォリオ収益率の分散 $\sigma _ p^2$ は以下で計算される.

$$ \begin{align} \sigma _ p^2 &= \mathbb{E} [(\tilde{r} _ p - \bar{r} _ p)^2] = \mathbb{E} \Bigl[ \Bigl( \sum _ {i=1}^n (\tilde{r} _ i - \bar{r} _ i) x _ i \Bigr)^2 \Bigr] \\
&= \mathbb{E} \Bigl[ \Bigl( \sum _ {i=1}^n (\tilde{r} _ i - \bar{r} _ i) x _ i \Bigr) \Bigl( \sum _ {j=1}^n (\tilde{r} _ j - \bar{r} _ j) x _ j \Bigr) \Bigr] \\
&= \sum _ {i=1}^n \sum _ {j=1}^n \mathbb{E} [(\tilde{r}_i - \bar{r}_i)(\tilde{r}_j - \bar{r}_j)] x _ i x _ j \\
&= \sum _ {i=1}^n \sum _ {j=1}^n \sigma _ {ij} x _ i x _ j \end{align} $$

ここで,相関係数$\rho _ {ij}$を用いると,$\sigma _ {ij} = \rho _ {ij} \sigma _ i \sigma _ j$より,以下で計算できる. $$ \begin{align} \sigma _ p ^ 2 = \sum _ {i=1}^n \sum _ {j=1}^n \rho _ {ij} \sigma _ {i} \sigma _ {j} x _ i x _ j \end{align} $$

相関の少ない資産を組み合わせることで分散を小さくすることができる. これは機械学習のアンサンブル学習と同じ原理である.

平均・分散モデル

本節では,前節で説明を行った「期待収益率」と「分散」のトレードオフを与える定式化の一つである 「平均・分散モデル」について説明を行う.

ポートフォリオ最適化問題は「期待収益率$\bar{r} _ p$が$r _ {E}$以上であるという制約の下で,リスク(分散)$\sigma _ p$を最小化する資産$i$への投資比率$x _i (i = 1, \cdots, n)$を求める」2次計画問題として以下で定式化される.

$$ \begin{align} {\rm minimize}\ & \ \ \sigma_p^2 \\
{\rm s.t.} \ & \ \ \bar{r}_p \geq r_E \\
& \ \ \sum _ {i=1}^n x _ i = 1 \\
& \ \ x _ i \geq 0 (i = 1, \cdots, n) \end{align} $$

Pythonによる実行

ここからは,Installationで説明されているコードを説明する. まず,データをこちらから手元に落としたあと,以下のコードを実行してデータフレームで扱えるようにしてほしい.

import pandas as pd
from pypfopt.efficient_frontier import EfficientFrontier
from pypfopt import risk_models
from pypfopt import expected_returns

# Read in price data
df = pd.read_csv("tests/stock_prices.csv", parse_dates=True, index_col="date")

データには各資産の価格が格納されている.

Fig. 1

ここで,各資産に対する収益率の(標本)平均と各資産間の(標本)共分散行列を以下で計算する.

# Calculate expected returns and sample covariance
mu = expected_returns.mean_historical_return(df)
S = risk_models.sample_cov(df)

以下はそれぞれ収益率の平均,共分散行列のプロットである.

Fig. 2

Fig. 3

これらを用いて, 先ほど説明を行った平均・分散モデルの数理計画問題に適用する. risk free rate $r _ f$を用いて計算されるSharpe Ratio $$ \begin{align} S _ p = \frac{\bar{r} _ p - r _ f}{\sqrt{\sigma _ p ^2}} \end{align} $$ の最大化は以下により行うことができる.

# Optimise for maximal Sharpe ratio
ef = EfficientFrontier(mu, S)
weights = ef.max_sharpe()
ef.portfolio_performance(verbose=True)

先ほど説明を行った平均・分散モデルについて,期待収益率と分散のトレードオフを考慮した効率的フロンティアを以下により描画する(参考 : PyPortfolioOptでポートフォリオ最適化).

trets = np.arange(0.05, 0.50, 0.02)
tvols = []
for tr in trets:
    w = ef.efficient_return(target_return=tr)
    w = pd.Series(w).values
    v = np.sqrt(np.dot(w.T, np.dot(np.array(S), w)))
    tvols += [v]
    
fig = plt.figure(figsize=(16, 8))
ax = fig.add_subplot(1, 1, 1)
ax.scatter(tvols, trets)
ax.set_xlabel('volatility')
ax.set_ylabel('expected return')
ax.grid(True)
plt.show()

Fig. 1

まとめ

本稿では,平均・分散モデルの説明とPyPortfolioOptにより投資比率を求める実験を行った. ポートフォリオ最適化は今回紹介したモデル以外にも様々なvariantが存在するため,これからいろいろ知っていきたいと考えている.

参考文献