Strasmore Research
تعلیمی مواد Matt Connorاز Matt Connor · اپ ڈیٹ شدہ 2026-08-05

Maximum Drawdown کیا ہے؟ گہرائی اور Recovery

Maximum drawdown value series میں peak سے trough تک سب سے بڑی گراوٹ ہے۔ جانیں deep drawdown کیا ہوتا ہے اور نئی بلند سطح تک Recovery میں زیادہ وقت کیوں لگتا ہے۔

Maximum drawdown کسی value series میں peak سے trough تک ہونے والی سب سے بڑی گراوٹ ہوتی ہے، جسے running peak کے فیصد کے طور پر ناپا جاتا ہے۔ اگر کوئی account $120,000 تک بڑھنے کے بعد $84,000 تک گر جائے اور پھر بحال ہو جائے، تو اس کا maximum drawdown 30% ہوگا۔ یہ عدد ہمیشہ برقرار رہتا ہے، کیونکہ یہ آج کی حالت کے بجائے پوری تاریخ کے دوران آنے والے بدترین دور کو ریکارڈ کرتا ہے۔ زیادہ تر لوگ صرف گراوٹ کی گہرائی بیان کرتے ہیں۔ لیکن اسی statistic میں دو مزید اعداد بھی شامل ہوتے ہیں: peak سے low تک پہنچنے میں لگا وقت، اور low سے دوبارہ نئی بلند ترین سطح تک پہنچنے میں لگنے والا کہیں زیادہ طویل وقت۔

زیادہ سے زیادہ drawdown کیسے calculate کیا جاتا ہے؟

یہ calculation پوری series پر ایک ہی pass میں مکمل ہو جاتی ہے۔ ہر observation پر running maximum کو update کیا جاتا ہے، موجودہ value کا اس maximum سے موازنہ کیا جاتا ہے، اور اب تک کی سب سے خراب reading محفوظ رکھی جاتی ہے۔

  1. Running peak کو پہلی value کے برابر set کریں۔
  2. ہر نئی value پر، اگر وہ زیادہ ہو تو peak کو update کریں۔
  3. اس مقام کا drawdown calculate کریں: value کو peak سے تقسیم کریں، پھر ایک منفی کریں۔
  4. سب سے زیادہ منفی reading محفوظ رکھیں۔ یہی maximum drawdown ہے۔

اس calculation میں returns series، volatility estimate یا distribution assumption شامل نہیں ہوتا۔ یہ loop Python standard library کے ساتھ numbers کی ایک سادہ list پر چلتا ہے۔ نئے Ubuntu box پر پہلے interpreter install کریں:

apt-get update && apt-get install -y python3

اس loop کو maxdd.py کے طور پر save کریں۔ نیچے دی گئی prices دس points پر مشتمل ایک فرضی series ہیں۔ انہیں اتنا مختصر رکھا گیا ہے کہ ہاتھ سے check کیا جا سکے:

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 چلائیں۔ اس کا output maximum drawdown: -15.4% ہوگا۔ ہاتھ سے check کریں: low سے پہلے peak 104 تھا، low 88 تھا، اور 88 کو 104 سے تقسیم کرنے پر نتیجہ 0.846 آتا ہے۔ اس کے بعد series 106 پر ختم ہوتی ہے، جو all time high ہے، لیکن 15.4% کا drawdown برقرار رہتا ہے۔ Maximum drawdown sample کے بدترین لمحے کا مستقل record ہے، اور یہ نہیں بتاتا کہ series آج کہاں کھڑی ہے۔ اسی loop میں مزید دو variables شامل کر کے timing بھی capture کی جا سکتی ہے: وہ index جہاں peak set ہوا، اور وہ index جہاں worst reading سامنے آئی۔

Drawdown curve کی شکل

