Strasmore Research
Навчання Matt ConnorВід Matt Connor · Оновлено 2026-08-08

Максимальна просадка: глибина та відновлення

Максимальна просадка показує найбільше падіння вартості від піку до мінімуму. Дізнайтеся, що вважається глибокою просадкою та чому відновлення до нового максимуму триває довше.

Максимальна просадка — це найбільше падіння вартості від піку до мінімуму, виміряне у відсотках від поточного пікового значення. Якщо рахунок зріс до $120,000, знизився до $84,000, а потім відновився, його максимальна просадка становить 30%. Це значення не змінюється, оскільки показник фіксує найгірший період за всю історію, а не поточний стан рахунку. Більшість інвесторів наводять лише глибину просадки. Але цей показник містить ще два параметри: час від піку до мінімуму та значно довший період від мінімуму до нового максимуму.

Як розраховують максимальну просадку?

Увесь розрахунок виконується одним проходом за часовим рядом. На кожному спостереженні оновлюється поточний максимум, поточне значення порівнюється з ним, а потім зберігається найгірший результат із уже отриманих.

  1. Встановіть поточний максимум на рівні першого значення.
  2. На кожному новому значенні підвищуйте максимум, якщо нове значення вище.
  3. Розрахуйте просадку в цій точці: значення поділіть на максимум і відніміть один.
  4. Збережіть найменше значення. Це і є максимальна просадка.

Для цього не потрібні ряд даних про доходність, оцінка волатильності чи припущення щодо розподілу. Цикл працює зі звичайним списком чисел і стандартною бібліотекою 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 — ETF, що відстежує S&P 500, — за цінами закриття на кінець місяця починаючи із січня 2016 року.

ЗапитКрива просадки SPY: ціна закриття на кінець місяця проти поточного піку, 2016–2026
Точний 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
Run this yourself

За 127 спостереженнями на кінець місяця лінія тривалий час залишається близькою до нуля, а потім опускається в кілька глибоких западин. Останнє доступне значення за місяць становить -1.27% відносно поточного піку. Форма кривої демонструє дві важливі особливості. Відновлення відбувається поступово, а не у вигляді різких відскоків. Кожен новий максимум повертає криву до нуля й стирає візуальний слід попереднього періоду.

Скільки часу потрібно, щоб відновитися після просадки?

В одній просадці є три окремі показники. Найчастіша помилка під час читання таблиці дохідності — сприймати їх як один показник:

  1. Глибина: на скільки відсотків вартість впала від свого піку.
  2. Час до мінімуму: кількість календарних днів від піку до дна.
  3. Час відновлення: кількість календарних днів від дна до нового максимуму.

Третій показник зазвичай є найдовшим. Саме його ніколи не відображає один заголовковий показник. Панель нижче відновлює всі завершені періоди перебування SPY нижче попереднього максимуму з 2016 року на основі денних цін закриття. Період починається в день встановлення максимуму і завершується в день, коли фонд уперше закривається вище нього.

ЗапитЗавершені просадки 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
Run this yourself

Найглибший завершений період у списку починається у Feb 2020 і сягає 34.2% нижче попереднього максимуму. Падіння тривало 33 календарних днів, а відновлення — 148 днів; загалом фонд залишався нижче максимуму 181 днів. Наступний період, починаючи з Jan 2022, був менш глибоким — 25.4%, але фонд залишався нижче попереднього максимуму 746 днів.

Глибина і тривалість можуть суттєво відрізнятися. Різке падіння з швидким відновленням і неглибоке зниження, яке триває роками, стискаються в один відсотковий показник. Обвал у березні 2020 року є хрестоматійним прикладом першого сценарію, а відновлення ринків після обвалів описує другий етап цього процесу.

Чому максимальна просадка погіршується зі збільшенням періоду вимірювання

Максимальна просадка є максимумом, тому додавання історичних даних може лише залишити її незмінною або збільшити. У довшому періоді поточний максимум у кожній точці щонайменше такий самий високий, як і в коротшому. Це й визначає арифметичний результат. Вимірювання показників одного й того самого фонду за п’ятьма періодами, що завершуються 31 липня 2026 року, демонструє цей ефект.

ЗапитТой самий фонд, п’ять періодів аналізу: максимальна просадка SPY за довжиною вибірки станом на 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
Run this yourself

За останній 1 year період найбільше падіння становило 9.1%. Якщо розширити той самий часовий ряд до 10 years, показник становитиме 34.2%, а найгірша точка припаде на Mar 2020. Фонд не став ризикованішим. Просто вибірка стала довшою.

