Maximum Drawdown: Lalim at Tagal ng Pagbawi
Ang maximum drawdown ay pinakamalaking pagbaba mula peak hanggang trough. Alamin kung kailan ito malalim at bakit mas matagal ang pagbawi sa bagong high.
Ang maximum drawdown ay pinakamalaking pagbaba mula peak hanggang trough sa isang serye ng halaga, na sinusukat bilang porsiyento ng running peak. Ang account na umakyat sa $120,000, bumaba sa $84,000, at pagkatapos ay nakabawi ay may maximum drawdown na 30%. Mananatili ang numerong ito magpakailanman dahil itinatala ng statistic ang pinakamalalang yugto sa buong kasaysayan, hindi ang kalagayan nito ngayon. Karamihan ay binabanggit lamang ang lalim ng pagbaba. May dalawa pang numerong kabilang sa parehong statistic: ang panahong lumipas mula peak hanggang low, at ang mas mahabang panahong mula low pabalik sa bagong high.
Paano kinakalkula ang maximum drawdown?
Isang pasada lamang sa buong series ang kailangan para sa kalkulasyon. Sa bawat observation, ina-update ang running maximum, sinusukat ang kasalukuyang halaga kumpara rito, at itinatala ang pinakamalaking pagbaba na nakita hanggang sa puntong iyon.
- Itakda ang running peak sa unang value.
- Sa bawat bagong value, itaas ang peak kung mas mataas ang value.
- Kalkulahin ang drawdown sa puntong iyon: value na hinati sa peak, bawas one.
- Itago ang pinaka-negatibong reading. Iyon ang maximum drawdown.
Walang returns series, volatility estimate, o distribution assumption na kasama rito. Gumagana ang loop sa simpleng listahan ng mga numero gamit ang Python standard library. Sa bagong Ubuntu box, i-install muna ang interpreter:
apt-get update && apt-get install -y python3
I-save ang loop bilang maxdd.py. Ang mga presyo sa ibaba ay isang gawa-gawang ten-point series na sapat ang liit para ma-check nang mano-mano:
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}%")
Patakbuhin ang python3 maxdd.py at ilalabas nito ang maximum drawdown: -15.4%. I-check ito nang mano-mano: ang peak bago ang low ay 104, ang low ay 88, at ang 88 na hinati sa 104 ay 0.846. Nagtatapos ang series sa 106, isang all-time high, at nananatili ang 15.4% na drawdown. Ang maximum drawdown ay permanenteng tala ng pinakamasamang sandali sa isang sample. Wala itong sinasabi tungkol sa kasalukuyang kinalalagyan ng series. Dalawa pang variable sa parehong loop ang maaaring magtala ng timing: ang index kung kailan naitakda ang peak at ang index kung kailan naitala ang pinakamalaking drawdown.
Ano ang hitsura ng drawdown curve
Pinananatili ng drawdown curve ang step 3 sa bawat punto sa halip na bawasan ito sa isang pinakamasamang halaga. Nasa zero ang linya tuwing nagpi-print ang serye ng bagong high, at nananatili itong nasa ibaba ng zero sa pagitan ng mga iyon. Kaya tinatawag na “underwater” ang pagitan. Narito ang curve para sa SPY, isang exchange traded fund na sumusubaybay sa S&P 500, batay sa mga closing price sa katapusan ng buwan mula Enero 2016.
Ang eksaktong SQL sa likod ng bawat numero
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_startSa 127 readings sa katapusan ng buwan, matagal na nananatiling malapit sa zero ang linya at bumababa lamang sa ilang malalalim na notch. Ang pinakahuling buwan sa talaan ay nasa -1.27% kumpara sa running peak. Dalawang katangian ng hugis nito ang mahalaga sa pag-unawa. Mabagal na pag-akyat ang mga recovery sa halip na matatalim na bounce, at nire-reset sa zero ng bawat bagong peak ang curve, kaya nabubura ang biswal na bakas ng mga naunang galaw.
Gaano katagal bago makabawi mula sa drawdown?
Tatlong magkahiwalay na numero ang nasa loob ng isang drawdown, at ang pagtrato sa mga ito bilang iisa ang pinakakaraniwang maling pagbasa sa isang performance table:
- Lalim: kung gaano kalaki ang ibinaba ng value mula sa peak nito, bilang porsiyento.
- Panahon bago maabot ang low: bilang ng calendar days mula sa peak hanggang sa bottom.
- Panahon ng recovery: bilang ng calendar days mula sa bottom pabalik sa isang bagong high.
Karaniwang pinakamahaba ang ikatlo, at ito ang hindi ipinapakita ng isang headline number. Muling binubuo ng panel sa ibaba ang bawat natapos na underwater stretch para sa SPY mula 2016 batay sa daily closes. Nagsisimula ang isang stretch sa araw na naitatag ang isang peak at nagtatapos sa araw na unang nagsara ang fund nang mas mataas kaysa rito.
Ang eksaktong SQL sa likod ng bawat numero
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 8Ang pinakamalalim na natapos na stretch sa listahan ay nagsisimula sa Feb 2020 at umaabot sa 34.2% sa ibaba ng dating peak. Bumaba ito nang 33 calendar days at umakyat pabalik nang 148, kaya nanatili itong underwater nang kabuuang 181 days. Ang kasunod na entry, mula sa Jan 2022, ay mas mababaw sa 25.4%, at nanatili nitong mas mababa ang fund kaysa sa dating high nito nang 746 days.
Lubos na magkahiwalay ang lalim at tagal. Ang isang matinding pagbagsak na mabilis ang round trip at ang mabagal na pagbaba na mababaw ngunit tumatagal nang maraming taon ay parehong naiikling sa iisang porsiyento. Ang crash noong March 2020 ang textbook na halimbawa ng unang anyo, at ipinapakita ng kung paano nakakabawi ang mga merkado mula sa mga crash ang ikalawang bahagi ng galaw.
Bakit lumalala ang maximum drawdown habang humahaba ang sinusukat na panahon
Maximum ang drawdown, kaya ang pagdaragdag ng kasaysayan ay maaari lamang magpanatiling pareho o magpalalim dito. Sa mas mahabang window, ang running peak sa bawat punto ay hindi bababa sa peak sa mas maikling window. Ito ang nagtatakda ng resulta sa arithmetic. Makikita ang epekto sa pagsukat sa parehong fund gamit ang limang window na lahat ay nagtatapos sa July 31, 2026.
Ang eksaktong SQL sa likod ng bawat numero
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_yearsSa trailing 1 year window, ang pinakamalaking pagbaba ay 9.1%. Kapag pinalawig ang kaparehong series hanggang 10 years, ang reading ay 34.2%, at ang pinakamababang punto ay nasa Mar 2020. Hindi naging mas mapanganib ang fund. Humaba lamang ang sample.
Binabago rin ng parehong arithmetic ang paghahambing ng mga strategy. Maaaring ilarawan ng three-year backtest at twenty-year backtest ang magkaparehong kilos ngunit mag-ulat pa rin ng magkaibang drawdown. Kaya kaunti ang ibig sabihin ng figure kung hindi kasama ang window na pinagmulan nito. Tinalakay sa Look-ahead bias sa backtesting ang isa pang paraan kung paano nagmumukhang mas maganda ang isang malinis na backtest kaysa sa aktuwal.
Maximum drawdown kumpara sa volatility
Sinusukat ng volatility ang karaniwang laki ng daily move sa alinmang direksiyon. Sinusukat naman ng maximum drawdown ang isang partikular na pababang galaw. Pareho silang risk numbers, pero magkaiba ang tanong na sinasagot ng bawat isa. Magkatabi sa panel ang mga ito para sa walong kilalang kumpanya sa loob ng limang taon hanggang July 31, 2026, kung saan annualized mula sa daily closes ang volatility.
Ang eksaktong SQL sa likod ng bawat numero
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 DESCBasahin nang magkasama ang dalawang column. Nagtala ang VZ ng pinakamalalim na pagbaba sa grupo, sa 45.4%, kumpara sa annualized volatility na 22.6%. Sa kabilang dulo, bumaba ang KO ng 20.9%, na may volatility na 16.7%. Ang volatility ay average ng galaw sa bawat araw sa loob ng period, at maaaring hindi makita sa average ang mahaba at mabagal na pagbaba. Ang drawdown ay ang iisang pinakamasamang landas na aktuwal na tinahak ng presyo. Maaaring magkaroon ang isang tahimik na holding na unti-unting bumababa sa loob ng dalawang taon ng malalim na drawdown kahit hindi kapansin-pansin ang volatility reading nito.
Sinusuri ng Anomalya ng mababang volatility kung paano kumikilos ang mga kalmadong pangalan sa mahahabang horizon, habang ipinapakita ng position sizing gamit ang Kelly criterion kung paano nagiging position size ang tolerance sa drawdown.
Hindi masasabi ng numero
May apat na limitasyong mahalagang tandaan:
- Isa itong na-realize na path. Maaaring nakabuo ang parehong proseso ng mas masamang resulta kung ibang draw ang nangyari.
- Nakadepende ito sa haba ng sample. Kaya maihahambing lamang ang dalawang drawdown kung magkatugma ang mga window.
- Nakadepende ito sa sampling frequency. Itinatago ng month-end closes ang mga intraday low, kaya mas maliit ang numerong lalabas kumpara sa daily closes sa parehong panahon.
- Wala itong forward information. Ang pagiging 30% na mas mababa sa isang peak ay walang sinasabi kung darating bukas ang ika-31 na punto.
Ang huling limitasyong ito ang dahilan kung bakit kailangan ng automated system ang drawdown policy, hindi lamang drawdown threshold. Sumasagot ang “Halt at 20%” sa isang tanong ngunit iniiwan nitong hindi nasasagot ang dalawa: ano ang mangyayari sa open positions kapag nag-halt, at anong ebidensiya ang magpapagana muli sa system. Tinutukoy ng Mga circuit breaker para sa trading bots ang istruktura ng naturang policy. Napupunta ang gastos ng arbitraryong flat rule sa recovery leg, kung saan hindi nakakasabay sa pag-akyat ang system na huminto malapit sa low at huli nang nag-restart. Naglalagay ng mga numero sa kalkulasyong iyon ang Hindi pagsabay sa pinakamagagandang araw.
Mahalaga ang isang detalye sa measurement bago paghambingin ang dalawang figure: magkaiba ang drawdown sa price series ng isang fund at ang drawdown sa aktuwal na account kapag may cash na pumapasok o lumalabas at kapag may natatanggap na dibidendo. Ganap itong tinatalakay sa kung paano sinusukat ang buwanang returns.
FAQ sa maximum drawdown
Ano ang magandang maximum drawdown?
Walang iisang pamantayang halaga. Kailangan ng benchmark at panahon ng pagsukat. Sa sampung taon hanggang July 31, 2026, ang pinakamalaking pagbaba ng SPY mula sa running peak nito ay umabot sa 34.2% batay sa daily closes. Hindi nangangahulugang mas ligtas ang isang strategy dahil mas maliit ang iniulat nitong drawdown sa mas maikling sample.
Pareho ba ang maximum drawdown at volatility?
Hindi. Inilalarawan ng volatility ang karaniwang daily move. Inilalarawan naman ng maximum drawdown ang pinakamasamang pagbaba mula peak hanggang trough. Maaaring magkaroon ng mas malalim na drawdown ang isang holding na may mababang volatility ngunit tuloy-tuloy na bumababa sa loob ng dalawang taon kaysa sa isang pabagu-bagong holding na patuloy namang nagtatakda ng mga bagong high.
Gaano katagal ang recovery mula sa maximum drawdown?
Nagkakaiba ito, at kadalasan ay mas matagal ang pag-akyat pabalik. Para sa SPY mula 2016, ang pinakamalalim na natapos na panahon sa ibaba ng naunang high ay umabot sa 181 calendar days mula peak hanggang sa bagong high. Sa panahong iyon, 33 araw ang ginugol sa pagbaba.
Nahuhulaan ba ng maximum drawdown ang mga pagkalugi sa hinaharap?
Hindi. Inilalarawan nito ang isang path na nangyari na, at halos palaging mas malaking figure ang lalabas kapag mas mahaba ang sample. Itinatala nito ang mga drawdown na nalampasan na ng isang strategy, ngunit walang limitasyon sa maaaring mangyari sa susunod.
Naka-store ang SQL sa likod ng bawat panel sa itaas. Buksan ang isa, palitan ang ticker o ang window, at patakbuhin ang parehong drawdown arithmetic sa Strasmore terminal.