σμ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 3 · Probabilidad y simulación Monte Carlo›Tema 3.9·~40 minIntermedio

Generadores de números aleatorios y semillas

Posición en la rutaMódulo 3 de 11 · Tema 9 de 12
3.9 Generadores de números aleatorios y semillas
—Puntuación del lab— / 100XP total—Racha—

Aleatorio, pero repetible

La simulación Monte Carlo, el bootstrap y muchas pruebas necesitan números aleatorios, pero un resultado que nadie puede reproducir no vale nada: no se puede depurar, ni comparar dos versiones de un modelo, ni enseñárselo a un colega. Los números que produce un ordenador no son realmente aleatorios. Un generador de números pseudoaleatorios es un algoritmo determinista que, a partir de un valor inicial llamado semilla (seed), produce una secuencia larga que se comporta como extracciones aleatorias. La misma semilla da la misma secuencia, siempre y en cualquier máquina.

import numpy as np

rng = np.random.default_rng(42)            # a Generator created from the seed 42
print(rng.random(3).round(4).tolist())     # [0.774, 0.4389, 0.8586]

rng = np.random.default_rng(42)            # the same seed again: the same numbers
print(rng.random(3).round(4).tolist())     # [0.774, 0.4389, 0.8586]

rng = np.random.default_rng(43)            # another seed: other numbers
print(rng.random(3).round(4).tolist())     # [0.6523, 0.0438, 0.02]

Usa un Generator, no estado global

El código antiguo llama una vez a np.random.seed(42) y luego a np.random.normal(...) en cualquier sitio: todo el código comparte un único generador global oculto. Cualquier biblioteca, o cualquier línea nueva que saque un número, desplaza la secuencia de todos los demás, de modo que los resultados cambian por razones ajenas a tu modelo. La forma moderna es crear un objeto Generator con np.random.default_rng(seed) y pasarlo explícitamente. Sus métodos random, normal, choice, integers hacen todas las extracciones, y dos generadores nunca interfieren.

def simulate_returns(seed, n, mu, sigma):
    rng = np.random.default_rng(seed)              # a private generator, not the global one
    return rng.normal(mu, sigma, size=n)

first = simulate_returns(7, 5, 0.0005, 0.01)
second = simulate_returns(7, 5, 0.0005, 0.01)
print(first.round(5).tolist())                     # [0.00051, 0.00349, -0.00224, -0.00841, -0.00405]
print(np.array_equal(first, second))               # True   repeatable

Remuestreo y flujos independientes

Un bootstrap remuestrea el historial para ver cuánto podría haber variado un estadístico: se extraen tantos rendimientos como se tienen, con reemplazo, con rng.choice(returns, size=len(returns), replace=True). Algunos días aparecen dos veces, otros ninguna. Cuando muchas simulaciones corren en paralelo, dar a cada proceso las semillas 1, 2, 3 es arriesgado porque las semillas cercanas no tienen garantizada la independencia. np.random.SeedSequence(seed).spawn(k) deriva k secuencias hijas diseñadas para no solaparse; construye un default_rng(child) con cada una.

data = np.array([1, 2, 3, 4, 5])
rng = np.random.default_rng(1)
print(rng.choice(data, size=len(data), replace=True).tolist())    # [3, 3, 4, 5, 1]   3 appears twice, 2 not at all

# Three independent streams from one seed, for three parallel simulations
children = np.random.SeedSequence(2026).spawn(3)
streams = [np.random.default_rng(child) for child in children]
print([stream.random(2).round(4).tolist() for stream in streams])
# [[0.3827, 0.0204], [0.6711, 0.158], [0.5508, 0.2339]]
rng = np.random.default_rng(42)
print(rng.integers(1, 7, size=8).tolist())             # [1, 5, 4, 3, 3, 6, 1, 5]   eight dice rolls, repeatable
rng = np.random.default_rng(42)
print(rng.uniform(-0.01, 0.01, 3).round(5).tolist())   # [0.00548, -0.00122, 0.00717]
Fija la semilla a propósito y anótalaUna semilla fija hace repetible una ejecución, pero no es un control de calidad: una semilla afortunada puede hacer que una mala idea parezca buena. Ejecuta el análisis con varias semillas y comprueba que la conclusión se mantiene. Imprime o registra la semilla usada para que un resultado de un informe pueda regenerarse siempre, y nunca elijas una semilla porque dé una respuesta más agradable.
  • rng = np.random.default_rng(seed): la misma semilla da siempre los mismos números; usa sus métodos random, normal, choice, integers.
  • Pasa el generador en lugar de usar el estado global oculto np.random.seed.
  • choice(..., replace=True) es un bootstrap; SeedSequence(seed).spawn(k) da k flujos independientes; registra la semilla usada.

A continuación: el muestreo de distribuciones, para convertir números aleatorios uniformes en extracciones normales, exponenciales y discretas.

Lab: qué se califica

  • Crear un generador repetible con make_rng25 pts
  • Generar rendimientos reproducibles con simulate_returns25 pts
  • Remuestrear el historial con bootstrap_returns25 pts
  • Dividir una semilla en flujos independientes con independent_streams25 pts
Explorador · lab-62-1
▾ lab-62-1
…
bash · en el navegador
learner@quantcraft:~/lab-62-1$
Python aún no cargadoPythonLn 1, Col 1Spaces: 4UTF-8

¿Restablecer este tema?

Todo lo que hay en lab-62-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