σμ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 7 · Investigación de alfa y riesgo›Tema 7.3·~55 minAvanzado

El coeficiente de información

Posición en la rutaMódulo 7 de 11 · Tema 3 de 9
7.3 El coeficiente de información
—Puntuación del lab— / 100XP total—Racha—

¿Predice algo la señal?

Antes de construir una estrategia sobre una señal, pregunta si apunta en la dirección correcta. Cada día una señal da una puntuación a cada acción y un día después cada acción tiene un rendimiento. El coeficiente de información (IC) es la correlación, entre acciones, de la puntuación y el rendimiento posterior. Va de -1 a 1; cero significa sin poder predictivo. Las señales reales son débiles: un IC de 0,02 a 0,05 ya es útil, porque se repite en muchas acciones y muchos días.

import numpy as np

signal = np.array([0.3, -1.2, 0.8, 0.1, 1.5])                  # today's score for five stocks
returns = np.array([0.01, -0.02, 0.005, -0.004, 0.03])         # their returns over the next day

s = signal - signal.mean()
r = returns - returns.mean()
ic = np.sum(s * r) / np.sqrt(np.sum(s ** 2) * np.sum(r ** 2))   # the Pearson correlation
print(round(float(ic), 4))
print(round(float(np.corrcoef(signal, returns)[0, 1]), 4))     # the same number

IC de rangos: robusto a valores extremos

Una correlación de Pearson está dominada por los valores extremos: una acción con una puntuación enorme o un salto del 40 % en un día puede inclinarla. El IC de rangos sustituye cada array por el rango de sus valores (1 para el menor) y correlaciona los rangos. Solo pregunta si las acciones que la señal pone más arriba terminan más arriba, sea cual sea el tamaño de los números, así que no cambia con ninguna transformación creciente de la señal. Es la versión que citan la mayoría de equipos cuantitativos, y es la correlación de Spearman.

# The rank of each value: argsort gives the order, assigning 1..n through it gives the ranks
import numpy as np

values = np.array([30.0, 10.0, 20.0, 5.0])
order = np.argsort(values)                       # positions from smallest to largest: [3 1 2 0]
ranks = np.empty(len(values))
ranks[order] = np.arange(1, len(values) + 1)
print(order, ranks)                              # [3 1 2 0] [4. 2. 3. 1.]
# Ranks via argsort, and a rank IC that shrugs off an extreme value
import numpy as np

def ranks(values):
    order = np.argsort(values)
    out = np.empty(len(values))
    out[order] = np.arange(1, len(values) + 1)
    return out

def ic(a, b):
    a, b = a - a.mean(), b - b.mean()
    return float(np.sum(a * b) / np.sqrt(np.sum(a ** 2) * np.sum(b ** 2)))

signal = np.array([0.3, -1.2, 0.8, 0.1, 1.5])
returns = np.array([0.01, -0.02, 0.005, -0.004, 0.03])
print(ranks(signal))                                           # [3. 1. 4. 2. 5.]
print(round(ic(signal, returns), 4), round(ic(ranks(signal), ranks(returns)), 4))

signal_with_outlier = signal.copy()
signal_with_outlier[4] = 1000.0                                # one absurd score
print(round(ic(signal_with_outlier, returns), 4), round(ic(ranks(signal_with_outlier), ranks(returns)), 4))

Consistencia en el tiempo: el ratio de información del IC

El IC de un día es ruidoso. Calcúlalo cada día para obtener una serie y mira su media y su regularidad. El ICIR, el IC medio dividido por su desviación típica, premia las señales que aciertan un poco cada día frente a las que aciertan mucho unos pocos días. Es un ratio tipo Sharpe para la propia señal. Una serie diaria de IC con media 0,03 y desviación 0,06 tiene un ICIR de 0,5.

# A daily rank-IC series for a weak signal, and its ICIR
import numpy as np

def ranks(values):
    out = np.empty(len(values))
    out[np.argsort(values)] = np.arange(1, len(values) + 1)
    return out

def ic(a, b):
    a, b = a - a.mean(), b - b.mean()
    return float(np.sum(a * b) / np.sqrt(np.sum(a ** 2) * np.sum(b ** 2)))

rng = np.random.default_rng(8)
daily_ics = []
for day in range(250):
    signal = rng.normal(size=300)                              # 300 stocks
    returns = 0.01 * (0.05 * signal + rng.normal(size=300))    # the signal explains a sliver of the return
    daily_ics.append(ic(ranks(signal), ranks(returns)))
daily_ics = np.array(daily_ics)
print(round(float(daily_ics.mean()), 4), round(float(daily_ics.std(ddof=1)), 4))
print(round(float(daily_ics.mean() / daily_ics.std(ddof=1)), 3))
Un buen IC es pequeño, y uno grande es una advertenciaLos mercados son casi eficientes, así que un IC superior a 0,1 es más probablemente un error que un hallazgo: busca sesgo de anticipación, una señal construida con los rendimientos que predice o un error de datos. Un IC real también decae con el horizonte, y su valor tras costes importa más que antes. Calcúlalo siempre con datos a los que la señal no se ajustó.
  • El IC es la correlación entre la señal de hoy en las acciones y sus rendimientos posteriores; 0,02 a 0,05 es útil, por encima de 0,1 es sospechoso.
  • El IC de rangos correlaciona rangos (argsort dos veces): robusto a valores extremos y sin cambio con cualquier transformación creciente de la señal.
  • ICIR = IC medio / desviación típica del IC durante muchos días: premia la habilidad constante; evalúe siempre fuera de muestra.

A continuación: el VaR histórico, la pérdida que una cartera no debe superar salvo en los peores días.

Lab: qué se califica

  • Ordenar los valores con ranks25 pts
  • Correlacionar señal y resultado con ic25 pts
  • Ignorar los valores extremos con rank_ic25 pts
  • Juzgar la consistencia con icir25 pts
Explorador · lab-95-1
▾ lab-95-1
…
bash · en el navegador
learner@quantcraft:~/lab-95-1$
Python aún no cargadoPythonLn 1, Col 1Spaces: 4UTF-8

¿Restablecer este tema?

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