Strasmore Research
Deep Dives · Matt ConnorBy Matt Connor · · Updated 2026-08-21

איך מחשבים Value at Risk: שלוש שיטות מרכזיות

מדריך לחישוב Value at Risk בשיטות היסטורית, פרמטרית ומונטה קרלו עבור SPY. הסבר על אופן המדידה ועל ה-Expected Shortfall שנותר מחוץ לחישוב ה-VaR הסטנדרטי.

ערך בסיכון (VaR)

מדד ה-Value at Risk, או VaR, מחושב על ידי קביעת טווח זמן, הגדרת רמת סמך, ולאחר מכן חילוץ אחוזון מסדרת תשואות. ערך VaR יומי של שני אחוזים ברמת סמך של תשעים ותשעה אחוזים משמעו שההפסד יישאר נמוך משני אחוזים בתשעים ותשעה מתוך כל מאה ימי מסחר, ויחרוג ממנו באחד הנותר. שלוש שיטות סטנדרטיות משיבות על שאלה זו בהתבסס על נתוני קלט זהים, והן מציגות פערים גדולים יותר ממה שרוב האנשים מצפים.

מה באמת מודד ערך בסיכון (VaR)

מדד ה-VaR הוא קוונטיל בהתפלגות הפסדים. אם נסדר את כל התשואות היומיות במדגם מהגרועה ביותר לטובה ביותר, ונתקדם אחוז אחד מהקצה השלילי, התשואה שבה נעצור – כשהיא מוצגת כהפסד חיובי – היא ה-VaR ההיסטורי ליום אחד ברמת סמך של 99%. שום דבר במבנה הזה אינו מבטיח תרחיש קיצון. המדד מסמן רק את הגבול של האזור שהאומדן מפסיק לתאר.

זהו המאפיין שקוראים נוטים להחמיץ בתדירות הגבוהה ביותר. VaR של 99% קובע כי אחוז אחד מהימים הגרועים ביותר נמצא מעבר לסף, אך הוא אינו מפרט עד כמה רחוק. ירידה מקסימלית מהשיא (Maximum drawdown) עונה על שאלה אחרת: ההפסד מהשיא לשפל שתיק השקעות חווה בפועל. שני המדדים עשויים לדרג את אותו זוג תיקים בסדר הפוך.

כל נתון להלן מתבסס על סדרה אחת: שערי הסגירה היומיים של SPY מתחילת שנת 2010 ועד סוף שנת 2025, שהומרו לשינויי אחוזים בין סגירה לסגירה. חלון הזמן קבוע ולא נע, וכל פאנל בונה מחדש את הסדרה מאותם תאריכים, כך שהמספרים אינם משתנים בין הרצות.

שאילתהסדרת התשואות הנבחרת: תשואות יומיות של 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
Run this yourself

הסדרה משתרעת על פני 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 מונטה קרלו: סימולציה עם "זרע" קבוע

מייצרים מדגם סינתטי גדול מתוך תהליך מוגדר וקוראים את האחוזון מתוך התוצאות. הלוח להלן משתמש ב-40,000 דגימות נורמליות סטנדרטיות שנבנו באמצעות טרנספורמציית Box-Muller מתוך רצף אחיד בעל "זרע" (seed) קבוע, ומותאמות לממוצע ולסטיית התקן של הסדרה. הזרע מוטמע ב-SQL, כך שהדגימות זהות בכל הרצה מחדש. סימולציה מעניקה גמישות, תלות במסלול ומתאם בין נכסים מרובים, אך לא בהכרח ריאליזם: אם מזינים לה התפלגות נורמלית, היא מחזירה את התוצאה הפרמטרית בתוספת רעש דגימה. לעומת זאת, דגימה מחדש (resampling) של התשואות שנצפו – הטכניקה שמאחורי רווחי סמך בשיטת ה-bootstrapping – שומרת על הזנבות האמיתיים בתוך החישוב.

שאילתהסדרה אחת, שלוש שיטות: 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
),
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)
Run this yourself

