σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
uantCraft Academyロードマップ
Ctrl K
AO
+1.2k 人の学習者
ログイン参加する ↗
ロードマップ
AO
+1.2k 人の学習者
ログイン
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Python ロードマップ›モジュール 5 · ポートフォリオ最適化›トピック 5.4·~55 分中級

平均分散最適化

ロードマップ上の位置モジュール 5/11 · トピック 4/5
5.4 平均分散最適化
—ラボスコア— / 100合計XP—連続日数—

リターンとリスクを1つの数に

最小分散はリターンを無視します。平均・分散最適化(マーコウィッツ)は両方を使います。投資家は高い期待リターン w @ mu と低い分散 w @ cov @ w を望みます。両者を天秤にかける簡単な方法が効用 w @ mu - 0.5 * lambda * w @ cov @ w で、lambda はリスク回避度です。大きいほど、分散1単位のコストが重くなります。同じ見通しでも lambda が違う2人の投資家は違うポートフォリオを選び、それぞれの最良のポートフォリオは滑らかな凹関数の最大点です。

import numpy as np

mu = np.array([0.08, 0.05, 0.10])                         # expected annual returns
cov = np.array([[0.0400, 0.0060, 0.0100],
                [0.0060, 0.0100, 0.0020],
                [0.0100, 0.0020, 0.0225]])

def utility(weights, mu, cov, risk_aversion):
    return weights @ mu - 0.5 * risk_aversion * weights @ cov @ weights

equal = np.full(3, 1 / 3)
print(round(float(equal @ mu), 4), round(float(equal @ cov @ equal), 4))      # 0.0767 0.0121
print(round(float(utility(equal, mu, cov, 4.0)), 4))                          # 0.0526

与えられたリスク回避度での最良ポジション

予算制約がない場合(残りの資金は無リスク金利を稼ぎ、ここでは超過リターンでゼロとみなす)、最良のポジションは勾配 mu - lambda * cov @ w がゼロになる点で、w = cov^-1 * mu / lambda です。コードでは np.linalg.solve(cov, mu) / lambda です。常識どおりにスケールし、リスク回避度が2倍ならポジションは半分です。ウェイトの合計は必要なだけの値になり、残りの 1 - w.sum() は現金です。

# The best position for several risk aversions: more aversion, smaller bets
import numpy as np

mu = np.array([0.08, 0.05, 0.10])
cov = np.array([[0.0400, 0.0060, 0.0100],
                [0.0060, 0.0100, 0.0020],
                [0.0100, 0.0020, 0.0225]])

for aversion in (5.0, 10.0, 20.0):
    w = np.linalg.solve(cov, mu) / aversion
    print(aversion, np.round(w, 3), "invested", round(float(w.sum()), 3))

接点ポートフォリオ

無リスク資産があるとき、すべての投資家は同じリスク資産の組み合わせを、量だけ変えて持ちます。その組み合わせはシャープ・レシオ (w @ mu - rf) / sqrt(w @ cov @ w) が最大のもの、すなわち接点ポートフォリオで、w は cov^-1 * (mu - rf) に比例し、合計1に直したものです。慎重な投資家は資金の一部だけをそこに入れて残りを現金にし、大胆な投資家は借り入れてもっと持ちます。どれだけのリスクを取るかと、どのリスク資産を持つかは別の問題です。

# The tangency portfolio: no other mix of the three assets has a higher Sharpe ratio
import numpy as np

mu = np.array([0.08, 0.05, 0.10])
cov = np.array([[0.0400, 0.0060, 0.0100],
                [0.0060, 0.0100, 0.0020],
                [0.0100, 0.0020, 0.0225]])
rf = 0.02

x = np.linalg.solve(cov, mu - rf)
best = x / x.sum()

def sharpe(w):
    return (w @ mu - rf) / np.sqrt(w @ cov @ w)