Та сама арифметика спотворює порівняння стратегій. Backtest за три роки та backtest за двадцять років можуть описувати ідентичну поведінку, але показувати дуже різні максимальні просадки. Тому без зазначення періоду вимірювання цей показник мало що означає. У матеріалі Погляд у майбутнє під час backtesting описано інший спосіб, у який зовні переконливий backtest створює надто сприятливе враження про себе.

Максимальна просадка проти волатильності

Волатильність вимірює типовий розмір денного руху в будь-якому напрямку. Максимальна просадка вимірює один конкретний низхідний шлях. Обидва показники характеризують ризик, але відповідають на різні запитання. У таблиці їх наведено поруч для восьми широко відомих компаній за п’ятирічний період до 31 липня 2026 року; волатильність розраховано в річному вимірі на основі денних цін закриття.

ЗапитМаксимальна просадка проти річної волатильності: вісім акцій великої капіталізації, п’ять років станом на 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
Run this yourself

Розглядайте ці два стовпці разом. VZ продемонструвала найглибше падіння у групі — 45.4%, за річної волатильності 22.6%. Найменше падіння у KO: 20.9% за волатильності 16.7%. Волатильність є середнім показником за кожен день періоду, а середні значення не відображають повною мірою тривале повільне зниження. Просадка — це найгірший шлях, який фактично пройшла ціна. Актив із низькою волатильністю, який поступово дешевшає протягом двох років, може мати значну просадку за непоказового значення волатильності.

Аномалія низької волатильності показує, як спокійні акції поводяться на довгих часових горизонтах, а визначення розміру позиції за критерієм Келлі демонструє, як допустимий рівень просадки перетворюється на розмір позиції.

Що цей показник не може показати

Варто пам’ятати про чотири обмеження:

  1. Це один реалізований сценарій. Той самий процес за іншої траєкторії міг би дати значно гірший результат.
  2. Показник залежить від довжини вибірки. Тому два просідання можна порівнювати лише за однакові періоди.
  3. Показник залежить від частоти спостережень. Ціни на кінець місяця приховують внутрішньоденні мінімуми й дають менше значення, ніж денні ціни за той самий період.
  4. Показник не містить інформації про майбутнє. Те, що ціна на 30% нижча за пік, нічого не говорить про те, чи буде досягнуто 31% завтра.

Саме останнє обмеження пояснює, чому автоматизованій системі потрібна політика управління просіданням, а не просто порогове значення. Правило «зупинити систему при просіданні на 20%» відповідає на одне запитання й залишає без відповіді ще два: що робити з відкритими позиціями після зупинки та які докази потрібні для повторного запуску системи. Автоматичні вимикачі для торгових ботів розглядає структуру такої політики. Вартість довільного фіксованого правила проявляється на етапі відновлення: система, яка зупинилася поблизу мінімуму й відновила роботу із запізненням, пропускає зростання. Пропущені найкращі дні показує цю арифметику в цифрах.

Перед порівнянням двох показників важливо врахувати один нюанс вимірювання: просідання за ціновим рядом фонду та просідання на реальному рахунку відрізняються, коли відбувається приплив або відтік грошових коштів, а також коли нараховуються дивіденди. Повний розбір цього питання наведено в матеріалі як вимірюють місячну дохідність.

Максимальна просадка: поширені запитання

Якою є прийнятна максимальна просадка?

Універсального значення немає. Потрібні лише бенчмарк і період, із яким проводять порівняння. За десять років до 31 липня 2026 року найглибше падіння SPY від локального максимуму, виміряне за денними цінами закриття, становило 34.2%. Стратегія, яка показує менше значення за коротший період, не обов’язково була безпечнішою.

Чи є максимальна просадка тим самим, що й волатильність?

Ні. Волатильність описує типовий денний рух. Максимальна просадка описує найгіршу траєкторію від піку до мінімуму. Актив із низькою волатильністю, який стабільно знижується протягом двох років, може мати глибшу просадку, ніж актив із різкими коливаннями, який продовжує встановлювати нові максимуми.

Скільки часу потрібно для відновлення після максимальної просадки?

Це залежить від ситуації. Відновлення часто займає більше часу, ніж саме падіння. Для SPY з 2016 року найдовший завершений період нижче попереднього максимуму тривав 181 календарних днів — від максимуму до встановлення нового максимуму. Із них 33 днів припали на зниження.

Чи прогнозує максимальна просадка майбутні збитки?

Ні. Вона описує траєкторію, яка вже відбулася. Довший період спостереження майже завжди дає більше значення. Показник відображає те, що стратегія пережила до цього моменту, але не обмежує можливі майбутні втрати.


У кожній панелі вище збережено SQL-код запиту. Відкрийте потрібну панель, замініть тикер або період і виконайте той самий розрахунок просадки в терміналі Strasmore.

#risk#drawdown#backtesting#performance metrics#python