σμ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 AcademyRutas
Ctrl K
AO
+1,2 k estudiantes
Iniciar sesiónUnirse ↗
Rutas
AO
+1,2 k estudiantes
Iniciar sesión
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Ruta de Python›Módulo 8 · Modelos estocásticos y aprendizaje automático›Tema 8.1·~50 minAvanzado

Movimiento browniano

Posición en la rutaMódulo 8 de 11 · Tema 1 de 10
8.1 Movimiento browniano
—Puntuación del lab— / 100XP total—Racha—

El paseo aleatorio con pasos reducidos

Imagina un precio que sube o baja cada segundo en una cantidad aleatoria. Acorta el intervalo más y más, y reduce cada paso para que la dispersión total siga siendo razonable: el límite es el movimiento browniano W(t), introducido para describir el polen en agua y adoptado por Bachelier en 1900 para modelar precios. Se define por tres propiedades: W(0) = 0; los incrementos en intervalos disjuntos son independientes; y W(t) - W(s) es normal con media 0 y varianza 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))

Una trayectoria es una suma acumulada

Para simular una trayectoria en una malla de tiempos 0, dt, 2 dt, ..., se saca un z normal estándar por paso, se escala por sqrt(dt) y se suma: W(k * dt) es la suma de los primeros k incrementos, np.cumsum. Se pone un 0 delante porque la trayectoria parte de 0. La varianza de W(t) es t, así que la dispersión de la posición crece como la raíz cuadrada del tiempo, la misma ley de raíz cuadrada que en el escalado de volatilidad y 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

Una trayectoria infinitamente rugosa

Una trayectoria browniana es continua pero en ninguna parte suave, y su longitud es infinita. Su rugosidad tiene una medida precisa, la variación cuadrática, la suma de los pasos al cuadrado. Para una curva suave esa suma tiende a 0 al afinar la malla; para el movimiento browniano se mantiene en el tiempo transcurrido t, sea cual sea la malla, porque cada paso al cuadrado vale unos dt y hay t / dt de ellos. Este hecho, (dW)^2 = dt, distingue el cálculo estocástico del ordinario y es la clave de los siguientes temas.

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

Deriva y volatilidad

Un precio tiene una tendencia y una escala. El movimiento browniano aritmético con deriva es X(t) = mu * t + sigma * W(t): mu es la deriva (la tendencia por unidad de tiempo), sigma la volatilidad (la escala de la parte aleatoria). Es el modelo más simple de un cambio de precio, y puede volverse negativo, por lo que los precios mismos se modelan como movimiento browniano geométrico en el siguiente tema. Sigue siendo la pieza básica para tipos y diferenciales.

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
Las trayectorias simuladas valen lo que valgan sus sorteosEn este lab los sorteos vienen dados, así que los resultados son exactos y comprobables. En simulaciones reales vienen de un generador con semilla (np.random.default_rng(seed)), lo que hace reproducible una ejecución. Una sola trayectoria no prueba nada: estadísticos como la media o la varianza de W(1) solo aparecen con miles de trayectorias, y el error de una estimación Monte Carlo decrece como 1 / sqrt(paths).
  • El movimiento browniano parte de 0 y tiene incrementos normales independientes de varianza dt: simular con z * sqrt(dt) y una suma acumulada.
  • La varianza de W(t) es t, y la variación cuadrática de una trayectoria se mantiene en el tiempo transcurrido: (dW)^2 = dt.
  • Añada tendencia y escala con X(t) = mu * t + sigma * W(t); una trayectoria no prueba nada, las estadísticas necesitan muchas.

A continuación: el movimiento browniano geométrico, el modelo en el que los precios no pueden ser negativos.

Lab: qué se califica

  • Escalar los shocks con brownian_increments25 pts
  • Construir la trayectoria con brownian_path25 pts
  • Medir la rugosidad con quadratic_variation25 pts
  • Añadir una tendencia con drifted_path25 pts
Explorador · lab-102-1
▾ lab-102-1
…
bash · en el navegador
learner@quantcraft:~/lab-102-1$
Python aún no cargadoPythonLn 1, Col 1Spaces: 4UTF-8

¿Restablecer este tema?

Todo lo que hay en lab-102-1 vuelve a los archivos iniciales y se limpia el terminal. Tu solución actual se perderá: no se puede deshacer.

Se restablecerá
  • main.py → código inicial
  • Historial del terminal y salida de pruebas
  • Cambios sin enviar
Se conservará
  • Mejor puntuación del lab
  • Tu XP y tu racha
  • Progreso de la lección y notas

Inicia sesión para ejecutar tu código.

Todas las clases se pueden leer gratis. Crea una cuenta o inicia sesión para ejecutar código, lanzar las pruebas y enviar este lab.

  • IDE en el navegador con terminal bash — sin instalar nada
  • Corrección instantánea, XP y tu lugar en la ruta
Crear una cuentaIniciar sesión
O
Continuar con GitHub