σμ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 AcademyRoteiros
Ctrl K
AO
+1,2 mil alunos
EntrarParticipar ↗
Roteiros
AO
+1,2 mil alunos
Entrar
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Roteiro de Python›Módulo 3 · Probabilidade e simulação Monte Carlo›Tópico 3.8·~40 minIntermediário

Drawdowns

Posição no roteiroMódulo 3 de 11 · Tópico 8 de 12
3.8 Drawdowns
—Nota do lab— / 100XP total—Sequência—

A perda que você realmente sente

A volatilidade trata igualmente a alta e a queda, mas o investidor vive com outro número: o quanto sua conta está abaixo do melhor valor que já teve. Esse é o drawdown. Se uma carteira subiu a 110 e agora vale 98, está 10,9% abaixo do pico, diga o que disser a volatilidade diária. O drawdown máximo é o buraco mais fundo do histórico, e o tempo submerso é quanto demorou para sair dele. Clientes saem e gestores de risco cortam limites em drawdowns, não em desvios padrão.

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]

O buraco mais fundo

cummax() dá o pico corrente em uma chamada. Dividir o preço por ele e subtrair 1 dá o drawdown de cada dia, sempre zero ou negativo. O drawdown máximo é simplesmente o mínimo dessa série, e idxmin() diz quando ocorreu. Os drawdowns são assimétricos de um jeito que importa: uma perda de 20% exige um ganho de 25% para voltar, 1 / (1 - 0,20) - 1, e uma perda de 50% exige 100%. Por isso os gestores de risco lutam para manter os drawdowns rasos.

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

O tempo submerso

A profundidade é metade da história; a duração é a outra metade. Uma estratégia pode perder só 8% e ainda passar três anos abaixo da sua antiga máxima, o que testa a paciência de qualquer investidor. Um dia está submerso enquanto seu drawdown é negativo, e uma nova máxima encerra o trecho. Para achar o trecho mais longo com pandas, marque os dias submersos com uma comparação, rotule cada sequência de valores iguais com (flag != flag.shift()).cumsum() e conte dentro de cada sequência. Um laço simples que conta e zera funciona igualmente bem e é fácil de ler.

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
Um drawdown passado não é o piorO drawdown máximo de um backtest é o pior ocorrido naquela amostra, não o pior possível: um histórico mais longo quase sempre conterá um buraco mais fundo. Trate-o como um limite inferior, compare-o com o maior drawdown do mercado no mesmo período e deixe uma margem ao dimensionar posições.
  • peak = prices.cummax() e drawdown = prices / peak - 1: zero em nova máxima, negativo abaixo dela.
  • O drawdown máximo é drawdown.min(); uma perda de x exige um ganho de 1 / (1 - x) - 1 para se recuperar.
  • O tempo submerso é a mais longa sequência de dias com drawdown negativo; o pior drawdown de um backtest é um limite inferior, não uma garantia.

A seguir: os geradores de números aleatórios e as sementes, a base de toda simulação.

Lab: o que é avaliado

  • Acompanhar a máxima atingida com running_peak25 pts
  • Medir a distância do pico com drawdown_series25 pts
  • Encontrar a pior queda com max_drawdown25 pts
  • Contar a mais longa espera por uma nova máxima com longest_underwater25 pts
Explorador · lab-61-1
▾ lab-61-1
…
bash · no navegador
learner@quantcraft:~/lab-61-1$
Python ainda não carregadoPythonLn 1, Col 1Spaces: 4UTF-8

Redefinir este tópico?

Tudo em lab-61-1 volta aos arquivos iniciais e o terminal é limpo. Sua solução atual será perdida — isso não pode ser desfeito.

Será redefinido
  • main.py → código inicial
  • Histórico do terminal e saída dos testes
  • Alterações não enviadas
Será mantido
  • Melhor nota do lab
  • Seu XP e sua sequência
  • Progresso da aula e anotações

Entre para executar o seu código.

Todas as aulas são gratuitas para ler. Crie uma conta ou entre para executar código, rodar os testes e enviar este lab.

  • IDE no navegador com terminal bash — nada para instalar
  • Correção instantânea, XP e o seu lugar no roteiro
Criar uma contaEntrar
OU
Continuar com o GitHub