---
title: "2.5.4 Deflated Sharpe Ratio y probabilidad de sobreajuste"
description: "PSR, Deflated Sharpe y PBO programados desde cero y aplicados a 1.000 estrategias sintéticas: qué Sharpe sobrevive al número de intentos y a las colas."
url: "https://pythonparatrading.com/curso-python-trading/nivel-2/deflated-sharpe-ratio-y-pbo/"
lang: "es"
image: "https://pythonparatrading.com/og/curso-python-trading/nivel-2/deflated-sharpe-ratio-y-pbo.png"
---

# 2.5.4 · 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.

- Curso: [Nivel 2: Estrategias sistemáticas y backtesting riguroso](https://pythonparatrading.com/curso-python-trading/nivel-2/)
- Módulo: 2.5 · Sesgos y validación
- Duración: 70 min
- Requisitos: [2.5.1 · Sesgos de backtest: anticipación, supervivencia, selección y narrativa](https://pythonparatrading.com/curso-python-trading/nivel-2/sesgos-de-backtest/), [2.5.3 · Validación cruzada combinatoria purgada para estrategias](https://pythonparatrading.com/curso-python-trading/nivel-2/validacion-cruzada-combinatoria-purgada-cpcv/), [0.7.2 · Probabilidad y distribuciones, correlación frente a causalidad y regresión simple](https://pythonparatrading.com/curso-python-trading/nivel-0/probabilidad-distribuciones-y-regresion/)

## Al terminar esta lección

- Calcular el Probabilistic Sharpe Ratio (PSR) de una serie de rendimientos, con su asimetría, su curtosis y su longitud.
- Calcular el Deflated Sharpe Ratio (DSR): el PSR frente al máximo esperado del Sharpe de N intentos sin ventaja, y ver cómo cambia con N.
- Estimar la probabilidad de sobreajuste del backtest (PBO) con validación cruzada simétrica combinatoria (CSCV) sobre una matriz de variantes.
- Interpretar el PBO junto con la degradación y la probabilidad de pérdida fuera de muestra, y saber qué hay que registrar durante la investigación para poder calcularlos.

## 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).

```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.

<aside class="callout" data-kind="aviso">

Los datos son los de `ruido2_estrategias.parquet`: rendimientos diarios de 1.000 estrategias ficticias en las 1.003
sesiones de 2022 a 2025, en 50 familias de 20 variantes con correlación 0,5 dentro de cada familia. **Todas tienen
ventaja cero salvo cinco**, cuyo Sharpe verdadero (de 0,5 a 1,5) está en `ruido2_verdad.csv`. Son sintéticos y la
respuesta está plantada: sirven para ver qué detecta cada herramienta, no para buscar estrategias.

</aside>

## 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 $\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^*$, con $\widehat{\gamma}_3$ la asimetría y $\widehat{\gamma}_4$ la curtosis (3 en la normal) de
los rendimientos:

$$
\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.

```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")
```
```output
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.

```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)
```
```output
            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[\{\widehat{SR}_n\}]$, y la misma expresión de valores extremos de la
lección 2.5.1:

$$
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 $\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.

```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)
```
```output
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.* Siete filas ordenadas por Sharpe medido, cada una con tres puntos unidos: PSR(0), DSR con N = 50 y DSR con N = 1.000. e0518 (real 1,5): 0,999, 0,83 y 0,50. e0598 (ruido, destacada): 0,999, 0,78 y 0,44. e0133 (real 0,8): 0,998, 0,75 y 0,40. e0316 (ruido): 0,998, 0,74 y 0,37. e0080, e0751 y e0258 (reales 0,5, 0,6 y 0,7) tienen PSR de 0,97, 0,95 y 0,89 y DSR con 1.000 intentos por debajo de 0,11. Ninguna llega a 0,95 en el DSR.

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.

```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}")
```
```output
      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.

<aside class="callout" data-kind="nota">

¿Cuántos intentos «efectivos» son 1.000 estrategias en 50 familias de 20 variantes correlacionadas? Menos de 1.000 y
más de 50: las variantes de una familia no son independientes, pero tampoco idénticas. Una opción es agrupar los
intentos por correlación y contar los grupos; otra heurística sencilla es la razón de participación de los autovalores de la matriz de correlación, $(\sum \lambda)^2 / \sum \lambda^2$. En
cualquier caso, DSR(50) y DSR(1000) acotan el resultado, y ninguna de las estrategias pasa con ninguno de los dos.

</aside>

```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())
```
```output
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 $\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, $\overline{\omega}_c$ (1 si es
   la mejor de N, cerca de 0 si es la peor), y su logit, $\lambda_c = \ln\left(\overline{\omega}_c / (1 - \overline{\omega}_c)\right)$.
4. El PBO es la proporción de particiones con $\lambda_c \le 0$: la elegida queda en la mitad mala fuera.