Drawdown curve ہر نقطے پر step 3 کو برقرار رکھتی ہے، بجائے اس کے کہ اسے صرف بدترین ایک قدر تک محدود کر دے۔ جب series نئی بلند ترین سطح بناتی ہے تو line صفر پر رہتی ہے، اور اس کے درمیان صفر سے نیچے چلی جاتی ہے۔ اسی لیے اس فرق کو “underwater” کہا جاتا ہے۔ ذیل میں SPY کی یہی curve دکھائی گئی ہے۔ SPY ایک exchange traded fund ہے جو S&P 500 کو track کرتا ہے۔ ڈیٹا جنوری 2016 سے month-end closes پر مبنی ہے۔

استفسار کریںSPY underwater curve: ماہ کے اختتامی close بمقابلہ running peak، 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 month-end readings کے دوران line طویل عرصے تک صفر کے قریب رہتی ہے اور چند گہری گراوٹوں میں نیچے جاتی ہے۔ ریکارڈ میں موجود آخری month کی قدر running peak کے مقابلے میں -1.27% ہے۔ اس شکل کی دو خصوصیات بنیادی سبق فراہم کرتی ہیں۔ Recovery تیز bounce کے بجائے آہستہ چڑھاؤ کی صورت میں آتی ہے۔ ہر نئی peak curve کو دوبارہ صفر پر لے آتی ہے اور اس سے پہلے کی گراوٹ کا بصری نشان مٹ جاتا ہے۔

Drawdown سے بحالی میں کتنا وقت لگتا ہے؟

ایک ہی drawdown میں تین الگ اعداد شامل ہوتے ہیں، اور انہیں ایک ہی چیز سمجھنا performance table کی سب سے عام غلط تشریح ہے:

  1. گہرائی: peak سے value کتنے فیصد نیچے گری۔
  2. کم ترین سطح تک وقت: peak سے bottom تک calendar days۔
  3. Recovery time: bottom سے نئی بلند ترین سطح تک calendar days۔

عموماً تیسرا دورانیہ سب سے طویل ہوتا ہے، اور headline number اسے کبھی ظاہر نہیں کرتا۔ ذیل کا panel روزانہ closing prices کی بنیاد پر 2016 سے SPY کے ہر مکمل underwater stretch کو دوبارہ مرتب کرتا ہے۔ کوئی stretch اس دن شروع ہوتا ہے جب peak بنتی ہے، اور اس دن ختم ہوتا ہے جب fund پہلی بار اس peak سے اوپر close کرتا ہے۔

استفسار کریں2016 کے بعد مکمل SPY drawdowns: گہرائی، گرنے کے دن، بحالی کے دن
ہر عدد کے پیچھے موجود درست 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

فہرست میں سب سے گہرا مکمل stretch Feb 2020 میں شروع ہوتا ہے اور سابقہ peak سے 34.2% نیچے تک پہنچتا ہے۔ اس میں کمی کا سلسلہ 33 calendar days تک جاری رہا، جبکہ بحالی میں 148 دن لگے؛ یوں fund مجموعی طور پر 181 دن underwater رہا۔ اگلی entry، جو Jan 2022 کی ہے، 25.4% پر نسبتاً کم گہری تھی، اور اس نے fund کو سابقہ high سے 746 دن تک نیچے رکھا۔

گہرائی اور دورانیہ مکمل طور پر الگ چیزیں ہیں۔ ایک شدید کمی جس کے بعد تیزی سے واپسی ہو، اور ایک معمولی کمی جو برسوں تک جاری رہے، دونوں ایک ہی percentage میں سمٹ جاتے ہیں۔ مارچ 2020 کا crash پہلی صورت کی textbook مثال ہے، جبکہ markets crashes سے کیسے recover کرتے ہیں اس سفر کے دوسرے مرحلے کی وضاحت کرتا ہے۔

زیادہ طویل مدت میں maximum drawdown کیوں بدتر دکھائی دیتا ہے

Maximum drawdown ایک maximum ہوتا ہے، اس لیے تاریخی مدت بڑھانے سے یہ یا تو برقرار رہتا ہے یا مزید گہرا ہو جاتا ہے۔ طویل window میں running peak ہر مقام پر مختصر window کے peak کے برابر یا اس سے زیادہ ہوتا ہے، اور یہی حسابی نتیجہ طے کرتا ہے۔

استفسار کریںایک ہی fund، پانچ lookback windows: sample length کے لحاظ سے SPY 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
Run this yourself

