σμ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 3 · Probabilités et simulation Monte-Carlo›Sujet 3.6·~45 minIntermédiaire

La volatilité

Position dans le parcoursModule 3 sur 11 · Sujet 6 sur 12
3.6 La volatilité
—Score du lab— / 100XP total—Série—

Le risque en un seul nombre

La volatilité est l'écart type des rendements, exprimé par an pour pouvoir comparer les actifs : environ 15 à 20 % pour un indice actions, 30 à 60 % pour une action isolée, proche de 0 pour du cash. Elle sert à dimensionner les positions, à valoriser les options et à fixer les limites de risque. L'estimation la plus simple est la volatilité réalisée sur une fenêtre : l'écart type d'échantillon des rendements multiplié par sqrt(périodes par an). Elle traite tous les jours de la fenêtre de la même façon, ce qui fait à la fois sa force (stable) et sa faiblesse (lente).

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

Réagir plus vite : EWMA

La volatilité se regroupe en grappes : les périodes calmes et les périodes agitées durent un certain temps, donc le choc d'hier en dit plus sur demain qu'une journée tranquille d'il y a un mois. La moyenne mobile exponentielle (EWMA, popularisée par RiskMetrics) met à jour la variance chaque jour : variance_t = lam * variance_(t-1) + (1 - lam) * rendement_t². Avec lam = 0,94, le rendement le plus récent pèse 6 % et les anciens s'estompent géométriquement. L'estimation saute au moment d'un choc puis décroît progressivement, au lieu de rester élevée jusqu'à ce que le choc quitte la fenêtre pour retomber d'un coup.

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

Utiliser l'amplitude, et cibler une volatilité

Les cours de clôture ignorent ce qui s'est passé pendant la journée. Le plus haut et le plus bas du jour portent davantage d'information : l'estimateur de Parkinson sqrt(mean(ln(high/low)²) / (4 ln 2)) est plusieurs fois plus efficace que l'estimation clôture à clôture, c'est-à-dire qu'il atteint la même précision avec bien moins de jours (il suppose l'absence de grands écarts entre les jours). Un usage pratique de toute estimation de volatilité est le ciblage de volatilité : si vous voulez 10 % de risque et que la volatilité réalisée est de 15 %, détenez 10 / 15 = 0,67 de la position. Le levier diminue dans la tempête et augmente dans le calme.

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
La volatilité n'est pas la direction, et elle bougeLa volatilité traite de la même façon une journée à +3 % et une journée à -3 %, mais les investisseurs ne craignent que la seconde. Elle n'est pas non plus constante : toute estimation dépend de sa fenêtre ou de sa décroissance, et l'hypothèse de 252 jours de bourse est une convention. Précisez l'estimateur, la fenêtre et l'annualisation utilisés chaque fois que vous annoncez une volatilité.
  • Volatilité réalisée : écart type d'échantillon fois sqrt(périodes par an) ; stable mais lente à réagir.
  • EWMA : variance_t = lam * variance_(t-1) + (1 - lam) * rendement_t² ; les chocs récents pèsent plus et s'estompent géométriquement.
  • Parkinson utilise l'amplitude haut/bas du jour ; le ciblage de volatilité ajuste la position par cible / réalisée.

À suivre : le ratio de Sharpe, la récompense par unité de risque, et jusqu'où lui faire confiance.

Lab : ce qui est noté

  • Mesurer la volatilité annuelle avec realized_volatility25 pts
  • Donner plus de poids aux chocs récents avec ewma_volatility25 pts
  • Utiliser l'amplitude quotidienne avec parkinson_volatility25 pts
  • Dimensionner une position selon un budget de risque avec volatility_target_leverage25 pts
Explorateur · lab-59-1
▾ lab-59-1
…
bash · dans le navigateur
learner@quantcraft:~/lab-59-1$
Python pas encore chargéPythonLn 1, Col 1Spaces: 4UTF-8

Réinitialiser ce sujet ?

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