Lección 2.5.4 · 70 min

Deflated Sharpe Ratio y Probability of Backtest Overfitting (PBO)

Un Sharpe de 1,5 no significa lo mismo si es el único que se ha probado que si es el mejor de mil. Esta lección programa las tres herramientas de Bailey y López de Prado para descontar la suerte: el Sharpe probabilístico, el Deflated Sharpe y la probabilidad de sobreajuste del backtest, y las prueba donde se conoce la respuesta.

Fig. — Deflated Sharpe Ratio según el número de intentos declarados: la mejor estrategia con ventaja (e0518) y el mejor ruido (e0598) de 1.000 estrategias sintéticas
Lecciones del nivel 2
  1. 2.1 · Estadística y econometría para trading

    1. 2.1.1 Contrastes de hipótesis, p-valores, bootstrap y regresión con errores robustos
    2. 2.1.2 Estacionariedad: ADF, KPSS, diferenciación y diferenciación fraccional
    3. 2.1.3 Modelos ARMA y ARIMA: autocorrelación simple (ACF) y parcial (PACF)
    4. 2.1.4 Modelos de volatilidad: ARCH, GARCH, EGARCH y GJR con la librería arch
    5. 2.1.5 Cointegración: Engle-Granger, Johansen y vida media de la reversión
    6. 2.1.6 Filtro de Kalman para hedge ratios dinámicos
    7. 2.1.7 Detección de regímenes: modelos de Markov ocultos y cambios estructurales
    8. 2.1.8 El problema de las pruebas múltiples: Bonferroni, FDR y el «factor zoo»
  2. 2.2 · Anatomía de un sistema de trading

    1. 2.2.1 Hipótesis de ventaja: riesgo, comportamiento, estructura e información
    2. 2.2.2 Universo, señal, filtro, entrada, salida, sizing y gestión del riesgo
    3. 2.2.3 Frecuencias: intradía, swing y posicional, y la capacidad de una estrategia
    4. 2.2.4 Diario de investigación y registro de experimentos contra el data snooping
  3. 2.3 · Familias de estrategias

    1. 2.3.1 Seguimiento de tendencia y momentum
    2. 2.3.2 Reversión a la media: RSI y Bollinger, reversión intradía y huecos
    3. 2.3.3 Pairs trading y arbitraje estadístico: distancia, cointegración y Kalman
    4. 2.3.4 Carry en divisas, futuros y bonos; estacionalidad y efectos calendario
    5. 2.3.5 Factores (value, calidad, baja volatilidad, tamaño) y estrategias de eventos
    6. 2.3.6 Introducción al market making: inventario, spread y selección adversa (Avellaneda-Stoikov)
    7. 2.3.7 Estrategias específicas de cripto: momentum, arbitraje de funding y basis
  4. 2.4 · Backtesting: motores y paradigmas

    1. 2.4.1 Backtest vectorizado desde cero: matrices, desfase, costes y límites
    2. 2.4.2 Backtest por eventos desde cero: bucle, cartera, órdenes y fills
    3. 2.4.3 vectorbt: barridos masivos de parámetros y simulación de carteras
    4. 2.4.4 backtesting.py y backtrader: dos motores didácticos y su estado
    5. 2.4.5 NautilusTrader: arquitectura, datos, estrategias y el mismo código en backtest y en real
    6. 2.4.6 LEAN/QuantConnect y Zipline Reloaded; bt para asignación de activos
    7. 2.4.7 Modelado de costes: comisiones, horquilla, impacto, financiación y préstamo de títulos
    8. 2.4.8 Modelado de fills: órdenes limitadas, cola, fills parciales, huecos y stops
  5. 2.5 · Sesgos y validación

    1. 2.5.1 Sesgos de backtest: anticipación, supervivencia, selección y narrativa
    2. 2.5.2 In-sample y out-of-sample: walk-forward anclado y móvil
    3. 2.5.3 Validación cruzada combinatoria purgada para estrategias
    4. 2.5.4 Deflated Sharpe Ratio y Probability of Backtest Overfitting (PBO)
    5. 2.5.5 Monte Carlo: remuestreo de trades, bootstrap de bloques y permutaciones de señales
    6. 2.5.6 Sensibilidad de parámetros: mesetas frente a picos, robustez entre activos y periodos
    7. 2.5.7 Datos sintéticos para pruebas de estrés: GBM, GARCH y bootstrapping
    8. 2.5.8 Checklist de «backtest honesto» antes de pasar a paper trading
  6. 2.6 · Métricas de rendimiento

    1. 2.6.1 CAGR, Sharpe, Sortino, Calmar, Omega, drawdown y Ulcer Index
    2. 2.6.2 Win rate, payoff, expectativa, alpha, beta, information ratio, turnover y capacidad
    3. 2.6.3 Informes con QuantStats o pyfolio-reloaded y tearsheets propios