ایک ہی fund کو دیکھتا ہے۔ پانچوں windows کا اختتام 31 جولائی 2026 پر ہوتا ہے، جس سے یہ اثر واضح ہوتا ہے۔

گزشتہ 1 year window میں ناپی گئی بدترین گراوٹ 9.1% تھی۔ اسی series کو 10 years تک بڑھانے پر reading 34.2% ہو گئی، جبکہ بدترین مقام Mar 2020 میں آیا۔ Fund زیادہ risky نہیں ہوا۔ صرف sample طویل ہوا۔

یہی حسابی عمل strategy comparisons کو بھی مسخ کرتا ہے۔ تین سالہ backtest اور بیس سالہ backtest ایک جیسا behavior بیان کر سکتے ہیں، پھر بھی ان میں drawdowns بہت مختلف رپورٹ ہو سکتے ہیں۔ اس لیے window کے ذکر کے بغیر یہ figure زیادہ معنی نہیں رکھتا۔ backtesting میں look-ahead bias میں ایک اور طریقہ بیان کیا گیا ہے جس سے بظاہر صاف backtest اپنے نتائج کو غیر حقیقی طور پر بہتر دکھاتا ہے۔

زیادہ سے زیادہ drawdown بمقابلہ volatility

Volatility روزانہ قیمت میں دونوں سمتوں میں ہونے والی معمول کی تبدیلی کا حجم ناپتی ہے۔ Maximum drawdown قیمت کے ایک مخصوص مسلسل منفی سفر کی پیمائش کرتا ہے۔ دونوں risk کے اعداد ہیں، لیکن دونوں مختلف سوالات کا جواب دیتے ہیں۔ یہ panel 31 جولائی 2026 تک کے پانچ برسوں کے دوران آٹھ معروف کمپنیوں کے لیے دونوں اعداد کو ساتھ رکھتا ہے۔ Volatility کا annualization روزانہ کے closing prices کی بنیاد پر کیا گیا ہے۔

استفسار کریںMaximum drawdown بمقابلہ annualized volatility: آٹھ large caps، 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

دونوں columns کو ساتھ پڑھیں۔ VZ نے اس گروپ میں 45.4% کے ساتھ سب سے گہری گراوٹ دکھائی، جبکہ اس کی annualized volatility 22.6% رہی۔ نسبتاً کم گراوٹ والے سرے پر KO میں 20.9% کی کمی ہوئی اور volatility 16.7% رہی۔ Volatility اس مدت کے ہر دن کا اوسط ہے، اور اوسط طویل مگر بتدریج کمی کے اثر کو کم کر دیتی ہے۔ Drawdown وہ واحد بدترین راستہ ہے جس پر قیمت حقیقی طور پر چلی۔ کوئی پُرسکون holding دو برس تک بتدریج نیچے آ سکتی ہے اور اس کے باوجود غیر نمایاں volatility کے ساتھ گہرا drawdown دکھا سکتی ہے۔

کم volatility کا anomaly طویل مدت میں پُرسکون ناموں کے رویے کا جائزہ لیتا ہے، جبکہ Kelly criterion کے مطابق position sizing دکھاتا ہے کہ drawdown برداشت کرنے کی حد کس طرح position size میں تبدیل ہوتی ہے۔

وہ بات جو یہ عدد نہیں بتا سکتا

چار حدود ذہن میں رکھنا ضروری ہیں:

  1. یہ ایک realised path ہے۔ کسی دوسرے مشاہدے میں یہی process کہیں زیادہ خراب figure پیدا کر سکتا تھا۔
  2. اس کا انحصار sample length پر ہوتا ہے، اس لیے دو drawdowns کا موازنہ صرف یکساں windows میں کیا جا سکتا ہے۔
  3. اس کا انحصار sampling frequency پر بھی ہوتا ہے۔ Month-end closes، intraday lows کو چھپا دیتے ہیں اور اسی مدت کے daily closes کے مقابلے میں کم عدد دکھاتے ہیں۔
  4. یہ مستقبل کے بارے میں کوئی information نہیں دیتا۔ Peak سے 30% نیچے ہونا یہ نہیں بتاتا کہ 31st point کل پہنچے گا یا نہیں۔