ברמת 95.0% שלוש השיטות מניבות תוצאות קרובות מאוד: 1.66% בשיטה ההיסטורית, 1.74% בפרמטרית, ו-1.71% בסימולציה. ברמת 99.9% הדרכים נפרדות: 5.85% בשיטה ההיסטורית לעומת 3.31% בפרמטרית, פער של 2.54 נקודות אחוז על אותם נתונים בדיוק. העמודה הסימולטיבית ניצבת לצד העמודה הפרמטרית בכל רמה, וזהו הלקח המרכזי ולא פגם בשיטה. סימולציה משחזרת את ההתפלגות שהוזנה לה.

קריאת הלוח לאורך עמודה מראה כיצד כל עלייה ברמת הסמך מרחיבה את הסף. קריאת הלוח לרוחב שורה מראה כי בחירת השיטה כמעט אינה מורגשת במרכז ההתפלגות, אך היא דומיננטית בקצוות. מגבלת VaR שמוצגת ללא ציון השיטה וחלון הזמן שלה אינה מספר שמישהו אחר יכול לשחזר.

מה VaR לא אומר לכם: ה-Expected Shortfall

ה-Expected Shortfall, המכונה גם Conditional VaR, מחשב את ממוצע ההפסדים בימים שבהם נחצה רף ה-VaR. בעוד שה-VaR מסמן את הנקודה שבה מתחיל הזנב של התפלגות ההפסדים, ה-Expected Shortfall מודד את מה שנמצא בתוכו.

שאילתהVaR מול Expected Shortfall, ממוצע ההפסד מעבר לסף
ה-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)
Run this yourself

ב-99.0%, ה-VaR של סדרה זו עומד על 3.09% וה-Expected Shortfall עומד על 4.43%, או פי 1.44 מהרף. תחת התפלגות נורמלית, יחס זה היה עומד על כ-1.15 באותה רמת מובהקות. גם ב-99.9%, שבו הרף כבר הגיע ל-5.85%, יום החריגה הממוצע מסתכם ב-8.14%. מגבלה המבוססת על VaR בלבד מתייחסת לכל חריגה כאל אירוע זהה, ועמודת היחס מודדת עד כמה הנחה זו אינה נכונה.

האם מדד VaR יומי ברמת מובהקות של 99% זהה עבור מוסד פיננסי ועבור סוחר?

לא, והפער נובע בעיקר מאופק הזמן. סוחר שסוגר פוזיציות לפני סוף יום המסחר חשוף לסיכון למשך שעות בלבד, ולכן סף של יום מסחר אחד תואם את תקופת ההחזקה שלו, אף שהתנודתיות התוך-יומית עשויה לחרוג משמעותית מהנתון הנמדד בין סגירה לסגירה. מוסד פיננסי המממן התחייבויות ארוכות טווח מחזיק בפוזיציות במשך שנים, החשיפה שלו נפרסת על פני רבעונים, ונתון ה-VaR היומי שלו משמש ככלי לניהול הון ובקרה ולא כתיאור מדויק של הסיכון הממשי שהוא נושא. כללי הלימות ההון של בנקים התבססו במשך שנים על VaR יומי של 99%, אך מסגרת סיכוני השוק של באזל עברה מאוחר יותר למדד של Expected Shortfall ברמת 97.5%.

הגשר המקובל בין אופקי זמן שונים הוא כיול באמצעות שורש ריבועי של הזמן: מכפילים את הנתון היומי בשורש הריבועי של מספר ימי המסחר באופק הנמדד. צעד זה מניח שהתשואות הן בלתי תלויות ובעלות סטיית תקן קבועה, אך עמודת סטיית התקן השנתית לעיל כבר מדגימה כיצד הנחה זו אינה מתקיימת במציאות.

שאילתהכיול לפי שורש הזמן מול הפסדים מדודים בריבוי תקופות, רמת 99%
ה-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)
Run this yourself