El Sharpe del mejor de N

La lección 2.5.1 enseñó el problema con números: entre 1.000 estrategias sin ventaja, el máximo del Sharpe está en torno a 2 aunque ninguna valga nada. La lección 2.5.2 vio la consecuencia en un walk-forward y la 2.5.3, en la distribución de caminos de una validación cruzada. Esta lección da las herramientas para corregir un Sharpe por la suerte, en dos niveles:

  • Para una estrategia, ¿cuánta evidencia da su Sharpe, dada la longitud de la serie y la forma de su distribución? Es el Probabilistic Sharpe Ratio (PSR).
  • Para la mejor de N, ¿supera lo que se esperaría del mejor de N intentos sin ventaja? Es el Deflated Sharpe Ratio (DSR). Y, si se tiene la matriz completa de los intentos, ¿con qué frecuencia el proceso de elegir el mejor acaba eligiendo uno peor que la mediana fuera de muestra? Es la probabilidad de sobreajuste del backtest (PBO).
Sharpe medidoPSR: frente a 0DSR: frente a maxN intentosMatriz T x NPBO por CSCVDecisión
Fuente Mermaid
flowchart TB
  S[Sharpe medido] --> P[PSR: frente a 0]
  P --> D[DSR: frente a max]
  N[N intentos] --> D
  M[Matriz T x N] --> B[PBO por CSCV]
  D --> X[Decisión]
  B --> X

Las tres son de David Bailey y Marcos López de Prado (con Borwein y Zhu en el PBO), y las fórmulas de esta lección siguen sus artículos, enlazados en los recursos.

El Sharpe probabilístico (PSR)

El Sharpe estimado con T observaciones tiene un error. Con rendimientos normales e independientes, su error típico es aproximadamente (1+SR^2/2)/T\sqrt{(1 + \widehat{SR}^2/2)/T} en unidades por periodo (Lo, 2002). Con colas gruesas y asimetría, es mayor: una estrategia que gana poco casi siempre y pierde mucho de vez en cuando (asimetría negativa, curtosis alta) puede tener un Sharpe alto durante años sin que eso diga mucho. El PSR mide la probabilidad de que el Sharpe verdadero supere un umbral SR∗SR^*, con γ^3\widehat{\gamma}_3 la asimetría y γ^4\widehat{\gamma}_4 la curtosis (3 en la normal) de los rendimientos:

PSR^(SR∗)=Φ((SR^−SR∗)T−11−γ^3 SR^+γ^4−14 SR^2)\widehat{PSR}(SR^*) = \Phi\left(\frac{(\widehat{SR} - SR^*)\sqrt{T-1}}{\sqrt{1 - \widehat{\gamma}_3\,\widehat{SR} + \frac{\widehat{\gamma}_4 - 1}{4}\,\widehat{SR}^2}}\right)

Todos los Sharpes de la fórmula van en la frecuencia de los datos (diarios aquí), sin anualizar.

IN [01]python
import numpy as np
import pandas as pd
from scipy.stats import norm

est = pd.read_parquet("ruido2_estrategias.parquet").pivot(
    index="fecha", columns="estrategia", values="rendimiento")
verdad = pd.read_csv("ruido2_verdad.csv", index_col="estrategia")

def psr(sr, sr_umbral, t, asim, curt):
    """Probabilistic Sharpe Ratio. Sharpes por periodo; `curt` es la
    curtosis (3 en la normal), no el exceso."""
    den = np.sqrt(1 - asim * sr + (curt - 1) / 4 * sr**2)
    z = (sr - sr_umbral) * np.sqrt(t - 1) / den
    if isinstance(z, pd.Series):  # conserva los nombres
        return pd.Series(norm.cdf(z), index=z.index)
    return norm.cdf(z)

T = len(est)
sr = est.mean() / est.std()           # Sharpe diario
asim, curt = est.skew(), est.kurt() + 3
psr0 = psr(sr, 0, T, asim, curt)

pasan = psr0 > 0.95
reales = verdad["sharpe_real"] > 0
print(f"T = {T} sesiones; PSR(0) > 0,95: {pasan.sum()} estrategias, "
      f"{(pasan & reales).sum()} con ventaja real")
OUT [01]El PSR, desde cero
T = 1003 sesiones; PSR(0) > 0,95: 57 estrategias, 4 con ventaja real

