CAPM#
概要#
CAPM ( 資本資産価格モデル :capital asset pricing model)は、市場均衡価格における個別銘柄の期待リターンと、市場に広く分散投資した「市場ポートフォリオ」の関係性を表したモデル。
モデル#
均衡で(期待効用最大化を解いた下で)危険資産の期待リターンは以下のように決まる
ここで\(\boldsymbol{\beta}\)をベータリスクまたはベータとよび、\(\mu_\mathcal{M}\)は市場ポートフォリオの期待リターンである
このような均衡における個別銘柄の期待リターンとベータの関係はとよばれる。
含意#
CAPMの含意は以下の2つ
市場ポートフォリオは効率的である
→ 市場に広く分散投資するインデックス投資が効率的
均衡で個別銘柄の期待リターンがすべて市場ポートフォリオに比例する形で決まる
個別銘柄への投資は市場ポートフォリオより効率的にはならない
限界#
CAPMは強い仮定を置いて市場のモデルを簡略化している
CAPMのみでは説明できない事象があり、3 Factor modelや5 Factor modelなど別のファクターを入れたモデルへと派生していった
期待効用最大化#
与えられた期待リターンのもとでボラティリティを最小化するポートフォリオは効率的フロンティア上のポートフォリオを選択すればよい。 効率的フロンティア上のどの点を選ぶのかは投資家の選好によって決まるが、なぜその点が選ばれるのかを考えたい。
効用関数#
投資家がポートフォリオのリターン\(R_P\)から得る満足度を効用(utility)といい、その関数(効用関数)を\(U(R_P)\)で表す。
効用関数には代表的なものだけでもいくつかの種類がある。
指数効用
ここで\(\gamma_e > 0\)は定数で、絶対的リスク回避度(absolute risk aversion)と言われる。
べき効用
\(\gamma_p\)は定数で、相対的リスク回避度(relative risk aversion)と言われる。\(\gamma_p\)が1に近づくとき、効用関数は対数型
になることが知られている。
期待効用最大化問題#
リターン\(R_P\)が確率変数なので、期待リターンでおおよその「あたり」をつける。期待効用は以下のように定義される。
ここで\(\pi_0\)は安全資産のポートフォリオ・ウェイトで、\(\boldsymbol{\pi}\)は危険資産のポートフォリオ・ウェイトである。
であるため、ポートフォリオ・リターンはポートフォリオ・ウェイトによって決まるため、ウェイトを引数としている。
期待効用の最大化が投資家の目標となる。
ただし、ポートフォリオ・ウェイトは\(\pi_0 + \boldsymbol{\pi}^\top \boldsymbol{1} = 1\)の制約を満たさなければならない。
近似手法#
Markowitz(2014)によると、期待効用最大化問題を直接解く代わりに、以下の期待効用の最大化を行うことで近似解が得られる
ここで\(\gamma > 0\)は定数。
先述の効用関数は次のように近似できる
元の効用関数 |
近似 |
|
|---|---|---|
指数効用 |
\(U(R_P) = 1 - e^{-\gamma_e R_P}\) |
\(\gamma_e(\mu_P-\frac{1}{2}\gamma_e(\sigma^2_P+\mu^2_P))\) |
べき効用 |
\(U(R_P) = \frac{(1 + R_P)^{1-\gamma_p} - 1}{1 - \gamma_p}\) |
\(\mu_P-\frac{1}{2}\gamma_p(\sigma^2_P+\mu^2_P)\) |
対数効用 |
\(U(R_p) = \log (1 + R_P)\) |
\(\mu_P-\frac{1}{2}(\sigma^2_P+\mu^2_P)\) |
この近似のメリットは効率的フロンティア上のどの点を選択することが期待効用最大化になるのかがはっきりわかること。
これと似た期待効用に 平均分散型の期待効用関数 がある
これは期待リターン高いほど効用が多くなり、ボラティリティが高いほど効用が減るので直感的である。リスク回避的な投資家ほど\(\gamma\)が大きくなると考えられる。
無差別曲線#
同じ期待効用をもたらす期待リターンとボラティリティの組み合わせで描かれた曲線を無差別曲線と呼ぶ。
実現可能領域内で最も高い効用をもたらす期待リターンとボラティリティのポートフォリオが期待効用最大化問題の解である。
期待効用を最大化する期待リターンとボラティリティは
である(\(\kappa\)はシャープ・レシオ)。
また、平均分散型の期待効用を最大化する安全資産と危険資産のポートフォリオ・ウェイトはそれぞれ
で、やはり\(\gamma\)が大きいほど危険資産へのウェイトが減る。
市場の均衡#
危険資産の平均分散フロンティアに安全資産を加えたものが直線で描かれるが、市場で取引されるすべての危険資産を含むことを強調した表現としてこの直線を資本市場線(capital market line, CML)という。
また、資本市場線における接点ポートフォリオを市場ポートフォリオ(market portfolio)という。
また、ここで描かれる無差別曲線は代表的投資家(representative investor)とよばれる、市場に参加するすべての投資家の富を合算した仮想的な存在である。
CAPM#
代表的投資家の期待効用が平均分散型で与えられることを仮定する。
ただし、\(\gamma_R > 0 \)は定数。このとき均衡で(期待効用最大化を解いた下で)危険資産の期待リターンは以下のように決まることが知られている
ここで\(\boldsymbol{\beta}\)をベータリスクまたはベータとよび、
で定義する。\(\mu_\mathcal{M}\)は市場ポートフォリオの期待リターン、\(\sigma_{m,\mathcal{M}}\)は危険資産と市場ポートフォリオの共分散である。
このような均衡における個別銘柄の期待リターンとベータの関係はCAPM(資本資産価格モデル:capital asset pricing model)とよばれる。
CAPMの含意は「均衡で個別銘柄の期待リターンがすべて市場ポートフォリオに比例する形で決まる」こと。
個別銘柄は市場ポートフォリオに比例する#
経済学的な解釈としては、ある銘柄\(S_m\)の期待リターン
を書き換えれば
となり、\(\mu_0\)と\(\mu_{\mathcal{M}}\)を\(1 - \beta_m: \beta_m\)の比で按分した格好になっている。
\(\beta_m\)が1を超えて大きくなると期待リターンも大きくなるが、その分リスクも大きくなる。つまりベータは個別銘柄のリスクを表す。
また、
は個別銘柄のリスク・プレミアム(\(\mu_m - \mu_0\))が市場ポートフォリオのリスク・プレミアム(\(\mu_{\mathcal{M}} - \mu_0\))に比例するとも解釈できる。
個別銘柄は市場ポートフォリオを上回らない#
市場ポートフォリオのシャープ・レシオ
を使うと
であることから、銘柄\(m\)の期待リターン\(\mu_m\)は
と表すことができ、左辺に\(\sigma_m/\sigma_m\)を乗じると
ここで
である。
さらに
と整理できる。相関係数\(\rho_{m, \mathcal{M}}\)は最大1であるため、この式は個別銘柄のシャープ・レシオは市場ポートフォリオのシャープ・レシオを超えることは不可能であることを意味する。
線形回帰との関係性#
CAPMの主張の一つは「個別銘柄のリスク・プレミアムは市場ポートフォリオのリスク・プレミアムに比例する」というものだ。しかし、リスク・プレミアムは直接観察できず、観察できるのは株価などの価格なので、価格をリターンに加工し、リターンから安全資産の利回りを差し引いて推定する必要がある。
さらに、売値と買値に乖離がある場合もある(その場合は仲値という買値と売値の中間の価格をとりあえずの価格とすることが多い)
観測できる価格は確率変数の実現値であると考え、その背後にある規則性を観察したいと考える。 例えば市場ポートフォリオと個別銘柄とのリスク・プレミアムの関係をデータから探りたい場合は
のようにして\(f(\cdot)\)を推定する。 なお、\(\tilde{R}_m = R_m - \mu_0, \tilde{R}_\mathcal{M} = R_\mathcal{M} - \mu_0\)であり\(\epsilon_m\)は観測の誤差を表す。誤差は平均がゼロで\(\tilde{R}_\mathcal{M}\)とは無相関な確率変数とする。
もしデータから\(f(\cdot) = \beta_m x\)という関係が特定できたならば、上の式は
となり、両辺の期待値はCAPMそのものになる。分散は
で、危険資産\(S_m\)のリスクは市場ポートフォリオに起因するリスクとそれ以外の(\(S_m\)に固有の)リスクに分解できる。そこで\(\beta_m \sigma_\mathcal{M}\)をシステマティック・リスク(systematic risk)、\(\sigma_{\epsilon_m}\)を固有リスク(idiosyncratic risk)と呼ぶ。
アルファ#
なお、線形回帰で推定した際、
標本平均・標本分散・標本共分散はそれぞれの真値をよく近似しているはずで\(\hat{\beta}_m \approx \beta_m\)なので、切片項\(\hat{\alpha}_m\)がゼロならば上の式はCAPMの近似となる。しかし、時折\(\hat{\alpha}_m\)はゼロにならないことがある。
ゼロでない\(\hat{\alpha}_m\)を組み込んだポートフォリオはそれ自体がアルファをもつことになる。正のアルファはポートフォリオのパフォーマンスを測る尺度にもなりうる。
このアルファをしばしばジェンセンのアルファ(Jensen’s alpha)という。
データによる推定#
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import yfinance as yf
start = "2016-01-01"
symbol_0 = "^TNX" # 米国10年もの国債
symbol_M = "^GSPC" # S&P500
symbol_m = "MCD" # マクドナルド
symbols = [symbol_0, symbol_M, symbol_m]
df_price = yf.download(symbols, start=start)["Adj Close"]
df_price
/tmp/ipykernel_4336/2605440001.py:12: FutureWarning: YF.download() has changed argument auto_adjust default to True
df_price = yf.download(symbols, start=start)["Adj Close"]
[ 0% ]
[**********************67%******* ] 2 of 3 completed
[*********************100%***********************] 3 of 3 completed
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
File ~/work/notes/notes/.venv/lib/python3.10/site-packages/pandas/core/indexes/base.py:3812, in Index.get_loc(self, key)
3811 try:
-> 3812 return self._engine.get_loc(casted_key)
3813 except KeyError as err:
File pandas/_libs/index.pyx:167, in pandas._libs.index.IndexEngine.get_loc()
File pandas/_libs/index.pyx:196, in pandas._libs.index.IndexEngine.get_loc()
File pandas/_libs/hashtable_class_helper.pxi:7088, in pandas._libs.hashtable.PyObjectHashTable.get_item()
File pandas/_libs/hashtable_class_helper.pxi:7096, in pandas._libs.hashtable.PyObjectHashTable.get_item()
KeyError: 'Adj Close'
The above exception was the direct cause of the following exception:
KeyError Traceback (most recent call last)
Cell In[6], line 12
9 symbol_m = "MCD" # マクドナルド
11 symbols = [symbol_0, symbol_M, symbol_m]
---> 12 df_price = yf.download(symbols, start=start)["Adj Close"]
13 df_price
File ~/work/notes/notes/.venv/lib/python3.10/site-packages/pandas/core/frame.py:4112, in DataFrame.__getitem__(self, key)
4110 if is_single_key:
4111 if self.columns.nlevels > 1:
-> 4112 return self._getitem_multilevel(key)
4113 indexer = self.columns.get_loc(key)
4114 if is_integer(indexer):
File ~/work/notes/notes/.venv/lib/python3.10/site-packages/pandas/core/frame.py:4170, in DataFrame._getitem_multilevel(self, key)
4168 def _getitem_multilevel(self, key):
4169 # self.columns is a MultiIndex
-> 4170 loc = self.columns.get_loc(key)
4171 if isinstance(loc, (slice, np.ndarray)):
4172 new_columns = self.columns[loc]
File ~/work/notes/notes/.venv/lib/python3.10/site-packages/pandas/core/indexes/multi.py:3059, in MultiIndex.get_loc(self, key)
3056 return mask
3058 if not isinstance(key, tuple):
-> 3059 loc = self._get_level_indexer(key, level=0)
3060 return _maybe_to_slice(loc)
3062 keylen = len(key)
File ~/work/notes/notes/.venv/lib/python3.10/site-packages/pandas/core/indexes/multi.py:3410, in MultiIndex._get_level_indexer(self, key, level, indexer)
3407 return slice(i, j, step)
3409 else:
-> 3410 idx = self._get_loc_single_level_index(level_index, key)
3412 if level > 0 or self._lexsort_depth == 0:
3413 # Desired level is not sorted
3414 if isinstance(idx, slice):
3415 # test_get_loc_partial_timestamp_multiindex
File ~/work/notes/notes/.venv/lib/python3.10/site-packages/pandas/core/indexes/multi.py:2999, in MultiIndex._get_loc_single_level_index(self, level_index, key)
2997 return -1
2998 else:
-> 2999 return level_index.get_loc(key)
File ~/work/notes/notes/.venv/lib/python3.10/site-packages/pandas/core/indexes/base.py:3819, in Index.get_loc(self, key)
3814 if isinstance(casted_key, slice) or (
3815 isinstance(casted_key, abc.Iterable)
3816 and any(isinstance(x, slice) for x in casted_key)
3817 ):
3818 raise InvalidIndexError(key)
-> 3819 raise KeyError(key) from err
3820 except TypeError:
3821 # If we have a listlike key, _check_indexing_error will raise
3822 # InvalidIndexError. Otherwise we fall through and re-raise
3823 # the TypeError.
3824 self._check_indexing_error(key)
KeyError: 'Adj Close'
# 日次リターンにする
df_rate = df_price[[symbol_M, symbol_m]].pct_change(1)
# 金利を足す
df_rate[symbol_0] = df_price[symbol_0]
df_rate
| ^GSPC | MCD | ^TNX | |
|---|---|---|---|
| Date | |||
| 2016-01-04 | NaN | NaN | 2.245 |
| 2016-01-05 | 0.002012 | 0.013778 | 2.248 |
| 2016-01-06 | -0.013115 | -0.006711 | 2.177 |
| 2016-01-07 | -0.023700 | -0.023142 | 2.153 |
| 2016-01-08 | -0.010838 | -0.001556 | 2.130 |
| ... | ... | ... | ... |
| 2023-02-13 | 0.011449 | 0.014404 | 3.717 |
| 2023-02-14 | -0.000280 | 0.001540 | 3.761 |
| 2023-02-15 | 0.002773 | -0.000187 | 3.809 |
| 2023-02-16 | -0.013789 | -0.002739 | 3.843 |
| 2023-02-17 | -0.002767 | 0.015649 | 3.828 |
1795 rows × 3 columns
# リスク・プレミアム
df_rp = pd.DataFrame({
# 金利はパーセント表示の年率なので、0.01をかけて日割りしておく
symbol_M: df_rate[symbol_M] - df_rate[symbol_0] * 0.01 / 255,
symbol_m: df_rate[symbol_m] - df_rate[symbol_0] * 0.01 / 255,
}).dropna()
df_rp
| ^GSPC | MCD | |
|---|---|---|
| Date | ||
| 2016-01-05 | 0.001924 | 0.013690 |
| 2016-01-06 | -0.013201 | -0.006797 |
| 2016-01-07 | -0.023785 | -0.023226 |
| 2016-01-08 | -0.010922 | -0.001640 |
| 2016-01-11 | 0.000769 | 0.010393 |
| ... | ... | ... |
| 2023-02-13 | 0.011303 | 0.014259 |
| 2023-02-14 | -0.000428 | 0.001393 |
| 2023-02-15 | 0.002624 | -0.000337 |
| 2023-02-16 | -0.013939 | -0.002889 |
| 2023-02-17 | -0.002918 | 0.015499 |
1792 rows × 2 columns
df_rp.plot.scatter(x=symbol_M, y=symbol_m)
plt.show()
from sklearn.model_selection import train_test_split
# shuffle=Falseにすることで新しいものだけをtestにできる
df_train, df_val = train_test_split(df_rp, test_size=0.2, shuffle=False)
X_train = df_train[[symbol_M]]
X_val = df_val[[symbol_M]]
y_train = df_train[symbol_m]
y_val = df_val[symbol_m]
推定されたαとβは以下のようになった。
from sklearn.linear_model import LinearRegression
reg = LinearRegression()
reg.fit(X_train, y_train)
print(f"α={reg.intercept_:.3g}, β={reg.coef_[0]:.3g}")
α=0.000193, β=0.776
fig, ax = plt.subplots()
df_rp.plot.scatter(x=symbol_M, y=symbol_m, ax=ax)
ax.plot(X_train, reg.predict(X_train), color="dimgray")
fig.show()
なおHold-out誤差は次のようになった。
日本株の場合#
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import yfinance as yf
start = "2016-01-01"
symbol_M = "^N225" # 日経平均
symbol_m = "9983.T" # ファーストリテイリング
symbols = [symbol_M, symbol_m]
df_price = yf.download(symbols, start=start)["Adj Close"]
#日本国債の金利(年率)を財務省から取得
url = "https://www.mof.go.jp/english/policy/jgbs/reference/interest_rate/historical/jgbcme_all.csv"
df_bond_yield = pd.read_csv(url, header=1, index_col="Date", na_values="-", parse_dates=True)
symbol_0 = '10Y'
df_price[symbol_0] = df_bond_yield[symbol_0].copy()
# 日次リターンにする
df_rate = df_price[[symbol_M, symbol_m]].pct_change(1)
# 金利を足す
df_rate[symbol_0] = df_price[symbol_0]
# リスク・プレミアム
df_rp = pd.DataFrame({
# 金利はパーセント表示の年率なので、0.01をかけて日割りしておく
symbol_M: df_rate[symbol_M] - df_rate[symbol_0] * 0.01 / 255,
symbol_m: df_rate[symbol_m] - df_rate[symbol_0] * 0.01 / 255,
}).dropna()
df_rp
[*********************100%***********************] 2 of 2 completed
| ^N225 | 9983.T | |
|---|---|---|
| Date | ||
| 2016-01-05 | -0.004182 | -0.005422 |
| 2016-01-06 | -0.009952 | -0.006441 |
| 2016-01-07 | -0.023316 | -0.027891 |
| 2016-01-08 | -0.003914 | -0.023312 |
| 2016-01-12 | -0.027074 | -0.013381 |
| ... | ... | ... |
| 2023-01-25 | 0.003492 | 0.001664 |
| 2023-01-26 | -0.001197 | -0.001439 |
| 2023-01-27 | 0.000705 | 0.015369 |
| 2023-01-30 | 0.001837 | 0.002655 |
| 2023-01-31 | -0.003895 | -0.003958 |
1727 rows × 2 columns
from sklearn.linear_model import LinearRegression
reg = LinearRegression()
reg.fit(X_train, y_train)
print(f"α={reg.intercept_:.3g}, β={reg.coef_[0]:.3g}")
df_rp.plot.scatter("^N225", "9983.T")
<AxesSubplot:xlabel='^N225', ylabel='9983.T'>
CAPMのまとめ#
仮定#
全ての投資家は平均分散分析によりポートフォリオを選択する。
全ての投資家は全ての金融資産の収益率の平均と分散について同一の予想を持つ。
金融市場が完全市場である。
無リスク資産が存在する。
含意#
1. マーケット・ポートフォリオは効率的#
オリジナルのCAPM
安全資産が存在するとき、市場の均衡状態においてマーケット・ポートフォリオは接点ポートフォリオと一致する。したがって、マーケット・ポートフォリオは効率的ポートフォリオである。
より一般化したものもある
ゼロベータCAPM(zero-beta CAPM)
安全資産の有無にかかわらず、市場の均衡状態においてマーケット・ポートフォリオは効率的ポートフォリオである(Black et al. 1972)
2. 個別銘柄はマーケット・ポートフォリオに比例する#
CAPMの限界#
CAPMだけでは説明できないアノマリーの存在が指摘され、市場ポートフォリオのリスク・プレミアム以外の要因(小型株効果やバリュー株効果)を含めた3-factor modelなどが提案されていった
参考#
吉川 大介(2022)『データ駆動型ファイナンス』、共立出版。
小林 孝雄(2009)『新・証券投資論 1 理論篇』、日本経済新聞出版社