σμ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.7·~40 minIntermedio

El ratio de Sharpe

Posición en la rutaMódulo 3 de 11 · Tema 7 de 12
3.7 El ratio de Sharpe
—Puntuación del lab— / 100XP total—Racha—

La recompensa por unidad de riesgo

Una estrategia que gana un 12 % con un 20 % de volatilidad no es mejor que una que gana un 6 % con un 5 %. El ratio de Sharpe las pone en una misma escala: el rendimiento medio por encima de la tasa libre de riesgo dividido por la volatilidad, (mean - rf) / std, anualizado con sqrt(periodos). Viste la fórmula en el tema de media y varianza. Este tema trata de su uso: cómo leer un ratio de Sharpe, mejorarlo y, sobre todo, cuánto fiarse de él. Un Sharpe de 0,5 es mediocre, 1 es bueno, 2 es excelente y sospechoso.

La volatilidad cuenta igual la subida y la bajada, pero nadie se queja de una ganancia sorpresa. El ratio de Sortino conserva solo el lado malo: sustituye la desviación típica por la desviación a la baja, sqrt(mean(min(r - mar, 0)²)), donde mar es el rendimiento mínimo aceptable. Los días por encima de mar aportan cero pero siguen contando en la media. Una estrategia con grandes saltos positivos y pequeñas pérdidas puntúa mucho mejor en Sortino que en Sharpe.

import math
import numpy as np
import pandas as pd

returns = np.array([0.004, -0.002, 0.001, 0.003, -0.004, 0.002, 0.006, -0.001, -0.010, 0.004, 0.002, -0.003])

sharpe = returns.mean() / returns.std(ddof=1) * math.sqrt(252)
print(round(sharpe, 3))                                  # 0.598

mar = 0.0                                                # a day below zero is a bad day
downside = math.sqrt(np.mean(np.minimum(returns - mar, 0) ** 2))
sortino = (returns.mean() - mar) / downside * math.sqrt(252)
print(round(downside, 5), round(sortino, 3))             # 0.00329 0.804   the up days no longer count as risk

Verlo moverse

Un solo ratio de Sharpe para todo el historial oculta la historia. Un ratio de Sharpe móvil lo recalcula con los últimos window rendimientos, de modo que se ven los buenos y malos regímenes de la estrategia. Con pandas es la media móvil dividida por la desviación típica móvil, anualizada. Fíjate en cuánto saltan las ventanas cortas: un mes de datos no basta ni de lejos para clasificar estrategias.

series = pd.Series(returns)
rolling = series.rolling(5)
rolling_sharpe = rolling.mean() / rolling.std() * math.sqrt(252)
print(rolling_sharpe.round(2).tolist())
# [nan, nan, nan, nan, 1.89, 0.0, 6.96, 4.97, -3.66, 0.51, 0.51, -4.69]   a 5-day Sharpe ratio is mostly noise

¿Cuánto es suerte?

Un ratio de Sharpe es una estimación, y las estimaciones tienen error. Para un Sharpe por periodo sr medido con n rendimientos, el error estándar es aproximadamente sqrt((1 + 0,5 * sr²) / n). Con nuestros 12 días es 0,29 diario frente a un Sharpe de 0,04: el error es siete veces la estimación. Anualizados, esos mismos 12 días dan 0,6 ± 4,6. Para un Sharpe anual S observado durante years años, el estadístico t es S * sqrt(years), así que hacen falta (1,96 / S)² años para estar seguro al 95 % de que no es cero: 15 años para un Sharpe de 0,5, 4 años para un Sharpe de 1. Los backtests cortos de estrategias modestas no prueban nada.

per_period = returns.mean() / returns.std(ddof=1)            # the per-day Sharpe ratio
std_error = math.sqrt((1 + 0.5 * per_period ** 2) / len(returns))
print(round(per_period, 4), round(std_error, 4))            # 0.0376 0.2888   the error is 7 times the estimate
print(round(std_error * math.sqrt(252), 3))                 # 4.584           annualised: 0.6 +/- 4.6

# Years needed for an annual Sharpe ratio to reach t = 1.96
for annual in (0.5, 1.0, 2.0):
    print(annual, round((1.96 / annual) ** 2, 1))
# 0.5 15.4
# 1.0 3.8
# 2.0 1.0
# A yearly Sharpe of 1.0 observed over 4 years (1,008 days): how precise is it?
per_day = 1.0 / math.sqrt(252)
error_per_day = math.sqrt((1 + 0.5 * per_day ** 2) / 1008)
print(round(per_day, 4), round(error_per_day, 4), round(error_per_day * math.sqrt(252), 3))   # 0.063 0.0315 0.5   so 1.0 +/- 0.5
El mejor backtest es el menos fiableSi pruebas 100 variantes de una estrategia y te quedas con la de mayor ratio de Sharpe, la cifra de la ganadora está inflada por la selección: incluso estrategias sin ventaja producen un Sharpe de 1 o más por suerte. Divide tu entusiasmo por el número de variantes probadas, prueba con datos que la selección nunca vio y prefiere ideas con una razón económica.
  • Sharpe = (mean - rf) / std * sqrt(periodos); Sortino sustituye la desviación por la desviación a la baja sqrt(mean(min(r - mar, 0)²)).
  • Un Sharpe móvil (rolling.mean() / rolling.std()) muestra cómo cambia el ratio; las ventanas cortas son sobre todo ruido.
  • Su error estándar es sqrt((1 + 0,5 * sr²) / n) por periodo; el estadístico t de un Sharpe anual es S * sqrt(years): un Sharpe de 1 necesita unos 4 años.

A continuación: los drawdowns, las pérdidas desde un máximo que los inversores realmente sienten.

Lab: qué se califica

  • Penalizar solo los días malos con sortino_ratio25 pts
  • Ver cómo cambia el ratio en el tiempo con rolling_sharpe25 pts
  • Medir la suerte de un ratio de Sharpe con sharpe_standard_error25 pts
  • Preguntarse si es real con sharpe_t_stat25 pts
Explorador · lab-60-1
▾ lab-60-1
…
bash · en el navegador
learner@quantcraft:~/lab-60-1$
Python aún no cargadoPythonLn 1, Col 1Spaces: 4UTF-8

¿Restablecer este tema?

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