السؤال «ماذا لو؟» بدل «ما احتمال؟»
تُقدَّر القيمة المعرضة والعجز المتوقع من العوائد السابقة، فلا ترى ما لم يحدث قط. أما اختبار الضغط فيترك الاحتمالات ويطبّق سيناريو تختاره: انهيار الأسهم 20%، أو قفزة الفائدة نقطتين، أو إعادة أزمة 2008، أو خفض العملة. وخسارة المحفظة في ذلك السيناريو رقم تناقشه لجنة المخاطر، ويكشف تركزات يخفيها المتوسط الإحصائي.
import numpy as np
values = np.array([500000.0, 300000.0, -200000.0]) # two longs and a short
shocks = np.array([-0.20, -0.10, 0.15]) # one scenario: stocks -20%, bonds -10%, the shorted stock +15%
pnl = values * shocks # per position
print(pnl) # [-100000. -30000. -30000.] the short loses when its stock rises
print(float(pnl.sum())) # -160000.0جدول من السيناريوهات
تحتفظ فرق المخاطر بقائمة دائمة من السيناريوهات، تاريخية (1987 و2008 ومارس 2020) وافتراضية. ضعها في مصفوفة بصف لكل سيناريو وعمود لكل مركز: فتكون الخسارة الكلية في كل سيناريو حاصل ضرب واحد بين مصفوفة ومتجه، scenarios @ values. وأخذ أصغر عنصر في المتجه يسمّي أسوأ حالة، والسيناريو الأشد إيلامًا معلومة بحد ذاته لأنه يدل على موضع انكشاف المحفظة.
import numpy as np
values = np.array([500000.0, 300000.0, -200000.0])
scenarios = np.array([[-0.20, -0.10, 0.15], # equity crash
[-0.05, 0.02, 0.00], # mild dip
[ 0.10, 0.05, -0.20]]) # the shorted stock falls 20%: the short gains
names = ["equity crash", "mild dip", "rally and short gain"]
pnl = scenarios @ values
for name, p in zip(names, pnl):
print(name, round(float(p)))
worst = int(np.argmin(pnl))
print("worst:", names[worst], round(float(pnl[worst])))# A shock does not have to be a price move: a rate jump hits a bond through its duration
duration = 7.5 # years, from the duration topic
bond_value = 1_000_000.0
rate_jump = 0.02 # +2 percentage points
print(round(bond_value * (-duration * rate_jump))) # -150000 the shock expressed as a price return of -15%اختبار الضغط العكسي
اعكس السؤال: ما مدى سوء الصدمة التي ستكلفنا مبلغًا معينًا مثل هامش رأس المال؟ خذ اتجاهًا للصدمات (مثلًا كل شيء يهبط معًا) وحجِّمه بعامل k. الخسارة هي -k * (values @ direction) خطية في k، فالعامل الذي يخسر loss_limit بالضبط هو loss_limit / -(values @ direction). وإن لم يكن الاتجاه خاسرًا فلا يبلغ أي عامل الحد.
import numpy as np
def reverse_stress(values, direction, loss_limit):
change = float(values @ direction)
if change >= 0:
return float("inf")
return loss_limit / -change
values = np.array([500000.0, 300000.0, -200000.0])
direction = np.array([-1.0, -1.0, 0.0]) # the two longs fall by the same percentage
k = reverse_stress(values, direction, 100000.0)
print(round(k, 4)) # 0.125 a 12.5% fall in both longs loses 100,000
print(round(float(-(values @ (k * direction))), 2)) # 100000.0- يطبّق اختبار الضغط صدمات مختارة: ربح المركز أو خسارته
values * shocks، سالب للخسائر وموجب للبيع على المكشوف الرابح. - سيناريوهات كثيرة معًا حاصل ضرب واحد
scenarios @ values؛ والأصغر يسمّي أسوأ حالة ويبين موضع انكشاف المحفظة. - الضغط العكسي: مضاعف الصدمة الذي يخسر الحد بالضبط هو
loss_limit / -(values @ direction)أو ما لا نهاية إن لم يخسر الاتجاه أبدًا.
التالي: نماذج ARIMA، التنبؤ بسلسلة من ماضيها نفسه.
المختبر: ما الذي يُقيَّم
- اضرب كل مركز باستخدام
shocked_pnl25 نقطة - شغّل سيناريوهات كثيرة معًا باستخدام
scenario_pnl25 نقطة - سمِّ أسوأ حالة باستخدام
worst_scenario25 نقطة - انطلق من خسارة إلى الوراء باستخدام
reverse_stress25 نقطة