Mímisbrunnr知恵の泉

← 金融工学 一覧

🎓 レベル:標準 | 重要度:A(必須)

📎 前提:VaR(バリュー・アット・リスク) | 関連:バックテストとストレステスト

要点(BLUF)

1. VaRの穴とCVaR

VaR(バリュー・アット・リスク) の致命的な弱点は、「VaR を超えたときにいくら損するか」を何も言わないことでした。99% VaR が 4% でも、残り1%の世界で 5% 損するのか 50% 損するのかで、リスクはまるで違います。CVaR(Conditional VaR / Expected Shortfall)は、その尾の部分の平均損失を測ります。

CVaRα=E ⁣[LLVaRα]\mathrm{CVaR}_\alpha = \mathbb{E}\!\left[\,L \mid L \ge \mathrm{VaR}_\alpha\,\right]

つまり「最悪の 1α1-\alpha 割」の損失だけを取り出して平均したもの。定義から常に CVaRαVaRα\mathrm{CVaR}_\alpha \ge \mathrm{VaR}_\alpha で、テールが厚いほど両者の差が開きます。

2. CVaRの計算

VaR(バリュー・アット・リスク) と同じ裾の厚いリターンで CVaR を計算します。実装は「損失を大きい順に並べ、最悪 1α1-\alpha 割の平均を取る」だけ。

import numpy as np
from scipy import stats

rng = np.random.default_rng(0)
n = 200000
mu, sigma, df = 0.0005, 0.015, 5
t_raw = stats.t(df).rvs(n, random_state=rng)
returns = mu + sigma*t_raw/np.sqrt(df/(df-2))
alpha = 0.99

def cvar_from_losses(losses, alpha):
    k = int(np.ceil((1-alpha)*len(losses)))     # 最悪 (1-alpha) 割の件数
    return np.sort(losses)[-k:].mean()          # その平均=期待ショートフォール

losses = -returns
var = np.percentile(losses, alpha*100)
cvar = cvar_from_losses(losses, alpha)
print(f"VaR  {alpha:.0%} = {var:.4f}")
print(f"CVaR {alpha:.0%} = {cvar:.4f}  (最悪1%の損失の平均)")

出力:

VaR  99% = 0.0385
CVaR 99% = 0.0514

出力の意味:99% VaR は 0.0385 ですが、その VaR を超える最悪1%の世界での平均損失(CVaR)は 0.0514 と、3割以上大きい。「99%の日は 3.85% 以内」だけでなく「最悪の日々は平均 5.14% 損する」まで言えるのが CVaR です。裾が厚いほどこの差は広がり、テールリスクの正直な姿が見えます。

3. 劣加法性:VaRの構造的欠陥

リスク尺度に最低限求めたい性質が劣加法性 ρ(A+B)ρ(A)+ρ(B)\rho(A+B) \le \rho(A) + \rho(B)——「分散投資でリスクは増えない(むしろ減る)」。ところが VaR はこれを破ることがあります。独立に 4% の確率でデフォルトする2つの社債で確かめます。

import numpy as np

def cvar_from_losses(losses, alpha):
    k = int(np.ceil((1-alpha)*len(losses)))
    return np.sort(losses)[-k:].mean()

rng = np.random.default_rng(1)
M = 2000000
def bond_pnl(M, rng):
    default = rng.random(M) < 0.04             # 4%の確率でデフォルト
    return np.where(default, -100.0, 5.0)      # デフォルトで-100, 平時+5

A = bond_pnl(M, rng); B = bond_pnl(M, rng)    # 独立な2社債
def var95(pnl): return -np.percentile(pnl, 5)
def cvar95(pnl): return cvar_from_losses(-pnl, 0.95)

print("【VaR は劣加法性を満たさない】")
print(f"VaR95(A)={var95(A):.1f}, VaR95(B)={var95(B):.1f}, 単純合計={var95(A)+var95(B):.1f}")
print(f"VaR95(A+B)={var95(A+B):.1f}  ← 合計を上回る(分散したのにリスク増)")
print("【CVaR は劣加法性を満たす】")
print(f"CVaR95(A)={cvar95(A):.2f}, CVaR95(B)={cvar95(B):.2f}, 単純合計={cvar95(A)+cvar95(B):.2f}")
print(f"CVaR95(A+B)={cvar95(A+B):.2f}  ← 合計以下(分散効果が正しく出る)")

出力:

【VaR は劣加法性を満たさない】
VaR95(A)=-5.0, VaR95(B)=-5.0, 単純合計=-10.0
VaR95(A+B)=95.0  ← 合計を上回る(分散したのにリスク増)
【CVaR は劣加法性を満たす】
CVaR95(A)=79.55, CVaR95(B)=78.96, 単純合計=158.51
CVaR95(A+B)=98.42  ← 合計以下(分散効果が正しく出る)

出力の意味:各社債単独の 95% VaR は 5-5(損失がマイナス=95%の確信では損失なし、むしろ +5 の利益。デフォルト確率4% < 5% のため)。ところが2社債を合わせると VaR95 は 95 に跳ね上がります——どちらかがデフォルトする確率が 7.8% > 5% になり、テールに損失が顔を出すから。95>1095 > -10 で、分散したのにリスクが増えたことになる。これは VaR が「閾値1点しか見ない」ことの構造的欠陥です。一方 CVaR は CVaR(A+B)=98.4158.5=\mathrm{CVaR}(A{+}B)=98.4 \le 158.5= 単純合計で、分散効果を正しく「リスク減」と評価します。

4. コヒーレントリスク尺度

劣加法性を含む4条件——単調性・並進不変性・正同次性・劣加法性——を満たすリスク尺度を**コヒーレント(整合的)**と呼びます(アルツナーら)。CVaR はコヒーレント、VaR は劣加法性を破るので非コヒーレント。「リスク尺度として CVaR のほうが理論的に健全」という結論です。実務でも、バーゼル銀行監督委員会は市場リスクの内部モデルを 99% VaR から 97.5% 期待ショートフォールへ移行しました(要最新確認)。それでも VaR は直感的で規制の歴史も長く、両者は併用されています。

⚠️ よくある誤解

関連ノート