یہ آخری حد اس وجہ سے اہم ہے کہ automated system کو drawdown threshold کے بجائے drawdown policy درکار ہوتی ہے۔ “20% پر halt” ایک سوال کا جواب دیتا ہے، مگر دو سوالات کا جواب نہیں دیتا: halt کے وقت open positions کے ساتھ کیا ہوگا، اور system کو دوبارہ فعال کرنے کے لیے کون سا evidence درکار ہوگا۔ Trading bots کے لیے circuit breakers اسی policy کی ساخت کو واضح کرتا ہے۔ من مانی flat rule کی لاگت recovery leg میں سامنے آتی ہے، جہاں system اگر low کے قریب رک جائے اور دیر سے restart ہو تو چڑھتی ہوئی مارکیٹ سے باہر رہ جاتا ہے۔ بہترین دنوں سے محرومی اس حساب کو اعداد میں بیان کرتا ہے۔

دو figures کا موازنہ کرنے سے پہلے measurement کی ایک تفصیل اہم ہے: fund کی price series پر drawdown اور حقیقی account پر drawdown اس وقت مختلف ہوتے ہیں جب cash اندر یا باہر منتقل ہو، یا dividends موصول ہوں۔ ماہانہ returns کیسے ناپے جاتے ہیں اس موضوع کو مکمل طور پر بیان کرتا ہے۔

Maximum drawdown سے متعلق عام سوالات

اچھا maximum drawdown کیا ہوتا ہے؟

اس کے لیے کوئی عالمگیر عدد موجود نہیں۔ اس کا انحصار benchmark اور پیمائش کے دورانیے پر ہوتا ہے۔ 31 جولائی 2026 تک کے دس برسوں میں SPY کی running peak سے سب سے بڑی گراوٹ روزانہ کے closing prices کی بنیاد پر 34.2% رہی۔ اگر کوئی strategy مختصر مدت کے sample میں اس سے کم عدد دکھائے تو ضروری نہیں کہ وہ زیادہ محفوظ ہو۔

کیا maximum drawdown اور volatility ایک ہی چیز ہیں؟

نہیں۔ Volatility روزانہ کی معمول کی price move کو بیان کرتی ہے، جبکہ maximum drawdown peak سے trough تک کا بدترین واحد راستہ ظاہر کرتا ہے۔ کم volatility والی کوئی holding اگر دو برس تک مسلسل گرتی رہے تو اس کا drawdown ایسی تیزی سے حرکت کرنے والی holding سے زیادہ گہرا ہو سکتا ہے جو مسلسل نئی بلند ترین سطحیں بناتی رہے۔

maximum drawdown سے بحالی میں کتنا وقت لگتا ہے؟

یہ مختلف ہوتا ہے، اور واپسی کا سفر اکثر اس عمل کا زیادہ طویل حصہ ہوتا ہے۔ 2016 سے SPY کے لیے، کسی سابقہ high سے نیچے رہنے والا سب سے گہرا مکمل دور peak سے نئی high تک 181 calendar days پر محیط تھا، جن میں 33 دن گراوٹ میں گزرے۔

کیا maximum drawdown مستقبل کے نقصانات کی پیش گوئی کرتا ہے؟

نہیں۔ یہ صرف اس راستے کو بیان کرتا ہے جو پہلے ہی طے ہو چکا ہے، اور طویل sample تقریباً ہمیشہ زیادہ بڑا عدد پیدا کرتا ہے۔ یہ بتاتا ہے کہ strategy نے اب تک کیا کچھ برداشت کیا ہے؛ آئندہ نقصان کی کوئی حد اس سے معلوم نہیں ہوتی۔


اوپر موجود ہر panel اپنے پیچھے موجود SQL محفوظ رکھتا ہے۔ کسی panel کو کھولیں، ticker یا window تبدیل کریں، اور Strasmore terminal پر یہی drawdown arithmetic دوبارہ چلائیں۔

#risk#drawdown#backtesting#performance metrics#python