σμ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.6·~45 minIntermediário

Volatilidade

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

O risco em um só número

A volatilidade é o desvio padrão dos retornos, expresso por ano para comparar ativos: cerca de 15 a 20% para um índice de ações, 30 a 60% para uma ação individual, perto de 0 para caixa. Ela dimensiona posições, precifica opções e define limites de risco. A estimativa mais simples é a volatilidade realizada numa janela: o desvio padrão amostral dos retornos vezes sqrt(períodos por ano). Trata todos os dias da janela igualmente, o que é ao mesmo tempo sua força (estável) e sua fraqueza (lenta).

import math
import numpy as np

# Eight quiet days, one -3% shock, three more days
returns = np.array([0.004, -0.002, 0.001, 0.003, -0.004, 0.002, 0.006, -0.001, -0.030, 0.004, 0.002, -0.003])

print(round(returns[:8].std(ddof=1) * math.sqrt(252), 4))    # 0.0526   before the shock: 5.3% a year
print(round(returns.std(ddof=1) * math.sqrt(252), 4))        # 0.1505   with the shock: 15.1% a year

Reagir mais rápido: EWMA

A volatilidade se agrupa: períodos calmos e períodos agitados duram um tempo, então o choque de ontem diz mais sobre amanhã do que um dia tranquilo de um mês atrás. A média móvel exponencial (EWMA, popularizada pelo RiskMetrics) atualiza a variância a cada dia: variância_t = lam * variância_(t-1) + (1 - lam) * retorno_t². Com lam = 0,94 o retorno mais recente pesa 6% e os antigos se apagam geometricamente. A estimativa salta no choque e decai aos poucos, em vez de ficar alta até o choque sair da janela e cair de uma vez.

lam = 0.94
variance = np.empty(len(returns))
variance[0] = returns[0] ** 2
for t in range(1, len(returns)):
    variance[t] = lam * variance[t - 1] + (1 - lam) * returns[t] ** 2    # the recursion needs the previous value

ewma = np.sqrt(variance)
print(ewma.round(5).tolist())
# [0.004, 0.00391, 0.0038, 0.00375, 0.00377, 0.00369, 0.00387, 0.00376, 0.0082, 0.00801, 0.00778, 0.00758]
#                                                                       ^ the shock doubles the estimate, then it fades
print(round(ewma[-1] * math.sqrt(252), 4))     # 0.1204   today's annualised estimate

Usar a amplitude e mirar uma volatilidade

Os preços de fechamento ignoram o que aconteceu durante o dia. A máxima e a mínima do dia carregam mais informação: o estimador de Parkinson sqrt(mean(ln(high/low)²) / (4 ln 2)) é várias vezes mais eficiente que a estimativa de fechamento a fechamento, ou seja, alcança a mesma precisão com muito menos dias (supõe que não há grandes saltos entre os dias). Um uso prático de qualquer estimativa de volatilidade é a meta de volatilidade: se você quer 10% de risco e a volatilidade realizada é 15%, mantenha 10 / 15 = 0,67 da posição. A alavancagem encolhe na tempestade e cresce na calma.

high = np.array([101.5, 102.0, 103.2, 102.8, 104.0])
low = np.array([99.8, 100.9, 101.7, 101.1, 102.4])
parkinson = math.sqrt(np.mean(np.log(high / low) ** 2) / (4 * math.log(2)))
print(round(parkinson, 5))                      # 0.00905   per-day volatility from the daily ranges

target = 0.10
realized = returns.std(ddof=1) * math.sqrt(252)
print(round(target / realized, 3))              # 0.664   hold two thirds of the position to run at 10% risk
# Close-to-close versus range: the same five days
close = np.array([100.0, 101.2, 102.5, 101.9, 103.4])
print(round(float(np.diff(np.log(close)).std(ddof=1)), 5))     # 0.00955   from the closes only
print(round(parkinson, 5))                                      # 0.00905   from the high-low ranges of the same days
Volatilidade não é direção, e ela se moveA volatilidade trata igualmente um dia de +3% e um de -3%, mas os investidores só temem o segundo. Também não é constante: toda estimativa depende de sua janela ou decaimento, e os 252 dias úteis são uma convenção. Diga qual estimador, janela e anualização usou sempre que citar uma volatilidade.
  • Volatilidade realizada: desvio padrão amostral vezes sqrt(períodos por ano); estável, mas lenta para reagir.
  • EWMA: variância_t = lam * variância_(t-1) + (1 - lam) * retorno_t²; choques recentes pesam mais e se apagam geometricamente.
  • Parkinson usa a amplitude máxima/mínima diária; a meta de volatilidade escala a posição por meta / realizada.

A seguir: o índice de Sharpe, a recompensa por unidade de risco, e até onde confiar nele.

Lab: o que é avaliado

  • Medir a volatilidade anual com realized_volatility25 pts
  • Dar mais peso aos choques recentes com ewma_volatility25 pts
  • Usar a amplitude diária com parkinson_volatility25 pts
  • Dimensionar uma posição a um orçamento de risco com volatility_target_leverage25 pts
Explorador · lab-59-1
▾ lab-59-1
…
bash · no navegador
learner@quantcraft:~/lab-59-1$
Python ainda não carregadoPythonLn 1, Col 1Spaces: 4UTF-8

Redefinir este tópico?

Tudo em lab-59-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