σμ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 AcademyParcours
Ctrl K
AO
+1,2 k apprenants
ConnexionRejoindre ↗
Parcours
AO
+1,2 k apprenants
Connexion
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Parcours Python›Module 7 · Recherche d'alpha et risque›Sujet 7.6·~50 minAvancé

Déficit attendu

Position dans le parcoursModule 7 sur 11 · Sujet 6 sur 9
7.6 Déficit attendu
—Score du lab— / 100XP total—Série—

Ce que la VaR ne dit pas

Une VaR à 99 % de 3 % dit que, 99 jours sur 100, vous perdez moins de 3 %. Elle ne dit rien du centième jour : ce peut être 3,1 % ou 30 %. L'expected shortfall (ES, CVaR) comble ce manque. C'est la perte moyenne les jours où la VaR est dépassée, donc elle décrit la forme de la queue. Comme elle fait une moyenne, elle varie aussi de façon continue et, contrairement à la VaR, elle récompense toujours la diversification, ce qui explique le passage de Bâle de la VaR à l'ES pour le risque de marché.

import numpy as np

rng = np.random.default_rng(5)
returns = rng.standard_t(4, size=1000) * 0.01

cutoff = np.quantile(returns, 0.05)                   # the 95% VaR is minus this
tail = np.sort(returns[returns <= cutoff])            # the worst 5% of the days, lowest first
print(len(tail), round(float(-cutoff), 5))            # 50 days; the VaR
print(np.round(tail[:4], 4))                          # the four worst days

Moyenner la queue

Historiquement, l'ES est simple : on sélectionne les rendements au niveau du seuil de la VaR ou en dessous, on les moyenne et on change le signe. Le résultat n'est jamais inférieur à la VaR, car chaque rendement de la queue est au moins aussi mauvais que le seuil. Le rapport ES / VaR indique l'épaisseur de la queue. Pour une loi normale, il vaut environ 1,2 à 95 %, et les données à queues épaisses montrent en général un rapport plus grand.

import numpy as np

def tail_returns(returns, confidence):
    cutoff = np.quantile(returns, 1 - confidence)
    return np.sort(returns[returns <= cutoff])

def historical_es(returns, confidence):
    return float(-tail_returns(returns, confidence).mean())

rng = np.random.default_rng(5)
returns = rng.standard_t(4, size=1000) * 0.01
for confidence in (0.95, 0.99):
    var = -np.quantile(returns, 1 - confidence)
    es = historical_es(returns, confidence)
    print(confidence, round(float(var), 5), round(es, 5), round(es / float(var), 3))

Une formule pour le cas normal

Pour un rendement normal, la moyenne de la queue a une forme explicite : ES = sigma * pdf(z) / (1 - confidence) - mu, où z est le quantile utilisé pour la VaR et pdf la densité normale centrée réduite en z. Le calcul tient en deux lignes et n'est exact que si les données sont normales ; le comparer à l'ES historique est donc un test rapide de l'écart à la normalité.

from statistics import NormalDist

def normal_es(mu, sigma, confidence):
    z = NormalDist().inv_cdf(confidence)
    return sigma * NormalDist().pdf(z) / (1 - confidence) - mu

for confidence in (0.95, 0.975, 0.99):
    var = NormalDist().inv_cdf(confidence)                        # in standard deviations, mu = 0
    es = normal_es(0.0, 1.0, confidence)
    print(confidence, round(var, 3), round(es, 3), round(es / var, 3))       # ES/VaR: 1.254, 1.193, 1.146
# The formula against a simulated tail
import numpy as np
from statistics import NormalDist

rng = np.random.default_rng(0)
sample = rng.normal(0.0, 0.01, size=1_000_000)
tail = sample[sample <= np.quantile(sample, 0.01)]
simulated = -tail.mean()
z = NormalDist().inv_cdf(0.99)
formula = 0.01 * NormalDist().pdf(z) / 0.01
print(round(float(simulated), 5), round(formula, 5))         # both close to 0.02665
L'ES est aussi plus difficile à testerLa VaR se vérifie en comptant les dépassements. L'ES repose sur les quelques observations de la queue : à 99 % sur 250 jours, deux ou trois rendements. Son estimation est plus bruitée et exige plus de données ou un modèle. En pratique, on rapporte les deux ensemble : la VaR comme seuil, l'ES comme gravité au-delà.
  • L'ES est la perte moyenne dans la queue au-delà de la VaR : l'opposé de la moyenne des rendements au niveau du quantile (1 - confidence) ou en dessous.
  • Elle n'est jamais inférieure à la VaR ; ES / VaR mesure l'épaisseur de la queue, et la formule normale est sigma * pdf(z) / (1 - confidence) - mu.
  • Rapportez la VaR comme seuil et l'ES comme gravité ; l'ES est plus bruitée car elle repose sur peu d'observations de queue.

À suivre : les tests de résistance, demander ce qu'un portefeuille perdrait dans un scénario précis et extrême.

Lab : ce qui est noté

  • Isoler les pires jours avec tail_returns25 pts
  • Moyenner la queue avec historical_es25 pts
  • L'obtenir par une formule avec normal_es25 pts
  • Comparer queue et seuil avec es_var_ratio25 pts
Explorateur · lab-98-1
▾ lab-98-1
…
bash · dans le navigateur
learner@quantcraft:~/lab-98-1$
Python pas encore chargéPythonLn 1, Col 1Spaces: 4UTF-8

Réinitialiser ce sujet ?

Tout le contenu de lab-98-1 revient aux fichiers de départ et le terminal est vidé. Votre solution actuelle sera perdue : cette action est irréversible.

Sera réinitialisé
  • main.py → code de départ
  • Historique du terminal et sortie des tests
  • Modifications non soumises
Sera conservé
  • Meilleur score du lab
  • Votre XP et votre série
  • Progression du cours et notes

Connectez-vous pour exécuter votre code.

Tous les cours sont gratuits à lire. Créez un compte ou connectez-vous pour exécuter du code, lancer les tests et soumettre ce lab.

  • IDE dans le navigateur avec terminal bash — rien à installer
  • Correction instantanée, XP et votre place dans le parcours
Créer un compteSe connecter
OU
Continuer avec GitHub