rng = np.random.default_rng(1)
trials = rng.normal(size=(2000, 3))
trials = trials / trials.sum(axis=1, keepdims=True)
print(np.round(best, 4), round(float(sharpe(best)), 4))
print(round(max(float(sharpe(w)) for w in trials), 4))      # the best of 2000 random mixes comes close, never above

目標リターンを達成する

別の問い方として、合計が1で期待リターンが決まっているポートフォリオのうち、分散が最小のものはどれでしょうか。制約が2つあるので、解は解いた2つのベクトル s1 = cov^-1 * 1 と sm = cov^-1 * mu の組み合わせで、係数は市場を要約する4つの数 a, b, c, d から決まります。目標リターンごとに1つのポートフォリオが得られ、それらすべてのリスクを描いたものが次のトピックの効率的フロンティアです。

# Minimum-variance portfolios for three target returns
import numpy as np

mu = np.array([0.08, 0.05, 0.10])
cov = np.array([[0.0400, 0.0060, 0.0100],
                [0.0060, 0.0100, 0.0020],
                [0.0100, 0.0020, 0.0225]])
ones = np.ones(3)
s1, sm = np.linalg.solve(cov, ones), np.linalg.solve(cov, mu)
a, b, c = ones @ s1, ones @ sm, mu @ sm
d = a * c - b ** 2

for target in (0.06, 0.08, 0.09):
    w = ((c - b * target) * s1 + (a * target - b) * sm) / d
    print(target, np.round(w, 3), round(float(w @ mu), 4), round(float(np.sqrt(w @ cov @ w)), 4))
オプティマイザは誤差を最大化する平均・分散のウェイトは mu に非常に敏感で、1つの期待リターンがわずかに変わるだけで、ポートフォリオがある資産から別の資産へ振れることがあります。オプティマイザは入力を完全に信じるので、過大評価されたリターンは大きなポジションになります。実務ではリターンを縮小し、ウェイトに上限を設け、入力は過去の生の平均ではなくモデルやビューから得ます。平均・分散は考えるための良い道具ですが、盲目的に使うと危険です。
  • 効用は w @ mu - 0.5 * lambda * w @ cov @ w。予算なしの最良ポジションは solve(cov, mu) / lambda で、lambda を2倍にすると半分になる
  • 無リスク資産があるとき最良のリスク資産の組み合わせは接点ポートフォリオ solve(cov, mu - rf) を合計1に直したもので、シャープ・レシオが最大
  • 目標リターンに対する最小分散のウェイトは solve(cov, ones) と solve(cov, mu) の組み合わせ。結果の質は推定した mu の質で決まる

次は効率的フロンティアです。リターンの水準ごとに最良のリスクを結んだ曲線です。

ラボ:採点される内容

  • utility でポートフォリオを採点する25点
  • utility_weights で最良のポジションを見つける25点
  • tangency_weights でシャープ・レシオを最大化する25点
  • target_return_weights でリターン目標を達成する25点
エクスプローラー · lab-85-1
▾ lab-85-1
…
bash · ブラウザ内
learner@quantcraft:~/lab-85-1$
Pythonは未読み込みPythonLn 1, Col 1Spaces: 4UTF-8

このトピックをリセットしますか?

lab-85-1 の内容はすべてスターターファイルに戻り、ターミナルも消去されます。現在の解答は失われ、元に戻せません。

リセットされるもの
  • main.py → スターターコード
  • ターミナル履歴とテスト出力
  • 未提出の変更
保持されるもの
  • ラボの最高スコア
  • XPと連続日数
  • 講義の進捗とメモ

コードを実行するにはログインしてください。

レクチャーはすべて無料で読めます。コードの実行、テスト、ラボの提出にはアカウントの作成かログインが必要です。

  • ブラウザ内IDEとbashターミナル。インストール不要
  • 即時採点、XP、ロードマップでの現在地
アカウントを作成ログイン
または
GitHubで続ける