σμ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.5·~50 minAvancé

VaR paramétrique

Position dans le parcoursModule 7 sur 11 · Sujet 5 sur 9
7.5 VaR paramétrique
—Score du lab— / 100XP total—Série—

Une formule au lieu d'un historique

La VaR historique lit la perte dans les rendements passés. La VaR paramétrique suppose que les rendements suivent une loi normale et n'a besoin que de deux nombres, la moyenne et l'écart-type. La perte dépassée avec une probabilité 1 - confidence vaut alors z * sigma - mu, où z est le quantile de la loi normale centrée réduite (1,645 à 95 %, 2,326 à 99 %). Elle est rapide, lisse et s'étend facilement à tout un portefeuille, d'où son statut de standard du secteur pendant des décennies.

from statistics import NormalDist

def normal_var(mu, sigma, confidence):
    z = NormalDist().inv_cdf(confidence)
    return z * sigma - mu

print(round(NormalDist().inv_cdf(0.95), 4), round(NormalDist().inv_cdf(0.99), 4))
print(round(normal_var(0.0005, 0.012, 0.95), 5))        # a 95% one-day loss limit
print(round(normal_var(0.0005, 0.012, 0.99), 5))        # a higher confidence, a larger limit
# The multiplier z for common confidence levels
from statistics import NormalDist

for confidence in (0.90, 0.95, 0.975, 0.99, 0.999):
    print(confidence, round(NormalDist().inv_cdf(confidence), 3))       # 1.282, 1.645, 1.96, 2.326, 3.09

D'un actif à un portefeuille, et à dix jours

Pour un portefeuille, la moyenne est weights @ mu et l'écart-type sqrt(weights @ cov @ weights), les quantités du sujet sur la variance de portefeuille. La diversification apparaît directement : de faibles corrélations réduisent l'écart-type et la VaR. Pour un horizon plus long, la moyenne croît avec le nombre de jours et l'écart-type avec sa racine carrée, donc une VaR à 10 jours vaut z * sigma * sqrt(10) - mu * 10.

import numpy as np
from statistics import NormalDist

def normal_var(mu, sigma, confidence):
    return NormalDist().inv_cdf(confidence) * sigma - mu

weights = np.array([0.6, 0.4])
mu = np.array([0.0005, 0.0003])
cov = np.array([[0.00016, 0.00004], [0.00004, 0.00009]])             # volatilities 1.26% and 0.95%, correlation 0.33

mean, std = float(weights @ mu), float(np.sqrt(weights @ cov @ weights))
print(round(mean, 5), round(std, 5))
print(round(normal_var(mean, std, 0.99), 5))
print(round(normal_var(mean * 10, std * np.sqrt(10), 0.99), 5))      # the 10-day figure

Là où l'hypothèse normale échoue

Les rendements réels ont des queues épaisses : les jours extrêmes sont bien plus fréquents que ne le permet une loi normale. La VaR paramétrique paraît alors trop faible, surtout à confiance élevée. La comparer à la VaR historique sur les mêmes données montre l'écart : positif, il signifie que le modèle normal sous-estime le risque. À 95 %, les deux sont souvent proches, à 99 % elles peuvent différer beaucoup.

# Fat-tailed returns: the normal model understates the 99% loss
import numpy as np
from statistics import NormalDist

rng = np.random.default_rng(2)
returns = rng.standard_t(3, size=5000) * 0.008           # a fat-tailed distribution (3 degrees of freedom)

for confidence in (0.95, 0.99):
    historical = -np.quantile(returns, 1 - confidence)
    parametric = NormalDist().inv_cdf(confidence) * returns.std(ddof=1) - returns.mean()
    print(confidence, round(float(historical), 5), round(float(parametric), 5), round(float(historical - parametric), 5))
Choisir la méthode selon la questionLa VaR paramétrique convient pour un chiffre rapide et lisse et pour des portefeuilles de positions linéaires. C'est un mauvais guide pour les options, dont les rendements ne sont pas linéaires en fonction des facteurs de risque, et pour les queues. Beaucoup de desks calculent plusieurs VaR, paramétrique, historique et Monte Carlo, et voient dans un fort désaccord un avertissement sur le modèle.
  • VaR paramétrique = z * sigma - mu avec z = NormalDist().inv_cdf(confidence) : seuls la moyenne et l'écart-type sont nécessaires.
  • Un portefeuille utilise weights @ mu et sqrt(weights @ cov @ weights) ; un horizon multiplie la moyenne par days et la volatilité par sqrt(days).
  • Les rendements réels ont des queues épaisses : comparez à la VaR historique ; un écart positif signifie que le modèle normal sous-estime le risque.

À suivre : l'expected shortfall, la perte moyenne les jours où la VaR est dépassée.

Lab : ce qui est noté

  • Transformer deux nombres en limite avec normal_var25 pts
  • Couvrir tout un portefeuille avec portfolio_normal_var25 pts
  • Regarder plus loin avec horizon_var25 pts
  • Mesurer les queues épaisses avec normality_gap25 pts
Explorateur · lab-97-1
▾ lab-97-1
…
bash · dans le navigateur
learner@quantcraft:~/lab-97-1$
Python pas encore chargéPythonLn 1, Col 1Spaces: 4UTF-8

Réinitialiser ce sujet ?

Tout le contenu de lab-97-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