σμ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 7 · Pesquisa de alfa e risco›Tópico 7.4·~50 minAvançado

VaR histórico

Posição no roteiroMódulo 7 de 11 · Tópico 4 de 9
7.4 VaR histórico
—Nota do lab— / 100XP total—Sequência—

Um limite de perda com um nível de confiança

O Value at Risk responde: quanto posso perder num dia ruim, mas não no pior? Um VaR de 1 dia a 95% de 2% diz que em 95 dias de 100 a perda não deve passar de 2%. O método histórico não precisa de modelo. Pegam-se os retornos passados, ordenam-se e lê-se a perda no percentil 5: o VaR é menos esse quantil. Reguladores e limites de risco o usam em todo lugar porque é um número único que um gestor pode comparar com um limite.

import numpy as np

rng = np.random.default_rng(3)
returns = rng.normal(0.0004, 0.012, size=500)           # two years of daily returns

var_95 = -np.quantile(returns, 0.05)                    # minus the 5th percentile
var_99 = -np.quantile(returns, 0.01)
print(round(float(var_95), 5), round(float(var_99), 5))  # 0.01928 0.027  the 99% loss limit is larger

Testar um VaR: as violações

Um VaR é uma previsão, então pode ser checado. Uma violação é um dia em que a perda excedeu o VaR, return < -VaR. Com um VaR a 95% esperam-se cerca de 5% dos dias como violações: muito mais significa que o modelo subestima o risco, muito menos que é cauteloso demais. Reguladores contam violações em 250 dias exatamente por isso. Note a desigualdade estrita: uma perda igual ao VaR não é uma violação.

import numpy as np

rng = np.random.default_rng(3)
returns = rng.normal(0.0004, 0.012, size=500)
var_95 = -np.quantile(returns, 0.05)

exceptions = int(np.sum(returns < -var_95))
print(exceptions, "exceptions in", len(returns), "days; expected about", int(0.05 * len(returns)))     # 25 25

Horizontes mais longos, e como aconteceu

Um VaR de 10 dias costuma ser exigido. Com retornos diários independentes, a volatilidade cresce com a raiz do tempo, então a regra da raiz do tempo escala: VaR_T = VaR_1 * sqrt(T). É uma aproximação, mais fraca com caudas pesadas e retornos autocorrelacionados. Backtests honestos também respeitam o tempo: o VaR usado no dia t só pode usar os retornos antes do dia t, a mesma disciplina de evitar antecipação. Um VaR móvel faz isso com uma janela dos últimos n dias.

# The square-root-of-time rule for several horizons
import math

one_day = 0.0186
for days in (1, 5, 10, 20):
    print(days, round(one_day * math.sqrt(days), 4))        # 1: 0.0186, 5: 0.0416, 10: 0.0588, 20: 0.0832
import numpy as np

def historical_var(returns, confidence):
    return float(-np.quantile(returns, 1 - confidence))

def rolling_var(returns, window, confidence):
    out = np.full(len(returns), np.nan)
    for t in range(window, len(returns)):
        out[t] = historical_var(returns[t - window:t], confidence)      # the days BEFORE day t
    return out

rng = np.random.default_rng(3)
returns = rng.normal(0.0004, 0.012, size=500)
rolling = rolling_var(returns, 250, 0.99)
print(np.isnan(rolling[:250]).all(), round(float(rolling[250]), 5), round(float(rolling[-1]), 5))
exceptions = int(np.sum(returns[250:] < -rolling[250:]))
print(exceptions, "exceptions in", len(returns) - 250, "days (about 2 expected at 99%)")
print(round(historical_var(returns, 0.99) * np.sqrt(10), 5))                 # a 10-day figure by the square-root rule
O que o VaR não dizO VaR é um limiar, não o pior caso: não diz nada sobre quão graves são as perdas além dele, e por isso os próximos tópicos tratam do expected shortfall e dos testes de estresse. O método histórico vale o que vale sua janela: dois anos calmos dão um VaR pequeno logo antes de uma crise, e o número a 99% se apoia em um punhado de observações.
  • O VaR histórico é menos o quantil (1 - confidence) dos retornos passados (np.quantile): uma fração de perda positiva sem modelo.
  • Teste contando violações (return < -VaR): cerca de 1 - confidence dos dias; mais significa um VaR baixo demais.
  • Escale para um horizonte com var * sqrt(days); uma janela móvel usa só dias anteriores; o VaR dá um limiar, não o tamanho das perdas além.

A seguir: o VaR paramétrico, calcular o mesmo limiar a partir de uma distribuição normal em vez do histórico bruto.

Lab: o que é avaliado

  • Ler a perda no histórico com historical_var25 pts
  • Contar as violações com var_exceptions25 pts
  • Esticar o horizonte com scale_var25 pts
  • Estimar como aconteceu com rolling_var25 pts
Explorador · lab-96-1
▾ lab-96-1
…
bash · no navegador
learner@quantcraft:~/lab-96-1$
Python ainda não carregadoPythonLn 1, Col 1Spaces: 4UTF-8

Redefinir este tópico?

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