השורה הראשונה היא בדיקת זהות: ב-1 session הנתון המכויל שווה לנתון הנמדד, יחס של 1. בטווח של 20 sessions השניים נפרדים, ולא בכיוון שבו נהוג להזהיר מפני קיצורי דרך: כיול הנתון היומי מניב 13.8%, בעוד שהתשואות שנמדדו בפועל על פני אופק זה מציגות 10.7%, יחס של 0.78. בטווח זה, הנתון המכויל גבוה מהזנב הנמדד של ריבוי ימים. שני דפוסים פועלים כאן בכיוונים מנוגדים. התפלגות בעלת זנבות עבים ביום בודד הופכת ל"דקה" יותר ככל שמצרפים תשואות, והקוונטיל של 99% המצטבר מתרחב לאט יותר מהשורש הריבועי של אופק הזמן. מנגד, התקבצות תנודתיות (volatility clustering) פועלת בכיוון ההפוך, ומקבצת ימים סוערים בתוך חלון זמן אחד. בסדרה זו, הדפוס הראשון הוא הדומיננטי, אך אין ערובה לכך שזה יהיה המצב בנכס אחר או בחלון זמן אחר; זו בדיוק הנקודה: המכפיל הוא הנחה, לא מדידה. התקבצות זו היא גם המאפיין שעליו נשענת אסטרטגיית volatility targeting בעת התאמת גודל הפוזיציות.

מגבלה נוספת, נאמרת בבירור: כל האמור לעיל מתייחס ל-VaR של נכס בודד בקרן מדד רחבה. תיק המורכב מעשרה נכסים מתואמים נושא סיכון ריכוזיות ש-VaR תיקי מטפל בו באמצעות אומדן מתאם, והמתאמים נוטים לזנק בדיוק ברגע שבו האומדן הופך לקריטי.

הערות מתודולוגיות ומוסכמות
  • אחוזונים נגזרים מקוונטיל מדויק ולא מאומדן דגימה, וסימולציות מונטה קרלו מבוססות על רצף אקראי אחיד עם "זרע" (seed) קבוע המוזן ל-SQL, כך שכל נתון כאן מחושב מחדש לאותו ערך.
  • התשואות מבוססות על שינויי מחיר בין סגירה לסגירה ללא השקעה חוזרת של דיבידנדים, המוסכמה המקובלת ל-VaR יומי.
  • לוח אופקי הזמן משתמש בחלונות חופפים: תשואות של עשרים ימי מסחר עוקבים חולקות תשעה-עשר ימים משותפים, ולכן הזנב שלהן נשען על מספר קטן בהרבה של תצפיות בלתי תלויות ממה שמרמז מספר השורות.

שאלות נפוצות

מהו מדד VaR יומי ברמת סמך של 99%?

זהו שיעור ההפסד שיום מסחר אחד מתוך מאה ימי מסחר גרועים צפוי לעבור, בחישוב של יום מסחר בודד. בסדרה שלעיל, האומדן ההיסטורי הוא 3.09%. הנתון מציין סף בלבד ואינו מספק מידע על גודל ההפסדים מעבר לסף זה.

איזו שיטת חישוב VaR היא המדויקת ביותר?

אף אחת משלוש השיטות אינה מדויקת באופן מופשט, שכן כל אחת מהן עונה על השאלה תחת הנחות שונות. VaR היסטורי נאמן למדגם שניתן לו ואינו מתייחס לכל מה שהמדגם החמיץ. VaR פרמטרי הוא זול ונוטה להמעיט בערך הזנבות של מניות. מודל Monte Carlo טוב רק כטיב ההתפלגות המוזנת לתוכו.

מהו ההבדל בין VaR לבין Expected Shortfall?

VaR הוא סף ברמת סמך נבחרת. Expected Shortfall מחשב את ממוצע ההפסדים בימים שבהם הסף נפרץ. בסדרה זו, ה-Expected Shortfall ברמת סמך של 99% עומד על פי 1.44 מה-VaR, לעומת יחס של 1.15 בקירוב תחת התפלגות נורמלית.

האם ניתן להמיר VaR יומי ל-VaR ל-10 ימים?

הכפלה בשורש ריבועי של 10 היא קיצור הדרך המקובל, והיא מניחה שהתשואות בלתי תלויות ובעלות תנודתיות קבועה. לוח האופק מודד את הפער: לאורך 20 ימי מסחר, הנתון המחושב לפי הקיצור עמד על 13.8% לעומת 10.7% במדידה בפועל.


כל לוח לעיל כולל את שאילתת ה-SQL שיצרה אותו. כדי להריץ את אותם שלושה חישובים על Ticker או טווח זמן אחר, יש לבקש זאת באנגלית פשוטה במסוף Strasmore.

#risk#value at risk#expected shortfall#quant#position sizing