σμ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 1 · Fundamentos de Python para quants›Tema 1.33·~45 minPrincipiante

Variables aleatorias y esperanza

Posición en la rutaMódulo 1 de 11 · Tema 33 de 33
1.33 Variables aleatorias y esperanza
—Puntuación del lab— / 100XP total—Racha—

Un número cuyo valor aún no se conoce

Una variable aleatoria es una cantidad cuyo valor depende del azar: la tirada de un dado, el rendimiento de mañana, el precio de una acción al vencimiento. Una variable aleatoria discreta toma una lista de valores posibles, cada uno con una probabilidad. Los valores y las probabilidades forman su distribución. Las probabilidades nunca son negativas y suman 1. En Python son simplemente dos listas de la misma longitud, values y probs. Un dado justo es values = [1, 2, 3, 4, 5, 6] con probs = [1/6] * 6.

import math

values = [1, 2, 3, 4, 5, 6]
probs = [1 / 6] * 6

# A valid distribution: no negatives, and the probabilities add up to 1
print(all(p >= 0 for p in probs))             # True
print(math.isclose(sum(probs), 1.0))          # True (compare floats with isclose)

# A stock tomorrow: down 5%, up 2% or up 8%
returns = [-0.05, 0.02, 0.08]
chances = [0.2, 0.5, 0.3]
print(math.isclose(sum(chances), 1.0))        # True

La esperanza: el promedio ponderado por probabilidades

La esperanza E[X] es el promedio que obtendrías tras muchas repeticiones: multiplica cada valor por su probabilidad y suma, sum(v * p). Un dado tiene E[X] = 3.5, un número que nunca puede salir, y no pasa nada: es un promedio a largo plazo, no la predicción de un resultado. La esperanza es lineal: E[a*X + b] = a*E[X] + b. La esperanza de una función E[g(X)] aplica primero g a cada valor: sum(g(v) * p). Cuidado: en general E[g(X)] no es g(E[X]). El pago de una opción max(S - K, 0) es el caso clásico.

def expected_value(values, probs):
    return sum(v * p for v, p in zip(values, probs))

die = [1, 2, 3, 4, 5, 6]
fair = [1 / 6] * 6
print(round(expected_value(die, fair), 4))            # 3.5

# E[g(X)]: apply g to each value first. Call payoff with strike 100:
prices = [90, 100, 110, 120]
chances = [0.1, 0.4, 0.3, 0.2]
mean_price = expected_value(prices, chances)
print(mean_price)                                      # 106.0
print(expected_value([max(s - 100, 0) for s in prices], chances))  # 7.0  = E[max(S - K, 0)]
print(max(mean_price - 100, 0))                        # 6.0  = max(E[S] - K, 0), not the same

La varianza: ¿cuán dispersa es?

Dos inversiones pueden tener la misma rentabilidad esperada y un riesgo muy distinto. La varianza mide la dispersión alrededor de la media: Var(X) = E[(X - mu)^2], que también se calcula como E[X^2] - E[X]^2. La desviación típica es su raíz cuadrada, en las mismas unidades que X; para rendimientos es la volatilidad. Para el dado, Var = 35/12 = 2.9167. Ambas se construyen con esperanzas de funciones de X, así que una expected_of(g, values, probs) bien escrita da la media, el segundo momento y todo lo demás.

def expected_value(values, probs):
    return sum(v * p for v, p in zip(values, probs))

def expected_of(g, values, probs):
    return expected_value([g(v) for v in values], probs)

def variance(values, probs):
    mean = expected_of(lambda v: v, values, probs)
    return expected_of(lambda v: v * v, values, probs) - mean ** 2

die, fair = [1, 2, 3, 4, 5, 6], [1 / 6] * 6
print(round(variance(die, fair), 4))                   # 2.9167

returns, chances = [-0.05, 0.02, 0.08], [0.2, 0.5, 0.3]
print(round(expected_value(returns, chances), 4))      # 0.024
print(round(variance(returns, chances), 6))            # 0.002044

Simulación y ley de los grandes números

También puedes estimar una esperanza sacando muestras. rng.choices(values, weights=probs, k=n) devuelve n extracciones, y el promedio de las extracciones se acerca a E[X] al crecer n: la ley de los grandes números. Es el corazón de la valoración Monte Carlo. Usa tu propio random.Random(seed) para que la ejecución sea repetible y no perturbe otro código. Con pocas extracciones el promedio es ruidoso; el error solo decrece como uno entre la raíz de n, así que 100 veces más extracciones dan solo 10 veces más precisión.

import random

die, fair = [1, 2, 3, 4, 5, 6], [1 / 6] * 6

def sample_mean(values, probs, n, seed):
    rng = random.Random(seed)                    # private, repeatable generator
    draws = rng.choices(values, weights=probs, k=n)
    return sum(draws) / n

for n in (10, 1000, 100000):
    print(n, round(sample_mean(die, fair, n, 1), 4))
# 10 3.1
# 1000 3.598
# 100000 3.5017       (closing in on 3.5)

print(sample_mean(die, fair, 1000, 1) == sample_mean(die, fair, 1000, 1))  # True: same seed, same answer
Comprueba la distribución antes de usarlaUna distribución cuyas probabilidades no suman 1, contienen un negativo o no coinciden en longitud con los valores da una esperanza sin sentido y sin ningún error. Valida primero: longitudes iguales, sin negativos, math.isclose(sum(probs), 1.0). Lanza ValueError en cualquier otro caso. Recuerda también que una esperanza es un promedio a largo plazo: una estrategia con esperanza positiva puede perder dinero un día cualquiera.
  • Una distribución es values más probs (sin negativos, suma 1); E[X] = sum(v * p).
  • E[g(X)] = sum(g(v) * p), que no es g(E[X]); Var = E[X^2] - E[X]^2.
  • Las medias muestrales convergen a E[X] (ley de los grandes números); usa tu propio random.Random(seed).

A continuación: arreglos NumPy y dtypes, los arreglos rápidos y tipados sobre los que se construye el resto del curso.

Lab: qué se califica

  • Promediar resultados según sus probabilidades con expected_value25 pts
  • Calcular la esperanza de un pago con expected_of25 pts
  • Medir la dispersión con variance25 pts
  • Estimar la esperanza por simulación con sample_mean25 pts
Explorador · lab-33-1
▾ lab-33-1
…
bash · en el navegador
learner@quantcraft:~/lab-33-1$
Python aún no cargadoPythonLn 1, Col 1Spaces: 4UTF-8

¿Restablecer este tema?

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