Contrastada una por una frente a un Sharpe de 0, más de cincuenta estrategias parecen tener ventaja con un 95 % de probabilidad, y solo cuatro la tienen. Es lo esperable: con 1.000 contrastes al 5 %, unos 50 falsos positivos (la lección 2.1.8 trata las correcciones de pruebas múltiples). El PSR no es el problema: está contestando a la pregunta de una estrategia aislada, y aquí hay mil.

IN [02]python
ruido = reales.index[~reales.to_numpy()]
mejores_ruido = sr[ruido].nlargest(2).index
elegidas = list(reales.index[reales.to_numpy()]) + list(mejores_ruido)
tabla = pd.DataFrame({
    "sharpe_anual": sr[elegidas] * np.sqrt(252),
    "asimetria": asim[elegidas], "curtosis": curt[elegidas],
    "PSR(0)": psr0[elegidas],
    "real": verdad.loc[elegidas, "sharpe_real"]})
tabla.round(3)
OUT [02]Las cinco con ventaja y las dos mejores del ruido
            sharpe_anual  asimetria  curtosis  PSR(0)  real
estrategia
e0080              0.951      0.234     4.657   0.972   0.5
e0133              1.459     -0.284     7.113   0.998   0.8
e0258              0.622     -0.096     4.295   0.892   0.7
e0518              1.579      0.252     7.003   0.999   1.5
e0751              0.832     -0.133     4.008   0.951   0.6
e0598              1.503     -0.066     4.803   0.999   0.0
e0316              1.423      0.309     6.503   0.998   0.0

Las dos mejores del ruido, e0598 y e0316, tienen un Sharpe medido de 1,50 y 1,42 y un PSR(0) de 0,999 y 0,998: igual que e0133 y e0518, que sí tienen ventaja. Por el Sharpe y su forma, nada las distingue. Y dos de las cinco buenas, e0258 y e0751, tienen un PSR(0) que roza o no llega al 0,95: con 1.003 sesiones, una ventaja verdadera de 0,6-0,7 anual se confunde con el ruido. La curtosis, de 4 a 7 en estas series (con innovaciones t de 5 grados de libertad), agranda el denominador, aunque con Sharpes diarios del orden de 0,1 su efecto es pequeño.

El Deflated Sharpe Ratio (DSR)

La pregunta correcta para la mejor de N no es si supera a 0, sino si supera al máximo que darían N intentos sin ventaja. El DSR es el PSR con el umbral en ese máximo esperado. Bailey y López de Prado (2014) lo aproximan con la dispersión de los Sharpes de los intentos, V[{SR^n}]V[\{\widehat{SR}_n\}], y la misma expresión de valores extremos de la lección 2.5.1:

SR0=V[{SR^n}][(1−γ) Φ−1 ⁣(1−1N)+γ Φ−1 ⁣(1−1Ne)],DSR=PSR^(SR0)SR_0 = \sqrt{V[\{\widehat{SR}_n\}]}\left[(1-\gamma)\,\Phi^{-1}\!\left(1-\tfrac{1}{N}\right) + \gamma\,\Phi^{-1}\!\left(1-\tfrac{1}{N e}\right)\right], \qquad DSR = \widehat{PSR}(SR_0)

con γ≈0,5772\gamma \approx 0{,}5772, la constante de Euler-Mascheroni. La varianza es la de los Sharpes medidos de todos los intentos, no una teórica: si los intentos se parecen (variantes muy correlacionadas), su dispersión es menor y el umbral baja.

IN [03]python
def sr_max_esperado(n, var_sr):
    g = np.euler_gamma
    return np.sqrt(var_sr) * ((1 - g) * norm.ppf(1 - 1 / n)
                              + g * norm.ppf(1 - 1 / (n * np.e)))

def dsr(sr_i, n, var_sr, t, asim_i, curt_i):
    umbral = sr_max_esperado(n, var_sr) if n > 1 else 0.0
    return psr(sr_i, umbral, t, asim_i, curt_i)

var_sr = sr.var()
print(f"Dispersión de los 1.000 Sharpes: {np.sqrt(var_sr * 252):.3f} "
      f"anual (teórica sin ventaja: {np.sqrt(252 / T):.3f})")
for n in (10, 50, 1000):
    print(f"N = {n:>4}: SR_0 = "
          f"{sr_max_esperado(n, var_sr) * np.sqrt(252):.2f} anual")

tabla["DSR(1000)"] = dsr(sr[elegidas], 1000, var_sr, T,
                         asim[elegidas], curt[elegidas])
tabla["DSR(50)"] = dsr(sr[elegidas], 50, var_sr, T,
                       asim[elegidas], curt[elegidas])
