σμ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 8 · Modèles stochastiques et apprentissage automatique›Sujet 8.1·~50 minAvancé

Mouvement brownien

Position dans le parcoursModule 8 sur 11 · Sujet 1 sur 10
8.1 Mouvement brownien
—Score du lab— / 100XP total—Série—

La marche aléatoire aux pas réduits

Imaginez un prix qui monte ou descend chaque seconde d'un montant aléatoire. Raccourcissez l'intervalle de plus en plus, et réduisez chaque pas pour que la dispersion totale reste raisonnable : la limite est le mouvement brownien W(t), introduit pour décrire le pollen dans l'eau et adopté par Bachelier en 1900 pour modéliser les prix. Il est défini par trois propriétés : W(0) = 0 ; les accroissements sur des intervalles disjoints sont indépendants ; et W(t) - W(s) suit une loi normale de moyenne 0 et de variance t - s.

import numpy as np

rng = np.random.default_rng(1)
dt = 0.01
z = rng.standard_normal(5)                         # standard normal draws
increments = z * np.sqrt(dt)                       # each step over dt has standard deviation sqrt(dt)
print(np.round(increments, 4))

Une trajectoire est une somme cumulée

Pour simuler une trajectoire sur une grille de temps 0, dt, 2 dt, ..., on tire un z normal centré réduit par pas, on le met à l'échelle par sqrt(dt) et on additionne : W(k * dt) est la somme des k premiers accroissements, np.cumsum. On place un 0 devant car la trajectoire part de 0. La variance de W(t) vaut t, donc la dispersion de la position croît comme la racine carrée du temps, la même loi en racine carrée que pour le passage à l'échelle de la volatilité et de la VaR.

import numpy as np

def brownian_path(z, dt):
    return np.concatenate([[0.0], np.cumsum(z * np.sqrt(dt))])

rng = np.random.default_rng(1)
n, dt = 252, 1 / 252
ends = np.array([brownian_path(rng.standard_normal(n), dt)[-1] for _ in range(4000)])
print(round(float(ends.mean()), 3), round(float(ends.var()), 3))      # about 0 and 1: W(1) is a standard normal

Une trajectoire infiniment rugueuse

Une trajectoire brownienne est continue mais nulle part lisse, et sa longueur est infinie. Sa rugosité a une mesure précise, la variation quadratique, somme des pas au carré. Pour une courbe lisse, cette somme tend vers 0 quand la grille s'affine ; pour le mouvement brownien, elle reste égale au temps écoulé t, quelle que soit la grille, car chaque pas au carré vaut environ dt et il y en a t / dt. Ce fait, (dW)^2 = dt, distingue le calcul stochastique du calcul ordinaire et est la clé des sujets suivants.

import numpy as np

def quadratic_variation(path):
    return float(np.sum(np.diff(path) ** 2))

rng = np.random.default_rng(2)
t = 2.0
for steps in (10, 100, 10000):
    dt = t / steps
    path = np.concatenate([[0.0], np.cumsum(rng.standard_normal(steps) * np.sqrt(dt))])
    print(steps, round(quadratic_variation(path), 3))              # settles near 2.0 as the grid gets finer

smooth = np.linspace(0, 1, 10001) * 2
print(round(quadratic_variation(smooth), 5))                       # a straight line: close to 0

Dérive et volatilité

Un prix a une tendance et une échelle. Le mouvement brownien arithmétique avec dérive est X(t) = mu * t + sigma * W(t) : mu est la dérive (la tendance par unité de temps), sigma la volatilité (l'échelle de la partie aléatoire). C'est le modèle le plus simple d'une variation de prix, et il peut devenir négatif, c'est pourquoi les prix eux-mêmes sont modélisés par un mouvement brownien géométrique dans le sujet suivant. Il reste la brique de base pour les taux et les spreads.

import numpy as np

def drifted_path(z, dt, mu, sigma):
    t = np.arange(len(z) + 1) * dt
    w = np.concatenate([[0.0], np.cumsum(z * np.sqrt(dt))])
    return mu * t + sigma * w

rng = np.random.default_rng(3)
n, dt = 252, 1 / 252
path = drifted_path(rng.standard_normal(n), dt, 0.08, 0.2)             # 8% a year drift, 20% volatility
print(round(float(path[-1]), 4), "after one year; the drift alone would give 0.08")
print(np.round(drifted_path(np.zeros(4), 0.25, 0.08, 0.2), 4))         # no noise: just the trend line
Les trajectoires simulées valent ce que valent leurs tiragesDans ce lab, les tirages sont fournis, donc les résultats sont exacts et testables. Dans les vraies simulations, ils viennent d'un générateur avec graine (np.random.default_rng(seed)), ce qui rend un essai reproductible. Une seule trajectoire ne prouve rien : les statistiques comme la moyenne ou la variance de W(1) n'apparaissent que sur des milliers de trajectoires, et l'erreur d'une estimation Monte Carlo décroît comme 1 / sqrt(paths).
  • Le mouvement brownien part de 0 et a des accroissements normaux indépendants de variance dt : simuler avec z * sqrt(dt) et une somme cumulée.
  • La variance de W(t) vaut t, et la variation quadratique d'une trajectoire reste égale au temps écoulé : (dW)^2 = dt.
  • Ajoutez tendance et échelle avec X(t) = mu * t + sigma * W(t) ; une trajectoire ne prouve rien, les statistiques demandent beaucoup de trajectoires.

À suivre : le mouvement brownien géométrique, le modèle où les prix ne peuvent pas devenir négatifs.

Lab : ce qui est noté

  • Mettre les chocs à l'échelle avec brownian_increments25 pts
  • Construire la trajectoire avec brownian_path25 pts
  • Mesurer la rugosité avec quadratic_variation25 pts
  • Ajouter une tendance avec drifted_path25 pts
Explorateur · lab-102-1
▾ lab-102-1
…
bash · dans le navigateur
learner@quantcraft:~/lab-102-1$
Python pas encore chargéPythonLn 1, Col 1Spaces: 4UTF-8

Réinitialiser ce sujet ?

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