σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
uantCraft Academyالمسارات
Ctrl K
AO
+1.2k متعلّم
تسجيل الدخولانضم ↗
المسارات
AO
+1.2k متعلّم
تسجيل الدخول
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
مسار Python›الوحدة 3 · الاحتمالات ومحاكاة مونت كارلو›الموضوع 3.8·~40 دمتوسط

التراجعات (Drawdowns)

الموضع في المسارالوحدة 3 من 11 · الموضوع 8 من 12
3.8 التراجعات (Drawdowns)
—درجة المختبر— / 100إجمالي XP—التتابع—

الخسارة التي تشعر بها فعلًا

يعامل التقلب الصعود والهبوط بالتساوي، لكن المستثمر يعيش برقم آخر: كم يقع حسابه تحت أفضل قيمة بلغها. هذا هو التراجع (drawdown). فإذا ارتفعت محفظة إلى 110 وتقف الآن عند 98 فهي أدنى من قمتها بـ 10.9% أيًّا كان ما يقوله التقلب اليومي. وأقصى تراجع هو أعمق حفرة في التاريخ، والزمن تحت الماء هو المدة التي استغرقها الخروج منها. يغادر العملاء ويخفّض مديرو المخاطر الحدود عند التراجعات لا عند الانحرافات المعيارية.

import pandas as pd

prices = pd.Series(
    [100, 105, 103, 98, 104, 110, 108, 107, 111, 95], dtype=float,
    index=pd.bdate_range("2026-03-02", periods=10),
)

peak = prices.cummax()                 # the highest price so far, day by day
drawdown = prices / peak - 1           # 0 on a new high, negative below it

print(peak.tolist())                   # [100.0, 105.0, 105.0, 105.0, 105.0, 110.0, 110.0, 110.0, 111.0, 111.0]
print(drawdown.round(4).tolist())      # [0.0, 0.0, -0.019, -0.0667, -0.0095, 0.0, -0.0182, -0.0273, 0.0, -0.1441]

أعمق حفرة

تعطي cummax() القمة الجارية باستدعاء واحد. وقسمة السعر عليها وطرح 1 يعطيان التراجع في كل يوم، صفرًا أو سالبًا دائمًا. وأقصى تراجع هو ببساطة أدنى قيمة في تلك السلسلة، ويخبرك idxmin() متى حدث. والتراجعات غير متماثلة بشكل مهم: خسارة 20% تحتاج ربح 25% للتعويض 1 / (1 - 0.20) - 1، وخسارة 50% تحتاج 100%. ولهذا يحارب مديرو المخاطر لإبقاء التراجعات ضحلة.

print(round(drawdown.min(), 4), drawdown.idxmin().date())   # -0.1441 2026-03-13   111 down to 95

# The climb back is steeper than the fall
for loss in (0.10, 0.20, 0.50):
    print(loss, round(1 / (1 - loss) - 1, 3))
# 0.1 0.111
# 0.2 0.25
# 0.5 1.0

الزمن تحت الماء

العمق نصف القصة والمدة نصفها الآخر. قد تخسر استراتيجية 8% فقط وتمضي ثلاث سنوات تحت قمتها القديمة، وهذا يختبر صبر أي مستثمر. يكون اليوم تحت الماء ما دام تراجعه سالبًا، وتنهي القمة الجديدة الفترة. ولإيجاد أطول فترة بـ pandas علّم أيام تحت الماء بمقارنة، ثم رقّم كل سلسلة من القيم المتساوية بـ (flag != flag.shift()).cumsum()، ثم عُدّ داخل كل سلسلة. وحلقة بسيطة تعدّ وتعيد التصفير تؤدي الغرض نفسه وتُقرأ بسهولة.

underwater = drawdown < 0                                     # True while below the running peak
run_id = (underwater != underwater.shift()).cumsum()           # a new id each time the flag changes
streak = underwater.astype(int).groupby(run_id).cumsum()       # 1, 2, 3, ... inside each underwater run

print(streak.tolist())                    # [0, 0, 1, 2, 3, 0, 1, 2, 0, 1]
print(int(streak.max()))                  # 3   the longest wait for a new high, in days
# Return divided by the depth of the worst hole: the Calmar ratio
annual_return = 0.12
print(round(annual_return / abs(drawdown.min()), 2))     # 0.83
التراجع السابق ليس الأسوأأقصى تراجع في اختبار رجعي هو الأسوأ الذي حدث في تلك العيّنة لا الأسوأ الممكن: فالتاريخ الأطول يحوي غالبًا حفرة أعمق. تعامل معه كحد أدنى، وقارنه بأكبر تراجع للسوق في الفترة نفسها، واترك هامشًا عند تحديد أحجام المراكز.
  • peak = prices.cummax() وdrawdown = prices / peak - 1: صفر عند قمة جديدة وسالب تحتها.
  • أقصى تراجع هو drawdown.min()؛ وخسارة x تحتاج ربحًا 1 / (1 - x) - 1 للتعويض.
  • الزمن تحت الماء هو أطول سلسلة أيام بتراجع سالب؛ وأسوأ تراجع في اختبار رجعي حد أدنى لا ضمان.

التالي: مولّدات الأعداد العشوائية والبذور، أساس كل محاكاة.

المختبر: ما الذي يُقيَّم

  • تتبّع أعلى سعر بلغته حتى الآن باستخدام running_peak25 نقطة
  • قِس البعد عن القمة باستخدام drawdown_series25 نقطة
  • اعثر على أسوأ هبوط باستخدام max_drawdown25 نقطة
  • عُدّ أطول انتظار لقمة جديدة باستخدام longest_underwater25 نقطة
المستكشف · lab-61-1
▾ lab-61-1
…
bash · داخل المتصفح
learner@quantcraft:~/lab-61-1$
لم يتم تحميل Python بعدPythonLn 1, Col 1Spaces: 4UTF-8

هل تريد إعادة ضبط هذا الموضوع؟

سيعود كل ما في lab-61-1 إلى الملفات الابتدائية وستُمسح الطرفية. ستفقد حلّك الحالي ولا يمكن التراجع عن ذلك.

سيُعاد ضبطه
  • main.py ← الشيفرة الابتدائية
  • سجل الطرفية ومخرجات الاختبارات
  • التغييرات غير المُرسلة
سيُحتفظ به
  • أفضل درجة في المختبر
  • نقاط XP والتتابع
  • تقدّم المحاضرة والملاحظات

سجّل الدخول لتشغيل الكود الخاص بك.

قراءة كل المحاضرات مجانية. أنشئ حسابًا أو سجّل الدخول لتشغيل الكود وتنفيذ الاختبارات وتسليم هذا المختبر.

  • بيئة تطوير داخل المتصفح مع طرفية bash — لا حاجة لتثبيت أي شيء
  • تصحيح فوري ونقاط خبرة ومكانك في المسار
إنشاء حسابتسجيل الدخول
أو
المتابعة عبر GitHub