cols = ["sharpe_anual", "PSR(0)", "DSR(50)", "DSR(1000)", "real"]
tabla[cols].round(3)
OUT [03]El DSR, desde cero
Dispersión de los 1.000 Sharpes: 0.486 anual (teórica sin ventaja: 0.501)
N =   10: SR_0 = 0.77 anual
N =   50: SR_0 = 1.11 anual
N = 1000: SR_0 = 1.58 anual
            sharpe_anual  PSR(0)  DSR(50)  DSR(1000)  real
estrategia
e0080              0.951   0.972    0.377      0.102   0.5
e0133              1.459   0.998    0.754      0.404   0.8
e0258              0.622   0.892    0.167      0.028   0.7
e0518              1.579   0.999    0.828      0.497   1.5
e0751              0.832   0.951    0.293      0.068   0.6
e0598              1.503   0.999    0.783      0.437   0.0
e0316              1.423   0.998    0.737      0.373   0.0

La dispersión medida de los 1.000 Sharpes, 0,49 anual, coincide casi con la teórica de un Sharpe sin ventaja con 1.003 sesiones: como debe ser, porque casi todas son ruido. Con N = 1.000, el máximo esperado del ruido es un Sharpe anual de 1,58, y ninguna estrategia lo supera con un 95 % de probabilidad: e0518, la mejor de verdad, se queda en 0,50, y e0598, el mejor ruido, en 0,44. El DSR no las separa porque los datos no las separan: con cuatro años de datos, un Sharpe verdadero de 1,5 no se distingue del máximo de mil ruidos. Es la conclusión honesta, y es la que daría el DSR con datos reales.

Fig. — PSR frente a 0 y Deflated Sharpe con 50 y 1.000 intentos de las cinco estrategias sintéticas con ventaja y las dos mejores del ruido, con su Sharpe verdadero

La figura pone las tres probabilidades de cada estrategia en la misma escala. Contra 0 (cuadrados) casi todas pasan; con 50 intentos (rombos) ninguna llega a 0,95; con 1.000 (círculos), la mejor se queda en 0,50. Y el orden de las filas, por Sharpe medido, mezcla buenas y ruido: el mejor ruido es la segunda fila.

La figura de la cabecera enseña la misma cuenta como función de N: el DSR de las dos estrategias cae al aumentar el número de intentos que se declaran.

IN [04]python
ns = [1, 2, 3, 5, 7, 10, 15, 20, 30, 50, 70, 100, 150, 200, 300,
      500, 700, 1000]
curvas = pd.DataFrame({e: [dsr(sr[e], n, var_sr, T, asim[e], curt[e])
                           for n in ns] for e in ("e0518", "e0598")},
                      index=pd.Index(ns, name="N"))
print(curvas.loc[[1, 5, 10, 20, 50, 100, 1000]].round(3))
for e in curvas:
    ultimo = curvas.index[curvas[e] >= 0.95].max()
    print(f"{e}: DSR ≥ 0,95 hasta N = {ultimo}")
OUT [04]DSR según el número de intentos
      e0518  e0598
N
1     0.999  0.999
5     0.977  0.966
10    0.948  0.928
20    0.905  0.874
50    0.828  0.783
100   0.757  0.705
1000  0.497  0.437
e0518: DSR ≥ 0,95 hasta N = 7
e0598: DSR ≥ 0,95 hasta N = 5

Si e0518 hubiera sido la única idea probada, su Sharpe sería concluyente (DSR 0,999). Declarando diez intentos, el DSR ya roza 0,95; con veinte, no llega. El mejor ruido tiene casi la misma curva, un poco por debajo. La lección práctica: el número de intentos es parte del resultado, y declarar menos de los que se hicieron es una forma de fraude, aunque sea involuntaria.

IN [05]python
autoval = np.linalg.eigvalsh(est.corr().to_numpy())
n_ef = autoval.sum() ** 2 / (autoval ** 2).sum()
print(f"Razón de participación: {n_ef:.0f} intentos efectivos")
d = dsr(sr[["e0518", "e0598"]], round(n_ef), var_sr, T,
        asim[["e0518", "e0598"]], curt[["e0518", "e0598"]])
print(d.round(3).to_string())
OUT [05]Un número efectivo de intentos
Razón de participación: 147 intentos efectivos
estrategia
e0518    0.715
e0598    0.660

Con 147 intentos efectivos, el DSR de e0518 es 0,72 y el de e0598, 0,66: entre las dos cotas y lejos de 0,95.

La probabilidad de sobreajuste (PBO)