```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.

```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}")
```
```output
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.* Dos histogramas con la línea del 0 marcada; las barras a la izquierda de 0, destacadas, son las particiones en que la elegida queda en la mitad mala fuera de muestra. Arriba, las 1.000 estrategias: campana centrada algo por encima de 0, de −6,5 a 3,5, con el 40 % a la izquierda (PBO 0,40; la elegida pierde fuera en el 37 %). Abajo, 8 variantes de momentum: 8 valores posibles que crecen hacia la derecha, con más de la mitad de las particiones (6.816) en el valor más alto, PBO 0,13, y la elegida pierde fuera solo en el 0,2 %.

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:

```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}")
```
```output
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:

```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)
```
```output
                      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ón | PBO | Degradación | P(pérdida fuera) | Lectura |
|---|---|---|---|---|
| Mil intentos, casi todos ruido | 0,40 | 2,36 a 0,14 | 0,37 | Sobreajuste: la elección es casi azar y el Sharpe dentro, ilusorio |
| Variantes buenas con un pico claro | 0,13 | 1,07 a 0,93 | 0,002 | La elección acierta y la familia tiene ventaja |
| Las mismas mezcladas con perdedoras claras | 0,002 | 1,07 a 0,93 | 0,002 | PBO más bajo por construcción del conjunto, no por mérito |
| Variantes buenas e intercambiables | Cerca de 0,5 | Pequeña | Baja | Elecció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):

| Herramienta | Qué necesita | Qué informar |
|---|---|---|
| PSR | La serie de rendimientos de la estrategia | PSR(0) y, si se quiere, PSR frente a un Sharpe mínimo útil |
| DSR | El número N de intentos y la dispersión de sus Sharpes | DSR con el N declarado y con un N prudente |
| PBO | La matriz T × N de rendimientos de todos los intentos | PBO, 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.

<aside class="callout" data-kind="riesgo">

Ninguna de estas correcciones arregla un backtest con sesgos (lección 2.5.1). Si la estrategia ejecuta en la misma
barra o usa un universo de supervivientes, su Sharpe está inflado antes de cualquier selección, y el DSR solo descuenta
la parte que viene de elegir entre intentos.

</aside>

## 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.**

```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}")
```
```output
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.

2. Repite el PBO de las 1.000 estrategias con S = 8 y S = 12 bloques. ¿Es estable el resultado?

**Solución.**

```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}")
```
```output
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.

3. 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.

## 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?

   - A. Porque su curtosis es alta
   - 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
   - C. Porque 1.003 sesiones son pocas para cualquier contraste
   - D. Porque el DSR solo vale para estrategias de ruido

   *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é?

   - A. La volatilidad anual, para anualizar
   - 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
   - C. El número de estrategias probadas
   - D. El tipo libre de riesgo

   *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?

   - A. Que el 40 % de las estrategias están sobreajustadas
   - B. Que en el 40 % de las particiones, la estrategia mejor dentro de muestra queda por debajo de la mediana fuera de muestra
   - C. Que la estrategia elegida pierde el 40 % del Sharpe
   - D. Que hay un 40 % de probabilidad de ganar dinero

   *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?

   - A. Que la versión con dieciséis variantes es mejor estrategia
   - 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
   - C. Que el PBO tiene un error de cálculo
   - D. Que las variantes de reversión tienen ventaja

   *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?

   - A. Solo la mejor estrategia
   - B. El número de variantes probadas y la serie de rendimientos de cada una, también de las que se descartaron
   - C. Solo el Sharpe de cada variante
   - D. Nada: se calculan con la estrategia final

   *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

- [SciPy: scipy.stats.norm](https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.norm.html) · docs.scipy.org

### Libros

- [Bailey, D. y López de Prado, M. (2014): The Deflated Sharpe Ratio. Journal of Portfolio Management 40(5), 94-107](https://doi.org/10.3905/jpm.2014.40.5.094) · doi.org
- [Bailey, D. y López de Prado, M. (2012): The Sharpe Ratio Efficient Frontier. Journal of Risk 15(2), 3-44](https://doi.org/10.21314/JOR.2012.255) · doi.org
- [Bailey, Borwein, López de Prado y Zhu (2016): The Probability of Backtest Overfitting. Journal of Computational Finance](https://doi.org/10.21314/JCF.2016.322) · doi.org
- [Lo, A. (2002): The Statistics of Sharpe Ratios. Financial Analysts Journal 58(4), 36-52](https://doi.org/10.2469/faj.v58.n4.2453) · doi.org
- [López de Prado, M. (2018): Advances in Financial Machine Learning. Wiley (capítulo 14: PSR y DSR)](https://www.wiley.com/en-us/Advances+in+Financial+Machine+Learning-p-9781119482086) · wiley.com

### Datos

- [Datos del nivel 2: 1.000 estrategias de ruido y cinco con ventaja (Parquet)](https://pythonparatrading.com/curso/datos/nivel-2/ruido2_estrategias.parquet) · Descarga · ruido2_estrategias.parquet

Lección anterior: [2.5.3 · Validación cruzada combinatoria purgada para estrategias](https://pythonparatrading.com/curso-python-trading/nivel-2/validacion-cruzada-combinatoria-purgada-cpcv/)

Lección siguiente: [2.5.5 · Monte Carlo: remuestreo de trades, bootstrap de bloques y permutaciones de señales](https://pythonparatrading.com/curso-python-trading/nivel-2/monte-carlo-bootstrap-y-permutaciones/)
