Apa Itu Maximum Drawdown? Kedalaman dan Pemulihan
Maximum drawdown adalah penurunan terbesar dari puncak ke titik terendah. Pahami kedalaman penurunan dan mengapa pemulihan ke rekor tertinggi baru membutuhkan waktu lebih lama.
Maximum drawdown adalah penurunan terbesar dari puncak ke titik terendah dalam suatu rangkaian nilai, yang diukur sebagai persentase dari puncak berjalan. Akun yang naik hingga $120.000, turun menjadi $84.000, lalu pulih, memiliki maximum drawdown sebesar 30%. Angka ini tetap tercatat selamanya karena statistik tersebut merekam periode terburuk sepanjang riwayat, bukan kondisi saat ini. Kebanyakan orang hanya menyebut besar penurunannya. Namun, statistik yang sama juga mencakup dua angka lain: waktu dari puncak hingga titik terendah, serta waktu yang jauh lebih lama dari titik terendah itu hingga mencapai rekor tertinggi baru.
Bagaimana maximum drawdown dihitung?
Seluruh perhitungan dilakukan dalam satu kali iterasi atas rangkaian data. Pada setiap observasi, Anda memperbarui nilai maksimum berjalan, mengukur nilai saat ini terhadapnya, lalu menyimpan hasil terburuk yang telah terlihat.
- Tetapkan puncak berjalan ke nilai pertama.
- Pada setiap nilai baru, naikkan puncak jika nilainya lebih tinggi.
- Hitung drawdown pada titik tersebut: nilai dibagi puncak, lalu dikurangi satu.
- Simpan hasil yang paling negatif. Itulah maximum drawdown.
Tidak ada return series, estimasi volatilitas, atau asumsi distribusi yang digunakan. Loop ini berjalan pada daftar angka sederhana dengan standard library Python. Pada instalasi Ubuntu baru, pasang interpreter terlebih dahulu:
apt-get update && apt-get install -y python3
Simpan loop tersebut sebagai maxdd.py. Harga di bawah ini adalah rangkaian sepuluh titik yang dibuat sebagai contoh dan cukup kecil untuk diperiksa secara manual:
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}%")
Jalankan python3 maxdd.py dan hasilnya adalah maximum drawdown: -15.4%. Periksa secara manual: puncak sebelum titik terendah adalah 104, titik terendahnya 88, dan 88 dibagi 104 adalah 0,846. Rangkaian tersebut kemudian berakhir pada 106, yang merupakan all-time high, tetapi angka 15,4% tetap menjadi hasilnya. Maximum drawdown merupakan catatan permanen atas titik terburuk dalam suatu sampel. Ukuran ini tidak menunjukkan posisi rangkaian saat ini. Dua variabel tambahan dalam loop yang sama dapat mencatat waktunya: indeks saat puncak terbentuk dan indeks saat hasil terburuk terjadi.
Seperti apa kurva drawdown
Kurva drawdown mempertahankan langkah 3 pada setiap titik, bukan mereduksinya menjadi satu nilai terburuk. Garis berada di nol setiap kali seri mencetak level tertinggi baru dan berada di bawah nol di antaranya. Karena itu, selisih tersebut disebut “underwater”. Berikut kurva SPY, exchange-traded fund yang melacak S&P 500, berdasarkan harga penutupan akhir bulan sejak Januari 2016.
SQL tepat di balik setiap angka
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_startDari 127 pembacaan akhir bulan, garis tersebut berada lama di dekat nol dan turun ke sejumlah kecil titik penurunan yang dalam. Bulan terakhir dalam data berada di -1.27% dibandingkan dengan puncak berjalan. Dua karakteristik bentuk kurva ini menjelaskan konsep tersebut. Pemulihan berlangsung sebagai kenaikan perlahan, bukan lonjakan tajam. Setiap puncak baru mengatur ulang kurva ke nol dan menghapus jejak visual dari periode sebelumnya.
Berapa lama waktu yang dibutuhkan untuk pulih dari drawdown?
Dalam satu drawdown terdapat tiga angka yang berbeda. Menganggapnya sebagai satu angka merupakan kesalahan tafsir yang paling umum dalam tabel kinerja:
- Kedalaman: seberapa jauh nilai turun dari puncaknya, dalam persentase.
- Waktu menuju titik terendah: jumlah hari kalender dari puncak ke titik terendah.
- Waktu pemulihan: jumlah hari kalender dari titik terendah hingga mencapai level tertinggi baru.
Angka ketiga biasanya merupakan yang terpanjang. Angka inilah yang tidak pernah ditampilkan oleh angka utama. Panel di bawah ini menyusun kembali setiap periode underwater yang telah selesai untuk SPY sejak 2016 berdasarkan harga penutupan harian. Suatu periode dimulai pada hari ketika puncak tercapai dan berakhir pada hari ketika fund pertama kali ditutup di atas puncak tersebut.
SQL tepat di balik setiap angka
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 8Periode terdalam yang telah selesai dalam daftar dimulai pada Feb 2020 dan mencapai 34.2% di bawah puncak sebelumnya. Nilainya turun selama 33 hari kalender dan membutuhkan 148 hari untuk pulih, sehingga total berada dalam kondisi underwater selama 181 hari. Entri berikutnya, dari Jan 2022, lebih dangkal, yaitu 25.4%, tetapi fund tersebut tetap berada di bawah level tertinggi sebelumnya selama 746 hari.
Kedalaman dan durasi dapat bergerak sepenuhnya terpisah. Penurunan tajam dengan pemulihan cepat dan penurunan dangkal yang berlangsung selama bertahun-tahun sama-sama diringkas menjadi satu angka persentase. Kejatuhan pasar pada Maret 2020 merupakan contoh klasik bentuk pertama, sedangkan bagaimana pasar pulih dari kejatuhan mengikuti tahap kedua dari perjalanan tersebut.
Mengapa maximum drawdown memburuk semakin lama periode pengukuran
Maximum drawdown adalah nilai maksimum, sehingga penambahan data historis hanya dapat membuatnya tetap atau menjadi lebih dalam. Running peak dalam periode yang lebih panjang setidaknya sama tinggi pada setiap titik dibandingkan peak dalam periode yang lebih pendek. Karena itu, hasil perhitungannya akan tetap atau memburuk. Pengukuran atas fund yang sama dalam lima periode, yang semuanya berakhir pada 31 Juli 2026, menunjukkan efek tersebut.
SQL tepat di balik setiap angka
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_yearsDalam periode trailing 1 year, penurunan terburuk tercatat sebesar 9.1%. Ketika rangkaian data yang sama diperpanjang hingga 10 years, hasilnya menjadi 34.2%, dengan titik terburuk terjadi pada Mar 2020. Fund tersebut tidak menjadi lebih berisiko. Sampelnya menjadi lebih panjang.
Aritmetika yang sama juga mendistorsi perbandingan strategi. Backtest tiga tahun dan backtest dua puluh tahun dapat menggambarkan perilaku yang identik, tetapi tetap melaporkan drawdown yang sangat berbeda. Karena itu, angka tersebut tidak banyak berarti tanpa keterangan periodenya. Look-ahead bias dalam backtesting membahas cara lain yang membuat backtest yang tampak bersih menilai dirinya terlalu baik.
Maximum drawdown vs volatility
Volatility mengukur besarnya pergerakan harian yang umum, baik naik maupun turun. Maximum drawdown mengukur satu jalur penurunan tertentu. Keduanya merupakan ukuran risiko, tetapi menjawab pertanyaan yang berbeda. Panel ini menempatkan keduanya berdampingan untuk delapan saham unggulan selama lima tahun hingga 31 Juli 2026, dengan volatility yang dianualisasi dari harga penutupan harian.
SQL tepat di balik setiap angka
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 DESCBaca kedua kolom tersebut secara bersamaan. VZ mencatat penurunan terdalam dalam kelompok ini, sebesar 45.4%, dibandingkan dengan volatility tahunan sebesar 22.6%. Di sisi penurunan yang paling dangkal, KO turun 20.9% dengan volatility sebesar 16.7%. Volatility merupakan rata-rata dari setiap hari dalam periode tersebut, dan rata-rata dapat mengabaikan penurunan panjang yang berlangsung perlahan. Drawdown adalah jalur terburuk yang benar-benar ditempuh harga. Aset yang pergerakannya tenang tetapi terus menurun selama dua tahun dapat mencatat drawdown yang dalam meskipun pembacaan volatility-nya biasa saja.
Anomali volatility rendah membahas perilaku saham-saham dengan pergerakan tenang dalam jangka panjang, sedangkan penentuan ukuran posisi dengan kriteria Kelly menunjukkan bagaimana toleransi terhadap drawdown diterjemahkan menjadi ukuran posisi.
Hal yang tidak dapat dijelaskan oleh angka
Ada empat keterbatasan yang perlu diingat:
- Angka tersebut hanya merepresentasikan satu jalur yang terealisasi. Proses yang sama dapat menghasilkan angka yang jauh lebih buruk pada pengambilan sampel yang berbeda.
- Angka tersebut bergantung pada panjang sampel. Karena itu, dua drawdown hanya dapat dibandingkan jika menggunakan periode pengamatan yang sama.
- Angka tersebut bergantung pada frekuensi pengambilan sampel. Harga penutupan akhir bulan menyembunyikan titik terendah intraday dan menghasilkan angka yang lebih kecil dibandingkan harga penutupan harian untuk periode yang sama.
- Angka tersebut tidak memberikan informasi ke depan. Berada 30% di bawah level puncak tidak menunjukkan apakah titik ke-31 akan tercapai besok.
Keterbatasan terakhir inilah yang membuat sistem otomatis memerlukan kebijakan drawdown, bukan sekadar ambang batas drawdown. “Hentikan pada 20%” menjawab satu pertanyaan, tetapi menyisakan dua pertanyaan lain: apa yang terjadi pada posisi terbuka saat penghentian, dan bukti apa yang diperlukan untuk mengaktifkan kembali sistem. Circuit breaker untuk trading bot membahas bentuk kebijakan tersebut. Biaya aturan datar yang arbitrer muncul pada fase pemulihan. Sistem yang berhenti di dekat titik terendah dan terlambat memulai kembali akan melewatkan kenaikan. Melewatkan hari-hari terbaik menyajikan perhitungan atas dampak tersebut.
Ada satu detail pengukuran yang penting sebelum membandingkan dua angka. Drawdown pada rangkaian harga suatu fund dan drawdown pada akun riil akan berbeda setiap kali terjadi arus kas masuk atau keluar, serta setiap kali dividen dibayarkan. Hal ini dibahas secara lengkap dalam cara mengukur return bulanan.
FAQ maximum drawdown
Berapa maximum drawdown yang baik?
Tidak ada angka universal. Yang tersedia adalah benchmark dan periode pengukuran. Dalam sepuluh tahun hingga 31 Juli 2026, penurunan terburuk SPY dari puncak berjalan, berdasarkan harga penutupan harian, tercatat sebesar 34.2%. Strategi yang mencatat angka lebih kecil dalam sampel yang lebih pendek belum tentu lebih aman.
Apakah maximum drawdown sama dengan volatilitas?
Tidak. Volatilitas menggambarkan pergerakan harian yang umum terjadi. Maximum drawdown menggambarkan jalur terburuk dari puncak ke titik terendah. Aset dengan volatilitas rendah yang terus turun selama dua tahun dapat mengalami drawdown lebih dalam daripada aset yang bergerak bergejolak tetapi terus mencetak level tertinggi baru.
Berapa lama waktu yang dibutuhkan untuk pulih dari maximum drawdown?
Lamanya bervariasi. Proses pemulihan sering kali memakan separuh waktu yang lebih panjang. Untuk SPY sejak 2016, periode terpanjang yang telah selesai di bawah level tertinggi sebelumnya berlangsung selama 181 hari kalender, sejak puncak hingga mencetak level tertinggi baru. Dari periode tersebut, 33 hari dihabiskan dalam penurunan.
Apakah maximum drawdown dapat memprediksi kerugian di masa depan?
Tidak. Maximum drawdown hanya menggambarkan satu jalur yang telah terjadi. Sampel yang lebih panjang hampir selalu menghasilkan angka yang lebih besar. Angka ini mencatat apa yang telah mampu dilewati oleh suatu strategi hingga saat ini, tanpa membatasi apa yang mungkin terjadi berikutnya.
Setiap panel di atas menyimpan SQL yang mendasarinya. Buka salah satunya, ganti ticker atau periodenya, lalu jalankan perhitungan drawdown yang sama di terminal Strasmore.