El DSR necesita N y la dispersión de los intentos. Si además se guardaron los rendimientos de todos los intentos (una matriz de T sesiones por N variantes), se puede medir directamente qué pasa al elegir el mejor. Es la idea de la validación cruzada simétrica combinatoria (CSCV) de Bailey, Borwein, López de Prado y Zhu:

  1. Se parte la matriz en S bloques de filas contiguos (S par; aquí 16).
  2. Para cada una de las (SS/2)\binom{S}{S/2} formas de elegir la mitad de los bloques (12.870 con S = 16): esa mitad es el conjunto «dentro» y la otra, «fuera».
  3. Se elige la variante con mejor Sharpe dentro y se mira su rango relativo fuera, ω‾c\overline{\omega}_c (1 si es la mejor de N, cerca de 0 si es la peor), y su logit, λc=ln⁡(ω‾c/(1−ω‾c))\lambda_c = \ln\left(\overline{\omega}_c / (1 - \overline{\omega}_c)\right).
  4. El PBO es la proporción de particiones con λc≤0\lambda_c \le 0: la elegida queda en la mitad mala fuera.
Matriz T x NS bloquesParticionesMejor dentroRango fueraLogitPBO: logit ≤ 0
Fuente Mermaid
flowchart TB
  M[Matriz T x N] --> B[S bloques]
  B --> C[Particiones]
  C --> E[Mejor dentro]
  E --> R[Rango fuera]
  R --> L[Logit]
  L --> P[PBO: logit ≤ 0]

Si la elección no aporta nada, el rango fuera de la elegida es uniforme y el PBO, 0,5. Si la elección acierta (la mejor dentro tiende a serlo fuera), los logits son positivos y el PBO, bajo. La partición es simétrica: dentro y fuera tienen el mismo tamaño y cada bloque está la mitad de las veces en cada lado.

IN [06]python
from itertools import combinations

