ما لا تقوله القيمة المعرضة للخطر
قيمة معرضة للخطر بنسبة 99% قدرها 3% تعني أنك تخسر أقل من 3% في 99 يومًا من كل 100. ولا تقول شيئًا عن اليوم المئة: قد تكون الخسارة 3.1% أو 30%. والعجز المتوقع (ES، CVaR) يسدّ الثغرة. فهو متوسط الخسارة في الأيام التي تُتجاوز فيها القيمة، فيصف شكل الذيل. ولأنه متوسط يتغير بسلاسة، وخلافًا للقيمة يكافئ التنويع دائمًا، ولهذا انتقلت بازل من القيمة إلى العجز لمخاطر السوق.
import numpy as np
rng = np.random.default_rng(5)
returns = rng.standard_t(4, size=1000) * 0.01
cutoff = np.quantile(returns, 0.05) # the 95% VaR is minus this
tail = np.sort(returns[returns <= cutoff]) # the worst 5% of the days, lowest first
print(len(tail), round(float(-cutoff), 5)) # 50 days; the VaR
print(np.round(tail[:4], 4)) # the four worst daysحساب متوسط الذيل
تاريخيًا، العجز المتوقع مباشر: نختار العوائد عند عتبة القيمة أو دونها، ونأخذ متوسطها، ونقلب الإشارة. ولا تقل النتيجة أبدًا عن القيمة لأن كل عائد في الذيل أسوأ من العتبة أو مساوٍ لها. والنسبة ES / VaR تبين مدى ثقل الذيل. وللتوزيع الطبيعي نحو 1.2 عند 95%، وتُظهر البيانات ذات الذيول السميكة عادة نسبة أكبر.
import numpy as np
def tail_returns(returns, confidence):
cutoff = np.quantile(returns, 1 - confidence)
return np.sort(returns[returns <= cutoff])
def historical_es(returns, confidence):
return float(-tail_returns(returns, confidence).mean())
rng = np.random.default_rng(5)
returns = rng.standard_t(4, size=1000) * 0.01
for confidence in (0.95, 0.99):
var = -np.quantile(returns, 1 - confidence)
es = historical_es(returns, confidence)
print(confidence, round(float(var), 5), round(es, 5), round(es / float(var), 3))صيغة للحالة الطبيعية
في العائد الطبيعي يكون لمتوسط الذيل صيغة مغلقة: ES = sigma * pdf(z) / (1 - confidence) - mu حيث z الكمّي المستخدم للقيمة وpdf كثافة التوزيع الطبيعي المعياري عند z. فيختصر الحساب في دالة من سطرين ولا يكون دقيقًا إلا إذا كانت البيانات طبيعية، ومقارنته بالعجز التاريخي اختبار سريع لمدى ابتعاد البيانات عن الطبيعية.
from statistics import NormalDist
def normal_es(mu, sigma, confidence):
z = NormalDist().inv_cdf(confidence)
return sigma * NormalDist().pdf(z) / (1 - confidence) - mu
for confidence in (0.95, 0.975, 0.99):
var = NormalDist().inv_cdf(confidence) # in standard deviations, mu = 0
es = normal_es(0.0, 1.0, confidence)
print(confidence, round(var, 3), round(es, 3), round(es / var, 3)) # ES/VaR: 1.254, 1.193, 1.146# The formula against a simulated tail
import numpy as np
from statistics import NormalDist
rng = np.random.default_rng(0)
sample = rng.normal(0.0, 0.01, size=1_000_000)
tail = sample[sample <= np.quantile(sample, 0.01)]
simulated = -tail.mean()
z = NormalDist().inv_cdf(0.99)
formula = 0.01 * NormalDist().pdf(z) / 0.01
print(round(float(simulated), 5), round(formula, 5)) # both close to 0.02665- العجز المتوقع هو متوسط الخسارة في الذيل بعد القيمة: سالب متوسط العوائد عند الكمّي
(1 - confidence)أو دونه. - لا تقل أبدًا عن القيمة؛ و
ES / VaRيقيس ثقل الذيل، والصيغة الطبيعيةsigma * pdf(z) / (1 - confidence) - mu. - أبلغ عن القيمة كعتبة والعجز كشدة؛ والعجز أكثر اضطرابًا لاعتماده على مشاهدات ذيل قليلة.
التالي: اختبارات الضغط، السؤال عمّا ستخسره المحفظة في سيناريو محدد متطرف.
المختبر: ما الذي يُقيَّم
- اعزل أسوأ الأيام باستخدام
tail_returns25 نقطة - احسب متوسط الذيل باستخدام
historical_es25 نقطة - احسبها بصيغة باستخدام
normal_es25 نقطة - قارن الذيل والعتبة باستخدام
es_var_ratio25 نقطة