روشهای محاسبه ارزش در معرض ریسک (VaR)
بررسی سه روش محاسباتی تاریخی، پارامتریک و مونت کارلو برای تعیین ارزش در معرض ریسک در سری بازدهی SPY و تحلیل مفهوم کسری مورد انتظار که در مدل VaR نادیده گرفته میشود.
ارزش در معرض ریسک یا VaR با تعیین یک افق زمانی، تعیین سطح اطمینان و سپس استخراج یک صدک از سری بازدهی محاسبه میشود. برای نمونه، یک VaR یکروزه 99 درصدی معادل 2 درصد، به این معناست که زیان در 99 جلسه از هر 100 جلسه معاملاتی زیر 2 درصد باقی میماند و تنها در یک جلسه از صد جلسه از این مقدار فراتر میرود. سه روش استاندارد برای پاسخ به این پرسش با استفاده از دادههای ورودی یکسان وجود دارد که نتایج آنها بیش از حد انتظار اکثر افراد با یکدیگر اختلاف دارد.
ارزش در معرض ریسک (VaR) واقعاً چه چیزی را اندازهگیری میکند
شاخص VaR یک چندک از توزیع زیان است. تمام بازدههای روزانه در یک نمونه را از بدترین به بهترین مرتب کنید، یک درصد از مسیر را از سمت انتهای بد (زیانده) طی کنید؛ بازدهی که به آن میرسید، اگر بهعنوان یک زیان مثبت نوشته شود، همان VaR تاریخی 99 درصدی یکروزه است. در این ساختار، هیچ وعدهای مبنی بر نشان دادن بدترین حالت ممکن وجود ندارد. این شاخص صرفاً مرز منطقهای را مشخص میکند که برآورد از آن نقطه به بعد دیگر توصیفی ارائه نمیدهد.
این همان ویژگی است که خوانندگان بیش از همه دچار سوءبرداشت درباره آن میشوند. یک VaR نود و نه درصدی بیان میکند که بدترین یک درصدِ روزها فراتر از این آستانه قرار دارند و در مورد میزان این فاصله سکوت میکند. حداکثر افت ارزش (Maximum drawdown) به پرسش متفاوتی پاسخ میدهد؛ یعنی زیان از قله تا دره که یک سبد دارایی واقعاً تجربه کرده است. این دو معیار میتوانند یک جفت سبد دارایی مشابه را در رتبهبندیهای کاملاً متضاد قرار دهند.
تمام ارقام زیر بر پایه یک سری داده استوار است: قیمتهای پایانی روزانه SPY از ابتدای سال 2010 تا پایان سال 2025 که به تغییرات درصدی قیمت پایانی به پایانی تبدیل شدهاند. پنجره زمانی ثابت است و متحرک نیست، و هر پنل، سری دادهها را از همان تاریخهای مشخص بازسازی میکند؛ بنابراین ارقام در اجراهای مختلف دچار انحراف نمیشوند.
کد دقیق SQL پشت هر عدد
WITH
px AS
(
SELECT date, max(toFloat64(close)) AS close_px
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'SPY'
AND date >= '2009-12-01'
AND date < '2026-01-01'
GROUP BY date
),
rets AS
(
SELECT date, 100 * (close_px / prev_close - 1) AS ret_pct
FROM
(
SELECT date, close_px,
lagInFrame(close_px, 1) OVER (ORDER BY date ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prev_close
FROM px
)
WHERE date >= '2010-01-01' AND prev_close > 0
)
SELECT
toString(toYear(date)) AS year,
count() AS sessions,
round(avg(ret_pct), 3) AS mean_return_pct,
round(stddevSamp(ret_pct), 2) AS daily_sigma_pct
FROM rets
GROUP BY year
ORDER BY yearاین سری داده شامل 16 سال تقویمی و 252 جلسه معاملاتی تنها در سال 2010 است. دو ویژگی از این دادهها برای تمام مباحث بعدی اهمیت دارد. میانگین جلسات در این افق زمانی تقریباً بیاهمیت است: 0.054% در 2010، در مقابل انحراف معیار روزانه (سیگما) به میزان 1.13%. و سیگما یک مقدار ثابت نیست. 2020 با نرخ 2.11% در روز فعالیت داشت و 2017 با نرخ 0.43%. یک سیگما نمیتواند هر دو را توصیف کند.
نحوه محاسبه ارزش در معرض ریسک (VaR)، سه روش
VaR تاریخی: استخراج صدک از دادههای گذشته
بازدههای واقعی را مرتب کرده و صدک مورد نظر را استخراج کنید. در این روش هیچ توزیع آماری فرض نمیشود که همین ویژگی، جذابیت اصلی آن است. فرض ضمنی این روش آن است که نمونه آماری، شامل سناریوهای مشابه روزی که قصد برآورد آن را دارید، باشد. اگر سطح اطمینان را به اندازه کافی بالا ببرید، تنها چند جلسه معاملاتی بد در کل بازه زمانی، پاسخ را تعیین میکنند.
VaR پارامتریک: میانگین منهای حاصلضرب z در سیگما
سری زمانی را با میانگین و سیگما خلاصه کنید و سپس فرض کنید بازدهها از توزیع نرمال پیروی میکنند. VaR برابر است با حاصلضرب z در سیگما منهای میانگین، که در آن z چندک توزیع نرمال استاندارد است: 1.645 برای سطح اطمینان 95٪، 2.326 برای 99٪ و 3.090 برای 99.9٪. محاسبات آنی است، اما این فرض در یک جهت خاص دچار خطا میشود. بازدههای روزانه سهام در محدوده میانی، فشردهتر از منحنی نرمال عمل کرده و در نقاط انتهایی (دم توزیع) بسیار فراتر میروند. سیگما در اینجا همان مخرج کسری است که در نسبت شارپ نیز به کار میرود و همان نقطه کور را در مواجهه با دادههای دارای دمکلفت (fat-tailed) به همراه دارد.
VaR مونتکارلو: شبیهسازی با بذر (seed) ثابت
یک نمونه بزرگ مصنوعی از یک فرآیند مفروض استخراج کنید و صدک مورد نظر را از میان دادههای شبیهسازیشده بخوانید. پنل زیر از 40,000 داده نرمال استاندارد استفاده میکند که با تبدیل باکس-مولر از یک دنباله یکنواخت با بذر مشخص ساخته شده و بر اساس میانگین و سیگمای سری، مقیاسبندی شدهاند. بذر در SQL قرار دارد، بنابراین دادهها در هر بار اجرا یکسان هستند. شبیهسازی، انعطافپذیری، وابستگی به مسیر و همبستگی چند دارایی را فراهم میکند، اما لزوماً واقعگرایی به همراه ندارد: اگر به آن توزیع نرمال بدهید، همان پاسخ پارامتریک را با مقداری نویز نمونهگیری تحویل میدهد. در مقابل، بازنمونهگیری (resampling) از بازدههای مشاهدهشده، که تکنیک پشت بازه اطمینان بوتاسترپ است، دم واقعی توزیع را حفظ میکند.
کد دقیق SQL پشت هر عدد
WITH
px AS
(
SELECT date, max(toFloat64(close)) AS close_px
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'SPY'
AND date >= '2009-12-01'
AND date < '2026-01-01'
GROUP BY date
),
rets AS
(
SELECT date, 100 * (close_px / prev_close - 1) AS ret_pct
FROM
(
SELECT date, close_px,
lagInFrame(close_px, 1) OVER (ORDER BY date ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prev_close
FROM px
)
WHERE date >= '2010-01-01' AND prev_close > 0
),
emp AS
(
SELECT
avg(ret_pct) AS mu,
stddevSamp(ret_pct) AS sd,
quantileExact(0.100)(ret_pct) AS h90,
quantileExact(0.050)(ret_pct) AS h95,
quantileExact(0.025)(ret_pct) AS h975,
quantileExact(0.010)(ret_pct) AS h99,
quantileExact(0.005)(ret_pct) AS h995,
quantileExact(0.001)(ret_pct) AS h999
FROM rets
),
draws AS
(
SELECT
quantileExact(0.100)(z) AS z90,
quantileExact(0.050)(z) AS z95,
quantileExact(0.025)(z) AS z975,
quantileExact(0.010)(z) AS z99,
quantileExact(0.005)(z) AS z995,
quantileExact(0.001)(z) AS z999
FROM
(
SELECT sqrt(-2 * log(u1)) * cos(2 * pi() * u2) AS z
FROM
(
SELECT
(cityHash64('var-seed-u1', i) % 999999937 + 1) / 999999938.0 AS u1,
(cityHash64('var-seed-u2', i) % 999999937 + 1) / 999999938.0 AS u2
FROM (SELECT arrayJoin(range(40000)) AS i)
)
)
)
SELECT
tupleElement(lvl, 1) AS confidence,
round(-1 * tupleElement(lvl, 2), 2) AS historical_var_pct,
round(tupleElement(lvl, 3) * sd - mu, 2) AS parametric_var_pct,
round(-1 * (mu + sd * tupleElement(lvl, 4)), 2) AS monte_carlo_var_pct,
round(-1 * tupleElement(lvl, 2) - (tupleElement(lvl, 3) * sd - mu), 2) AS method_spread
FROM
(
SELECT
mu,
sd,
arrayJoin([
('90.0%', h90, 1.281552, z90, 1),
('95.0%', h95, 1.644854, z95, 2),
('97.5%', h975, 1.959964, z975, 3),
('99.0%', h99, 2.326348, z99, 4),
('99.5%', h995, 2.575829, z995, 5),
('99.9%', h999, 3.090232, z999, 6)
]) AS lvl
FROM emp
CROSS JOIN draws
)
ORDER BY tupleElement(lvl, 5)در سطح 95.0%، هر سه روش به نتایجی با اختلاف یک واحد از یکدیگر میرسند: 1.66% برای روش تاریخی، 1.74% برای پارامتریک و 1.71% برای شبیهسازیشده. در سطح 99.9%، مسیرها از هم جدا میشوند: 5.85% برای روش تاریخی در مقابل 3.31% برای پارامتریک، شکافی به اندازه 2.54 واحد درصد روی دادههای یکسان ایجاد میشود. ستون شبیهسازیشده در تمامی سطوح در کنار ستون پارامتریک قرار میگیرد که این خود یک درس است، نه یک نقص. یک شبیهسازی، هر توزیعی که به آن داده شود را بازتولید میکند.
اگر پنل را از بالا به پایین در یک ستون بخوانید، هر گام در سطح اطمینان، آستانه را وسیعتر میکند. اگر آن را در یک سطر بخوانید، انتخاب روش در محدوده میانی توزیع تأثیر ناچیزی دارد، اما در نقاط انتهایی (دم توزیع) تعیینکننده است. حد VaR که بدون ذکر روش و بازه زمانی آن ارائه شود، عددی نیست که دیگران بتوانند آن را بازتولید کنند.
آنچه VaR به شما نمیگوید: زیان مورد انتظار (Expected Shortfall)
زیان مورد انتظار که به آن VaR شرطی نیز میگویند، میانگین زیانها در روزهایی را محاسبه میکند که از حد VaR فراتر رفتهاند. VaR نشاندهنده نقطه آغاز «دم» توزیع است، در حالی که زیان مورد انتظار، عمق و شدت آنچه در آن محدوده قرار دارد را اندازهگیری میکند.
کد دقیق SQL پشت هر عدد
WITH
px AS
(
SELECT date, max(toFloat64(close)) AS close_px
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'SPY'
AND date >= '2009-12-01'
AND date < '2026-01-01'
GROUP BY date
),
rets AS
(
SELECT date, 100 * (close_px / prev_close - 1) AS ret_pct
FROM
(
SELECT date, close_px,
lagInFrame(close_px, 1) OVER (ORDER BY date ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prev_close
FROM px
)
WHERE date >= '2010-01-01' AND prev_close > 0
),
qs AS
(
SELECT
quantileExact(0.100)(ret_pct) AS q90,
quantileExact(0.050)(ret_pct) AS q95,
quantileExact(0.025)(ret_pct) AS q975,
quantileExact(0.010)(ret_pct) AS q99,
quantileExact(0.005)(ret_pct) AS q995,
quantileExact(0.001)(ret_pct) AS q999
FROM rets
),
tails AS
(
SELECT
any(q90) AS var90,
any(q95) AS var95,
any(q975) AS var975,
any(q99) AS var99,
any(q995) AS var995,
any(q999) AS var999,
avgIf(ret_pct, ret_pct <= q90) AS es90,
avgIf(ret_pct, ret_pct <= q95) AS es95,
avgIf(ret_pct, ret_pct <= q975) AS es975,
avgIf(ret_pct, ret_pct <= q99) AS es99,
avgIf(ret_pct, ret_pct <= q995) AS es995,
avgIf(ret_pct, ret_pct <= q999) AS es999
FROM rets
CROSS JOIN qs
HAVING countIf(ret_pct <= q999) > 0
)
SELECT
tupleElement(lvl, 1) AS confidence,
round(-1 * tupleElement(lvl, 2), 2) AS historical_var_pct,
round(-1 * tupleElement(lvl, 3), 2) AS expected_shortfall_pct,
round(tupleElement(lvl, 3) / tupleElement(lvl, 2), 2) AS es_to_var_ratio
FROM
(
SELECT
arrayJoin([
('90.0%', var90, es90, 1),
('95.0%', var95, es95, 2),
('97.5%', var975, es975, 3),
('99.0%', var99, es99, 4),
('99.5%', var995, es995, 5),
('99.9%', var999, es999, 6)
]) AS lvl
FROM tails
)
ORDER BY tupleElement(lvl, 4)در 99.0%، مقدار VaR برای این سری دادهها برابر با 3.09% و زیان مورد انتظار برابر با 4.43%، یا به عبارتی 1.44 برابرِ آستانه تعیینشده است. تحت توزیع نرمال، این نسبت در همان سطح باید نزدیک به 1.15 باشد. حتی در 99.9%، که آستانه به 5.85% رسیده است، میانگین زیان در روزهای نقض حد، معادل 8.14% است. محدودیتهایی که صرفاً بر پایه VaR تعریف میشوند، هر مورد نقض حد را رویدادی یکسان در نظر میگیرند؛ ستون نسبتها نشان میدهد که این فرض تا چه حد با واقعیت فاصله دارد.
آیا VaR یکروزه با سطح اطمینان 99 درصد برای یک نهاد مالی و یک معاملهگر معنای یکسانی دارد؟
خیر، و این تفاوت عمدتاً به افق زمانی بازمیگردد. معاملهگری که موقعیتهای خود را پیش از پایان روز معاملاتی میبندد (flat)، ریسک را تنها برای چند ساعت متحمل میشود؛ بنابراین، آستانه یک جلسه معاملاتی با دوره نگهداری او همخوانی دارد، هرچند مسیر نوسانات درونروزی میتواند بسیار فراتر از عددِ «قیمت بسته به قیمت بسته» باشد. یک نهاد مالی که تعهدات بلندمدت را تأمین مالی میکند، موقعیتها را برای سالها نگه میدارد و در معرض ریسک در طول چندین فصل (Q) قرار دارد؛ برای چنین نهادی، عدد VaR یکروزه 99 درصد، بیشتر یک ابزار نظارتی و سرمایهای است تا توصیفگر ریسکی که واقعاً متحمل میشود. قوانین سرمایه بانکها سالها بر پایه VaR یکروزه 99 درصد بنا شده بود و چارچوب ریسک بازار «بازل» (Basel) بعدها این معیار را به «کسری مورد انتظار» (Expected Shortfall) 97.5 درصد تغییر داد.
پل استاندارد میان افقهای زمانی، مقیاسبندی با استفاده از جذر زمان است: عدد مربوط به یک جلسه معاملاتی را در جذر تعداد جلساتِ افق زمانی ضرب کنید. این گام فرض میکند که بازدهیها مستقل هستند و انحراف معیار (sigma) ثابتی دارند، اما ستون انحراف معیار سالانه در جدول بالا نشان میدهد که بخش دوم این فرض با شکست مواجه میشود.
کد دقیق SQL پشت هر عدد
WITH
px AS
(
SELECT date, max(toFloat64(close)) AS close_px
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'SPY'
AND date >= '2009-11-01'
AND date < '2026-01-01'
GROUP BY date
),
multi AS
(
SELECT
date,
100 * (close_px / p1 - 1) AS r1,
100 * (close_px / p5 - 1) AS r5,
100 * (close_px / p10 - 1) AS r10,
100 * (close_px / p20 - 1) AS r20
FROM
(
SELECT
date,
close_px,
lagInFrame(close_px, 1) OVER (ORDER BY date ROWS BETWEEN 20 PRECEDING AND CURRENT ROW) AS p1,
lagInFrame(close_px, 5) OVER (ORDER BY date ROWS BETWEEN 20 PRECEDING AND CURRENT ROW) AS p5,
lagInFrame(close_px, 10) OVER (ORDER BY date ROWS BETWEEN 20 PRECEDING AND CURRENT ROW) AS p10,
lagInFrame(close_px, 20) OVER (ORDER BY date ROWS BETWEEN 20 PRECEDING AND CURRENT ROW) AS p20
FROM px
)
WHERE date >= '2010-01-01' AND p20 > 0
),
q AS
(
SELECT
quantileExact(0.01)(r1) AS q1,
quantileExact(0.01)(r5) AS q5,
quantileExact(0.01)(r10) AS q10,
quantileExact(0.01)(r20) AS q20
FROM multi
)
SELECT
tupleElement(h, 1) AS horizon,
round(-1 * tupleElement(h, 3), 2) AS actual_var_pct,
round(-1 * q1 * sqrt(tupleElement(h, 2)), 2) AS sqrt_scaled_var_pct,
round(tupleElement(h, 3) / (q1 * sqrt(tupleElement(h, 2))), 2) AS actual_to_scaled_ratio
FROM
(
SELECT
q1,
arrayJoin([
('1 session', 1.0, q1, 1),
('5 sessions', 5.0, q5, 2),
('10 sessions', 10.0, q10, 3),
('20 sessions', 20.0, q20, 4)
]) AS h
FROM q
)
ORDER BY tupleElement(h, 4)ردیف اول یک بررسی همانی است: در 1 session عدد مقیاسبندیشده با عدد اندازهگیریشده برابر است که نسبت 1 را نشان میدهد. در 20 sessions این دو از هم جدا میشوند، و نه در جهتی که معمولاً درباره میانبرهای محاسباتی هشدار داده میشود: مقیاسبندی عدد یکجلسهای، مقدار 13.8% را به دست میدهد، در حالی که بازدهیهای اندازهگیریشده در آن افق زمانی، عدد 10.7% را ثبت میکنند که نسبت 0.78 است. در این بازه، عدد مقیاسبندیشده بالاتر از دمِ توزیعِ چندجلسهایِ اندازهگیریشده قرار میگیرد. دو الگو در اینجا با یکدیگر در تقابلاند. توزیع تکجلسهای با دمِ پهن، با تجمیع بازدهیها نازکتر میشود و در نتیجه، چندک 99 درصدِ تجمیعی، کندتر از جذر افق زمانی گسترش مییابد. خوشهبندی نوسانات (Volatility clustering) در جهت مخالف عمل میکند و جلسات پرنوسان را در یک بازه زمانی کنار هم قرار میدهد. در این سری داده، الگوی اول تأثیر بیشتری دارد، اما هیچکدام از این دو جهت در بازه یا دارایی دیگر تضمینشده نیستند؛ و نکته همینجاست: ضریبِ ضربکننده یک فرض است، نه یک اندازهگیری. همان خوشهبندی، ویژگیای است که استراتژی هدفگذاری نوسان هنگام تغییر اندازه موقعیتها به آن تکیه میکند.
یک محدودیت دیگر را بهصراحت بیان میکنیم: تمام موارد فوق، VaR تکدارایی روی یک صندوق شاخصی گسترده است. سبدی متشکل از ده نامِ همبسته، حامل ریسک تمرکز است که VaR پرتفوی آن را از طریق برآورد همبستگی مدیریت میکند، و همبستگیها دقیقاً در لحظهای که برآورد اهمیت مییابد، بیشترین تغییر را دارند.
یادداشتهای روششناسی و قراردادها
- چندکها از یک مقدار دقیق (exact quantile) به دست آمدهاند، نه یک برآورد نمونهگیریشده؛ و شبیهسازیهای مونتکارلو از یک دنباله یکنواخت با بذر هش (hash seeded) که در SQL نوشته شده، استخراج شدهاند تا هر عدد در اینجا به همان مقدار قبلی بازتولید شود.
- بازدهیها تغییرات قیمت «بسته به بسته» بدون احتساب سود تقسیمی (dividend reinvestment) هستند که قرارداد معمول برای VaR یکجلسهای است.
- پنل افق زمانی از پنجرههای همپوشان استفاده میکند: بازدهیهای متوالی 20 جلسهای، 19 روز مشترک دارند؛ بنابراین دمِ توزیع آنها بر تعداد مشاهدات مستقل بسیار کمتری نسبت به آنچه تعداد ردیفها نشان میدهد، استوار است.
پرسشهای متداول
ارزش در معرض ریسک (VaR) یکروزه با سطح اطمینان 99 درصد چیست؟
این شاخص، سطح زیانی است که بدترین یک روز از هر 100 روز معاملاتی از آن فراتر میرود و در یک جلسه معاملاتی اندازهگیری میشود. در سری دادههای بالا، برآورد تاریخی برابر با 3.09% است. این رقم تنها یک آستانه را تعیین میکند و هیچ اطلاعاتی درباره بزرگی زیانهای فراتر از آن ارائه نمیدهد.
کدام روش محاسبه VaR دقیقتر است؟
هیچکدام از این سه روش در حالت انتزاعی دقیق نیستند، زیرا هر یک پرسش را تحت مفروضات متفاوتی پاسخ میدهند. VaR تاریخی به نمونهای که به آن داده شده وفادار است و درباره آنچه در نمونه نادیده گرفته شده، سکوت میکند. VaR پارامتریک ارزان است اما دنبالههای توزیع سهام را کمتر از واقع نشان میدهد. روش مونتکارلو نیز تنها به اندازه توزیعی که به آن خورانده میشود، اعتبار دارد.
تفاوت میان VaR و کسری مورد انتظار (Expected Shortfall) چیست؟
VaR آستانهای در یک سطح اطمینان مشخص است. کسری مورد انتظار، میانگین زیانها در روزهایی است که از این آستانه عبور میکنند. در این سری داده، کسری مورد انتظار در سطح 99 درصد، 1.44 برابرِ VaR است، در حالی که این نسبت در توزیع نرمال تقریباً 1.15 برابر است.
آیا میتوان VaR یکروزه را به VaR دهروزه تبدیل کرد؟
ضرب در جذر 10، میانبر استاندارد برای این کار است و فرض میکند بازدهیها مستقل بوده و دارای نوسانپذیری ثابت هستند. پنل افق زمانی این شکاف را اندازهگیری میکند: در طول 20 جلسه معاملاتی، رقم مقیاسشده برابر با 13.8% و رقم اندازهگیریشده برابر با 10.7% بوده است.
هر پنل در بالا شامل کد SQL تولیدکننده آن است. برای اجرای همین سه محاسبه روی یک تیکر یا بازه زمانی متفاوت، درخواست خود را به زبان ساده در ترمینال Strasmore مطرح کنید.