def pbo_cscv(m, s=16):
    """m: matriz T x N de rendimientos. Devuelve el PBO, los logits y,
    por partición, el Sharpe dentro y fuera de la elegida."""
    t, n = m.shape
    bloques = np.array_split(np.arange(t), s)
    suma = np.array([m[b].sum(0) for b in bloques])
    suma2 = np.array([(m[b] ** 2).sum(0) for b in bloques])
    filas = np.array([len(b) for b in bloques])

    def sharpe(idx):
        k = filas[idx].sum()
        media = suma[idx].sum(0) / k
        return media / np.sqrt(suma2[idx].sum(0) / k - media ** 2)

    logits, sh_dentro, sh_fuera = [], [], []
    for dentro in combinations(range(s), s // 2):
        dentro = list(dentro)
        fuera = [i for i in range(s) if i not in dentro]
        a, b = sharpe(dentro), sharpe(fuera)
        j = np.argmax(a)
        w = (b < b[j]).sum() + 1        # rango de 1 (peor) a n
        w = w / (n + 1)
        logits.append(np.log(w / (1 - w)))
        sh_dentro.append(a[j]); sh_fuera.append(b[j])
    logits = np.array(logits)
    return ((logits <= 0).mean(), logits,
            np.array(sh_dentro) * np.sqrt(252),
            np.array(sh_fuera) * np.sqrt(252))

pbo, logits, sh_d, sh_f = pbo_cscv(est.to_numpy())
print(f"Particiones: {len(logits)}; PBO = {pbo:.3f}")
print(f"Sharpe de la elegida: dentro {sh_d.mean():.2f}, "
      f"fuera {sh_f.mean():.2f}; "
      f"P(fuera < 0) = {(sh_f < 0).mean():.2f}")
OUT [06]PBO por CSCV, desde cero
Particiones: 12870; PBO = 0.398
Sharpe de la elegida: dentro 2.36, fuera 0.14; P(fuera < 0) = 0.37
Fig. — Distribución del logit del rango fuera de muestra de la variante elegida en las 12.870 particiones de la CSCV (S = 16): 1.000 estrategias sintéticas arriba, 8 lookbacks de momentum de futuros abajo

El PBO de las 1.000 estrategias es 0,40: en cuatro de cada diez particiones, la mejor dentro de muestra cae en la mitad mala fuera. El Sharpe medio de la elegida pasa de 2,36 dentro a 0,14 fuera (la degradación), y en algo más de un tercio de las particiones pierde dinero fuera. Sin las cinco estrategias con ventaja, el PBO se acerca a 0,5:

IN [07]python
solo_ruido = est[ruido].to_numpy()
pbo_r, _, d_r, f_r = pbo_cscv(solo_ruido)
print(f"995 estrategias sin ventaja: PBO = {pbo_r:.3f}; "
      f"Sharpe dentro {d_r.mean():.2f}, fuera {f_r.mean():.2f}")
OUT [07]Solo ruido
995 estrategias sin ventaja: PBO = 0.455; Sharpe dentro 2.31, fuera 0.05

Las cinco buenas bajan el PBO solo unos seis puntos porque, entre mil, la mejor dentro de muestra suele ser ruido: es la misma conclusión que el DSR, por otro camino. La figura enseña, arriba, los logits de las 12.870 particiones de la matriz completa: una campana centrada algo por encima de 0, con una cola larga a la izquierda y el 40 % de la masa por debajo de 0, que es lo que mide el PBO. Con una elección que acertara, la campana estaría desplazada a la derecha. El panel de abajo es el caso de la sección siguiente.

Leer el PBO con cuidado

El PBO responde a una pregunta concreta: ¿elegir el mejor dentro de muestra da algo mejor que la mediana fuera? No dice si la mediana gana dinero. Las ocho variantes de momentum de futuros de la lección 2.5.2 lo enseñan:

IN [08]python
fut = pd.read_parquet("futuros2_continuos.parquet")
precio = fut.pivot(index="fecha", columns="mercado",
                   values="cierre_ajustado")
rf = precio.pct_change(fill_method=None)
vol = rf.ewm(span=60, min_periods=60).std() * np.sqrt(252)
mom = {}
for n in (10, 21, 42, 63, 126, 189, 252, 378):
    senal = np.sign(precio.pct_change(n, fill_method=None))
    peso = (senal * 0.40 / vol / precio.shape[1]).shift(1)
    mom[f"mom{n}"] = (peso * rf).sum(axis=1, min_count=1)
mom = pd.DataFrame(mom).loc["2002":]
mezcla = pd.concat([mom, (-mom).add_prefix("rev_")], axis=1)

filas = {}
for nombre, m in (("8 de momentum", mom),
                  ("8 + 8 de reversión", mezcla)):
    p, _, d, f = pbo_cscv(m.to_numpy())
    filas[nombre] = {"PBO": p, "dentro": d.mean(), "fuera": f.mean(),
                     "P(fuera < 0)": (f < 0).mean()}
pd.DataFrame(filas).T.round(3)
OUT [08]PBO de ocho variantes buenas y de dieciséis mezcladas
                      PBO  dentro  fuera  P(fuera < 0)
8 de momentum       0.127   1.074  0.928         0.002
8 + 8 de reversión  0.002   1.074  0.928         0.002

Con ocho variantes de momentum, todas con ventaja y muy correlacionadas, el PBO es 0,13: en la mayoría de las particiones la elegida queda también en la mitad buena fuera de muestra. La elección acierta porque en estos datos hay un parámetro verdadero (252) con un pico claro (lección 2.5.2) y sus vecinos, 189 y 378, también son buenos. La degradación es pequeña, de 1,07 a 0,93, y la elegida pierde fuera de muestra en el 0,2 % de las particiones. Es el panel de abajo de la figura de los logits: solo hay ocho valores posibles del rango, y más de la mitad de las particiones caen en el más alto.

Ahora se añaden ocho variantes de reversión (las mismas con el signo cambiado, todas perdedoras). El PBO baja a 0,002, pero la estrategia elegida es la misma y su Sharpe fuera de muestra también: la elección «acierta» más porque descartar perdedoras evidentes es fácil. El PBO de un conjunto de variantes depende de qué variantes se metan en él. Con variantes buenas y casi intercambiables, el caso contrario, el PBO subiría hacia 0,5 aunque la familia ganara fuera de muestra: cuál queda primera sería azar, y la elección no añadiría nada, pero tampoco haría daño.

SituaciónPBODegradaciónP(pérdida fuera)Lectura
Mil intentos, casi todos ruido0,402,36 a 0,140,37Sobreajuste: la elección es casi azar y el Sharpe dentro, ilusorio
Variantes buenas con un pico claro0,131,07 a 0,930,002La elección acierta y la familia tiene ventaja
Las mismas mezcladas con perdedoras claras0,0021,07 a 0,930,002PBO más bajo por construcción del conjunto, no por mérito
Variantes buenas e intercambiablesCerca de 0,5PequeñaBajaElección irrelevante; lo que funciona es la familia

La regla: el PBO, la degradación y la probabilidad de pérdida se leen juntos, y el conjunto de variantes se fija antes de mirar. Un PBO bajo puede fabricarse añadiendo variantes malas; un PBO alto con pérdidas raras dice que lo que funciona es la familia, no el parámetro.

Qué registrar y cómo informar

Las tres herramientas necesitan datos que solo existen si se guardaron durante la investigación (lección 2.2.4):

HerramientaQué necesitaQué informar
PSRLa serie de rendimientos de la estrategiaPSR(0) y, si se quiere, PSR frente a un Sharpe mínimo útil
DSREl número N de intentos y la dispersión de sus SharpesDSR con el N declarado y con un N prudente
PBOLa matriz T × N de rendimientos de todos los intentosPBO, degradación y probabilidad de pérdida, con S

Tres limitaciones a tener presentes. El DSR depende de N, y N es difícil de contar con honestidad: incluye las ideas descartadas a medias, las variantes probadas por colegas y las de la literatura que inspiraron la estrategia. La aproximación del máximo esperado supone intentos independientes; con intentos correlacionados es conservadora. Y el PBO, como la CPCV, mezcla dentro y fuera sin respetar la flecha del tiempo: supone que el proceso es estable a lo largo de la muestra.

Ejercicios

  1. Calcula el PSR de e0518 frente a un umbral de Sharpe anual de 1 (un mínimo útil, no 0). ¿Qué probabilidad hay de que su Sharpe verdadero supere 1?
Solución
IN [09]python
umbral = 1 / np.sqrt(252)      # a frecuencia diaria
p1 = psr(sr["e0518"], umbral, T, asim["e0518"], curt["e0518"])
print(f"PSR(1 anual) de e0518: {p1:.3f}")
OUT [09]PSR frente a un Sharpe anual de 1
PSR(1 anual) de e0518: 0.877

Frente a 1 anual, la probabilidad baja de 0,999 a 0,88: un Sharpe medido de 1,58 en cuatro años deja una incertidumbre de ±0,5 anual por error típico, y el 1 queda a poco más de un error típico. Su Sharpe verdadero es 1,5, así que en este caso la respuesta correcta es «sí lo supera», pero los datos solo lo dicen con una probabilidad moderada. Contrastar frente a 0 responde a si hay alguna ventaja; frente a un mínimo útil, a si compensa operarla.

  1. Repite el PBO de las 1.000 estrategias con S = 8 y S = 12 bloques. ¿Es estable el resultado?
Solución
IN [10]python
for s in (8, 12, 16):
    p, lg, _, f = pbo_cscv(est.to_numpy(), s=s)
    print(f"S = {s:>2}: {len(lg):>5} particiones, PBO = {p:.3f}, "
          f"P(fuera < 0) = {(f < 0).mean():.2f}")
OUT [10]PBO con otros números de bloques
S =  8:    70 particiones, PBO = 0.371, P(fuera < 0) = 0.36
S = 12:   924 particiones, PBO = 0.425, P(fuera < 0) = 0.39
S = 16: 12870 particiones, PBO = 0.398, P(fuera < 0) = 0.37

El PBO se mueve unos puntos con S, porque cambian el tamaño de los bloques y el número de particiones, pero la conclusión no: en todos los casos la elegida queda en la mitad mala fuera de muestra en una proporción grande de las particiones (de 0,37 a 0,43). S se fija antes de mirar y se informa junto con el resultado.

  1. Un fondo te presenta una estrategia con Sharpe 2,1 en seis años de datos diarios y dice que es «la única que probaron». Su equipo tiene cuatro investigadores que llevan dos años trabajando en variantes. ¿Qué N usarías para el DSR y qué información pedirías?
Solución

«La única que probaron» casi nunca es cierto en un equipo que lleva dos años investigando: cada investigador habrá probado decenas de variantes (horizontes, filtros, universos, costes). Usaría un N prudente, del orden de cientos, y calcularía el DSR con varios valores para ver si la conclusión depende de él. Pediría el registro de experimentos (fechas, variantes y resultados, también las descartadas), la serie diaria de la estrategia para estimar su asimetría y su curtosis, y, si existe, la matriz de rendimientos de las variantes para calcular el PBO. Si no hay registro, la falta de información es en sí un dato: el Sharpe no se puede deflactar y debe tratarse con mucha cautela.

Respuesta plegada en cada pregunta

Autoevaluación

  1. La estrategia e0518 tiene un Sharpe anual de 1,58 en 1.003 sesiones y un PSR(0) de 0,999. ¿Por qué su Deflated Sharpe con N = 1.000 intentos baja a 0,50?

    • APorque su curtosis es alta
    • BPorque con 1.000 intentos sin ventaja, el máximo esperado del Sharpe ronda 1,58 anual: superar a cero no basta, hay que superar al mejor del ruido
    • CPorque 1.003 sesiones son pocas para cualquier contraste
    • DPorque el DSR solo vale para estrategias de ruido
    Ver respuesta

    Respuesta B. Porque con 1.000 intentos sin ventaja, el máximo esperado del Sharpe ronda 1,58 anual: superar a cero no basta, hay que superar al mejor del ruido

    El DSR es el PSR con el umbral SR* en el Sharpe máximo esperado de N candidatos sin ventaja. Con la dispersión medida de los 1.000 Sharpes (≈ 0,49 anual), ese máximo es 1,58: e0518 queda justo en él.

  2. ¿Qué entra en el denominador del PSR y por qué?

    • ALa volatilidad anual, para anualizar
    • BLa asimetría y la curtosis: con colas gruesas o asimetría negativa, el Sharpe estimado es más incierto y hace falta más evidencia
    • CEl número de estrategias probadas
    • DEl tipo libre de riesgo
    Ver respuesta

    Respuesta B. La asimetría y la curtosis: con colas gruesas o asimetría negativa, el Sharpe estimado es más incierto y hace falta más evidencia

    El error típico del Sharpe estimado crece con la curtosis y con la asimetría negativa: es la expresión que usan Bailey y López de Prado en el PSR. El número de intentos entra en el DSR a través del umbral, no en el denominador.

  3. En la CSCV sobre las 1.000 estrategias, el PBO es 0,40. ¿Qué significa?

    • AQue el 40 % de las estrategias están sobreajustadas
    • BQue en el 40 % de las particiones, la estrategia mejor dentro de muestra queda por debajo de la mediana fuera de muestra
    • CQue la estrategia elegida pierde el 40 % del Sharpe
    • DQue hay un 40 % de probabilidad de ganar dinero
    Ver respuesta

    Respuesta B. Que en el 40 % de las particiones, la estrategia mejor dentro de muestra queda por debajo de la mediana fuera de muestra

    El PBO es la frecuencia con que el logit del rango fuera de muestra de la elegida es ≤ 0, es decir, con que la elegida queda en la mitad mala. Con puro ruido sería ≈ 0,5; las cinco con ventaja lo bajan un poco.

  4. Ocho variantes de momentum de futuros dan un PBO de 0,13. Añadiendo sus ocho inversas (reversión, todas perdedoras), el PBO baja a 0,002, con la misma elegida y el mismo Sharpe fuera de muestra (0,93). ¿Qué se concluye?

    • AQue la versión con dieciséis variantes es mejor estrategia
    • BQue el PBO depende del conjunto de variantes: añadir perdedoras evidentes lo baja sin mejorar nada. Se lee con la degradación y la probabilidad de pérdida, y el conjunto se fija antes de mirar
    • CQue el PBO tiene un error de cálculo
    • DQue las variantes de reversión tienen ventaja
    Ver respuesta

    Respuesta B. Que el PBO depende del conjunto de variantes: añadir perdedoras evidentes lo baja sin mejorar nada. Se lee con la degradación y la probabilidad de pérdida, y el conjunto se fija antes de mirar

    El PBO mide si el proceso de elección acierta el orden, no si las variantes ganan. Descartar perdedoras evidentes es fácil, así que añadirlas «mejora» el PBO sin cambiar la estrategia elegida ni su resultado: por eso no se puede leer solo.

  5. ¿Qué hay que guardar durante la investigación para poder calcular el DSR y el PBO al final?

    • ASolo la mejor estrategia
    • BEl número de variantes probadas y la serie de rendimientos de cada una, también de las que se descartaron
    • CSolo el Sharpe de cada variante
    • DNada: se calculan con la estrategia final
    Ver respuesta

    Respuesta B. El número de variantes probadas y la serie de rendimientos de cada una, también de las que se descartaron

    El DSR necesita N y la dispersión de los Sharpes de los intentos; el PBO, la matriz completa T × N de rendimientos. Si solo se guarda la ganadora, la corrección es imposible (lección 2.2.4).

Ideas clave

  • El PSR convierte un Sharpe en una probabilidad de que el verdadero supere un umbral, teniendo en cuenta la longitud de la serie, la asimetría y la curtosis.
  • El DSR es el PSR con el umbral en el Sharpe máximo esperado de N intentos sin ventaja. Con los 1.000 intentos de ruido2, ese máximo es 1,58 anual y ninguna estrategia lo supera con un 95 %.
  • El mejor ruido (e0598, Sharpe 1,50) y la mejor con ventaja (e0518, 1,58) tienen DSR de 0,44 y 0,50: con estos datos son indistinguibles. Declarando 7 intentos o menos, e0518 pasaría el 95 %.
  • El PBO por CSCV cuenta con qué frecuencia la mejor dentro de muestra cae en la mitad mala fuera: 0,40 en ruido2, con un Sharpe de la elegida que pasa de 2,36 dentro a 0,14 fuera.
  • El PBO se lee con la degradación y la probabilidad de pérdida, y el conjunto de variantes se fija antes: añadir ocho perdedoras evidentes baja el PBO del momentum de futuros de 0,13 a 0,002 sin cambiar nada.
  • Sin el registro de todos los intentos (N y sus rendimientos) no hay corrección posible.

Recursos

Documentación