מהי ירידה מרבית? עומק הירידה מול זמן ההתאוששות
הכירו את מדד הירידה המרבית, כיצד מחשבים אותו ומה ההבדל בין עומק הירידה לזמן ההתאוששות. דוגמה מעשית מראה מדוע הדרך לשיא חדש עלולה להימשך זמן רב.
הירידה המרבית (Maximum Drawdown) היא הירידה הגדולה ביותר משיא לשפל בסדרת ערכים, הנמדדת כאחוז מהשיא המתעדכן. חשבון שטיפס ל־$120,000, ירד ל־$84,000 ולאחר מכן התאושש, מציג ירידה מרבית של 30%. הנתון הזה נשאר 30% לתמיד, משום שהוא מתעד את התקופה הגרועה ביותר בתולדות החשבון ולא את מצבו כיום. רוב האנשים מציינים את עומק הירידה ומסתפקים בכך. אך באותו נתון גלומים שני מדדים נוספים: הזמן מהשיא עד לשפל, והזמן הארוך בהרבה מהשפל עד לשיא חדש.
כיצד מחשבים ירידה מרבית?
החישוב כולו מתבצע במעבר אחד על הסדרה. בכל תצפית מעדכנים את השיא המצטבר, מודדים את הערך הנוכחי ביחס אליו ושומרים את הקריאה הגרועה ביותר שנרשמה עד אותו שלב.
- מגדירים את השיא המצטבר כשווה לערך הראשון.
- בכל ערך חדש מעלים את השיא אם הערך גבוה ממנו.
- מחשבים את הירידה באותה נקודה: הערך חלקי השיא, פחות אחד.
- שומרים את הקריאה השלילית ביותר. זו הירידה המרבית.
אין צורך בסדרת תשואות, באומדן תנודתיות או בהנחת התפלגות. הלולאה פועלת על רשימה פשוטה של מספרים באמצעות ספריית Python הסטנדרטית. בשרת Ubuntu חדש יש להתקין תחילה את המפרש:
apt-get update && apt-get install -y python3
שמרו את הלולאה בשם maxdd.py. המחירים שלהלן הם סדרה מומצאת בת עשר נקודות, שנשמרה קטנה מספיק כדי לאפשר בדיקה ידנית:
prices = [100.0, 104.0, 98.0, 92.0, 95.0, 88.0, 90.0, 101.0, 99.0, 106.0]
peak = prices[0]
max_dd = 0.0
for price in prices:
if price > peak:
peak = price
drawdown = price / peak - 1.0
if drawdown < max_dd:
max_dd = drawdown
print(f"maximum drawdown: {max_dd * 100:.1f}%")
הריצו את python3 maxdd.py, והוא ידפיס maximum drawdown: -15.4%. בדקו זאת ידנית: השיא שלפני השפל הוא 104, השפל הוא 88, ו-88 חלקי 104 שווה ל-0.846. הסדרה מסתיימת לאחר מכן ב-106, שיא של כל הזמנים, אך הירידה בשיעור 15.4% עדיין נותרת בעינה. ירידה מרבית היא תיעוד קבוע של הרגע הגרוע ביותר במדגם, והיא אינה אומרת דבר על המקום שבו הסדרה נמצאת כיום. שני משתנים נוספים באותה לולאה מתעדים את העיתוי: האינדקס שבו נקבע השיא והאינדקס שבו נרשמה הקריאה הגרועה ביותר.
איך נראית עקומת ירידה מהשיא
עקומת ירידה מהשיא שומרת את שלב 3 בכל נקודה, במקום לצמצם אותו לערך הגרוע ביותר. הקו נמצא באפס בכל פעם שסדרת הנתונים רושמת שיא חדש, ויורד מתחת לאפס בין השיאים. לכן הפער מכונה "מתחת למים". זו העקומה של SPY, קרן סל העוקבת אחר S&P 500, לפי שערי הסגירה בסוף החודש מאז ינואר 2016.
ה-SQL המדויק מאחורי כל מספר
WITH monthly AS (
SELECT toStartOfMonth(toDate(toTimeZone(window_start, 'America/New_York'))) AS month_start,
argMax(toFloat64(close), window_start) AS close_px
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2016-01-01')
AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-07-31')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY month_start
),
runs AS (
SELECT month_start,
close_px,
max(close_px) OVER (ORDER BY month_start
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS running_peak
FROM monthly
)
SELECT formatDateTime(month_start, '%Y-%m') AS month,
round(100 * (close_px / running_peak - 1), 2) AS drawdown_pct
FROM runs
ORDER BY month_startלאורך 127 מדידות בסוף החודש, הקו נותר במשך תקופות ארוכות סמוך לאפס ויורד למספר שקעים עמוקים. בחודש האחרון שנכלל בנתונים נרשמה ירידה של -1.27% ביחס לשיא המצטבר. צורת העקומה ממחישה שני מאפיינים. ההתאוששות מתרחשת בטיפוס איטי ולא בקפיצות חדות, וכל שיא חדש מאפס את העקומה ומוחק את הזיכרון החזותי של מה שקדם לו.
כמה זמן נדרש להתאוששות מירידה חדה?
בתוך כל ירידה חדה קיימים שלושה נתונים נפרדים. הטעות הנפוצה ביותר בקריאת טבלת ביצועים היא להתייחס אליהם כאל נתון אחד:
- עומק הירידה: שיעור הירידה של הערך מהשיא, באחוזים.
- הזמן עד לשפל: מספר הימים הקלנדריים מהשיא ועד לתחתית.
- זמן ההתאוששות: מספר הימים הקלנדריים מהתחתית ועד לשיא חדש.
הנתון השלישי הוא בדרך כלל הארוך ביותר. זה גם הנתון שמספר כותרתי לעולם אינו מציג. הפאנל שלהלן משחזר כל תקופה שהושלמה מתחת לשיא עבור SPY מאז 2016, על בסיס שערי הסגירה היומיים. תקופה כזו מתחילה ביום שבו נקבע שיא ומסתיימת ביום שבו הקרן נסגרת לראשונה מעליו.
ה-SQL המדויק מאחורי כל מספר
WITH daily AS (
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS session_date,
argMax(toFloat64(close), window_start) AS close_px
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2016-01-01')
AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-07-31')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY session_date
),
runs AS (
SELECT session_date,
close_px,
max(close_px) OVER (ORDER BY session_date
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS running_peak
FROM daily
),
episodes AS (
SELECT running_peak AS peak_px,
min(session_date) AS peak_date,
argMin(session_date, close_px) AS trough_date,
min(close_px) AS trough_px
FROM runs
GROUP BY running_peak
),
sequenced AS (
SELECT peak_px,
peak_date,
trough_date,
trough_px,
leadInFrame(peak_date, 1) OVER (ORDER BY peak_date
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS recovery_date
FROM episodes
)
SELECT formatDateTime(peak_date, '%b %Y') AS episode_label,
round(100 * (1 - trough_px / peak_px), 1) AS fall_from_peak_pct,
dateDiff('day', peak_date, trough_date) AS days_to_trough,
dateDiff('day', trough_date, recovery_date) AS days_to_new_high,
dateDiff('day', peak_date, recovery_date) AS days_underwater
FROM sequenced
WHERE recovery_date > trough_date
AND round(100 * (1 - trough_px / peak_px), 1) >= 5
ORDER BY fall_from_peak_pct DESC
LIMIT 8התקופה העמוקה ביותר שהושלמה ברשימה מתחילה ב-Feb 2020 ומגיעה לירידה של 34.2% מתחת לשיא הקודם. היא נמשכה 33 ימים קלנדריים בדרכה מטה ו-148 ימים בדרכה חזרה, כלומר 181 ימים בסך הכול מתחת לשיא. הרשומה הבאה, משנת Jan 2022, מתונה יותר ועומקה 25.4%, אך היא הותירה את הקרן מתחת לשיא הקודם במשך 746 ימים.
עומק הירידה ומשך הזמן שלה אינם קשורים בהכרח זה לזה. ירידה חדה עם התאוששות מהירה ותהליך שחיקה מתון שנמשך שנים מתכווצים שניהם לנתון אחוזי אחד. הקריסה של מרץ 2020 היא דוגמה קלאסית למקרה הראשון, ואילו האופן שבו השווקים מתאוששים מקריסות מתאר את השלב השני במסע.
מדוע ה-drawdown המרבי מחמיר ככל שתקופת המדידה מתארכת
Maximum drawdown הוא ערך מרבי, ולכן הוספת היסטוריה יכולה רק להשאיר אותו ללא שינוי או להעמיק אותו. השיא המצטבר בחלון ארוך יותר גבוה לפחות כמו השיא בחלון קצר יותר בכל נקודת זמן. זה קובע את התוצאה החשבונית. מדידת אותה קרן בחמישה חלונות, שכולם מסתיימים ב-31 ביולי 2026, ממחישה את ההשפעה.
ה-SQL המדויק מאחורי כל מספר
WITH daily AS (
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS session_date,
argMax(toFloat64(close), window_start) AS close_px
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY'
AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2016-07-01')
AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-07-31')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY session_date
),
scoped AS (
SELECT arrayJoin([1, 2, 3, 5, 10]) AS lookback_years,
session_date,
close_px
FROM daily
),
windowed AS (
SELECT lookback_years, session_date, close_px
FROM scoped
WHERE session_date >= subtractYears(toDate('2026-07-31'), lookback_years)
),
runs AS (
SELECT lookback_years,
session_date,
close_px,
max(close_px) OVER (PARTITION BY lookback_years ORDER BY session_date
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS running_peak
FROM windowed
)
SELECT concat(toString(lookback_years), if(lookback_years = 1, ' year', ' years')) AS lookback,
round(100 * max(1 - close_px / running_peak), 1) AS max_drawdown_pct,
formatDateTime(argMax(session_date, 1 - close_px / running_peak), '%b %Y') AS worst_point
FROM runs
GROUP BY lookback_years
ORDER BY lookback_yearsבחלון 1 year האחרון, הירידה החדה ביותר שנמדדה הייתה 9.1%. כאשר מרחיבים את אותה סדרת נתונים ל-10 years, מתקבלת תוצאה של 34.2%, כאשר נקודת השפל נרשמה ב-Mar 2020. הקרן לא נעשתה מסוכנת יותר. המדגם פשוט התארך.
אותו חישוב מעוות גם השוואות בין אסטרטגיות. Backtest של שלוש שנים ו-Backtest של עשרים שנה יכולים לתאר התנהגות זהה ועדיין להציג drawdown שונה מאוד. לכן לנתון אין משמעות רבה בלי לציין את חלון המדידה שאליו הוא מתייחס. הטיית הסתכלות קדימה ב-Backtesting עוסקת בדרך נוספת שבה Backtest שנראה נקי מציג את עצמו באור מחמיא מדי.
ירידה מרבית לעומת תנודתיות
תנודתיות מודדת את הגודל האופייני של שינוי יומי, לכל כיוון. ירידה מרבית מודדת מסלול ירידה מסוים אחד. שתיהן מדידות סיכון, אך הן עונות על שאלות שונות. התרשים מציג אותן זו לצד זו עבור שמונה מניות מוכרות, בחמש השנים שהסתיימו ב־31 ביולי 2026, כאשר התנודתיות מחושבת במונחים שנתיים על בסיס שערי הסגירה היומיים.
ה-SQL המדויק מאחורי כל מספר
WITH daily AS (
SELECT ticker,
toDate(toTimeZone(window_start, 'America/New_York')) AS session_date,
argMax(toFloat64(close), window_start) AS close_px
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('SPY', 'AAPL', 'MSFT', 'KO', 'JNJ', 'CVX', 'VZ', 'PG')
AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2021-08-01')
AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-07-31')
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY ticker, session_date
),
runs AS (
SELECT ticker,
session_date,
close_px,
max(close_px) OVER (PARTITION BY ticker ORDER BY session_date
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS running_peak,
lagInFrame(close_px, 1) OVER (PARTITION BY ticker ORDER BY session_date
ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prev_close
FROM daily
)
SELECT ticker,
round(100 * max(1 - close_px / running_peak), 1) AS max_drawdown_pct,
round(100 * sqrt(252) * stddevSampIf(close_px / prev_close - 1, prev_close > 0), 1) AS annualized_volatility_pct
FROM runs
GROUP BY ticker
HAVING countIf(prev_close > 0) > 20
ORDER BY max_drawdown_pct DESCיש לקרוא את שני הטורים יחד. VZ רשמה את הירידה העמוקה ביותר בקבוצה, בשיעור של 45.4%, לעומת תנודתיות שנתית של 22.6%. בקצה המתון יותר, KO ירדה בשיעור של 20.9%, עם תנודתיות של 16.7%. תנודתיות היא ממוצע של כל הימים בתקופה, וממוצעים נוטים להקל על ירידה ארוכה ואיטית. ירידה מרבית היא המסלול הגרוע ביותר שהמחיר עבר בפועל. החזקה יציבה שמידרדרת במשך שנתיים יכולה לרשום ירידה מרבית עמוקה, אף שמדד התנודתיות שלה אינו חריג.
אנומליית התנודתיות הנמוכה בוחנת כיצד מניות רגועות מתנהגות לאורך אופקי זמן ארוכים, ואילו קביעת גודל פוזיציה לפי קריטריון Kelly מראה כיצד סבילות לירידה מתורגמת לגודל פוזיציה.
מה שהמספר אינו יכול לספר
יש ארבע מגבלות שכדאי לזכור:
- זהו מסלול ממומש אחד. אותו תהליך עשוי היה להניב נתון גרוע בהרבה במסלול אחר.
- הוא תלוי באורך המדגם, ולכן אפשר להשוות בין שתי ירידות רק בחלונות זמן זהים.
- הוא תלוי בתדירות הדגימה. שערי הסגירה בסוף החודש מסתירים את השפל התוך-יומי ומניבים נתון נמוך יותר לעומת שערי סגירה יומיים באותה תקופה.
- אין בו מידע צופה פני עתיד. העובדה שנכס נמצא 30% מתחת לשיא אינה אומרת דבר על השאלה אם הנקודה ה-31 תגיע מחר.
המגבלה האחרונה היא הסיבה לכך שמערכת אוטומטית זקוקה למדיניות ירידה מרבית, ולא רק לסף ירידה. הקביעה "לעצור בירידה של 20%" עונה על שאלה אחת ומשאירה שתיים ללא מענה: מה יקרה לפוזיציות הפתוחות בעת העצירה, ואילו ראיות יאפשרו להפעיל מחדש את המערכת. מפסקי הגנה למסחר באמצעות בוטים עוסק במבנה של מדיניות כזו. עלותה של הוראה שרירותית וקבועה מתבטאת בשלב ההתאוששות, כאשר מערכת שנעצרת סמוך לשפל ומתניעה מחדש באיחור אינה משתתפת בעלייה. החמצת הימים הטובים ביותר מציג את החשבון במספרים.
פרט מדידה אחד חשוב לפני שמשווים בין שני נתונים: ירידה מרבית בסדרת המחירים של קרן וירידה מרבית בחשבון אמיתי שונות זו מזו בכל פעם שמזומן נכנס לחשבון או יוצא ממנו, וכן בכל פעם שמתקבלים דיבידנדים. הנושא הזה מוסבר במלואו ב-כיצד נמדדות תשואות חודשיות.
שאלות נפוצות על ירידה מרבית
מהי ירידה מרבית סבירה?
אין נתון אוניברסלי. יש רק מדד ייחוס ותקופת מדידה. בעשר השנים שהסתיימו ב-31 ביולי 2026, הירידה החדה ביותר של SPY משיא מתגלגל, לפי שערי הסגירה היומיים, עמדה על 34.2%. אסטרטגיה שמציגה נתון נמוך יותר על פני תקופה קצרה יותר אינה בהכרח בטוחה יותר.
האם ירידה מרבית זהה לתנודתיות?
לא. תנודתיות מתארת את השינוי היומי האופייני. ירידה מרבית מתארת את המסלול הגרוע ביותר, משיא לשפל. נכס בעל תנודתיות נמוכה שיורד בהתמדה במשך שנתיים עלול לרשום ירידה מרבית עמוקה יותר מנכס תנודתי שממשיך לקבוע שיאים חדשים.
כמה זמן נדרש להתאושש מירידה מרבית?
הדבר משתנה, ולעיתים קרובות העלייה חזרה נמשכת זמן רב יותר מהירידה. עבור SPY מאז 2016, התקופה השלמה הארוכה ביותר מתחת לשיא קודם נמשכה 181 ימים קלנדריים, מהשיא ועד לשיא חדש. מתוכה, 33 ימים עברו בירידות.
האם ירידה מרבית מנבאת הפסדים עתידיים?
לא. היא מתארת מסלול אחד שכבר התרחש, ותקופת מדידה ארוכה יותר מניבה כמעט תמיד נתון גדול יותר. היא מתעדת את מה שהאסטרטגיה שרדה עד כה, אך אינה מגבילה את מה שעלול לקרות בהמשך.
כל לוח המופיע לעיל שומר את שאילתת ה-SQL שמאחוריו. פתחו לוח, החליפו את הטיקר או את תקופת המדידה, והריצו את אותו חישוב של ירידה מרבית במסוף Strasmore.