Lección 5.1.3 · 65 min

Métricas económicas para modelos de trading: más allá del acierto

Un modelo de trading no se juzga por cuántas veces acierta, sino por el dinero que deja la cartera que se construye con él, tras costes. En el panel del nivel, la señal con peor acierto es la que más gana neta, y un LightGBM con un AUC por encima de 0,5 da probabilidades peores que una moneda. Esta lección mide cada métrica sobre las mismas señales y enseña cuál usar para cada decisión.

Fig. — Acierto frente a Sharpe neto (10 pb por lado) de seis señales en el panel, 2019-2025: el orden de una métrica no es el de la otra
Lecciones del nivel 5
  1. 5.1 · Fundamentos de ML aplicados a finanzas

    1. 5.1.1 Por qué el machine learning financiero es distinto
    2. 5.1.2 Aprendizaje supervisado, no supervisado y por refuerzo; pipelines de scikit-learn
    3. 5.1.3 Métricas económicas para modelos de trading: más allá del acierto
  2. 5.2 · Ingeniería de características

    1. 5.2.1 Features de precio, volumen y microestructura
    2. 5.2.2 Fundamentales point-in-time, macro y datos alternativos
    3. 5.2.3 Diferenciación fraccional para features
    4. 5.2.4 Normalización sin leakage y rank transversal
    5. 5.2.5 Importancia de features: MDI, MDA, SFI y SHAP
  3. 5.3 · Etiquetado y muestreo

    1. 5.3.1 Etiquetado de horizonte fijo y sus problemas
    2. 5.3.2 Método de la triple barrera: etiquetas que imitan una operación
    3. 5.3.3 Meta-labeling: un modelo para el lado y otro para el tamaño
    4. 5.3.4 Unicidad de las etiquetas, pesos por solapamiento y bootstrap secuencial
    5. 5.3.5 Muestreo por eventos: el filtro CUSUM simétrico
  4. 5.4 · Validación para series financieras

    1. 5.4.1 Por qué falla el k-fold aleatorio en datos financieros
    2. 5.4.2 Purged k-fold con embargo y CPCV para modelos de ML
    3. 5.4.3 Walk-forward con reentrenamiento: ventanas y frecuencia
    4. 5.4.4 Backtest de señales de ML con costes y Deflated Sharpe
  5. 5.5 · Modelos clásicos

    1. 5.5.1 Regresiones regularizadas: Ridge, Lasso, Elastic Net y logística
    2. 5.5.2 Árboles de decisión, Random Forest y bagging
    3. 5.5.3 Gradient boosting: XGBoost, LightGBM y CatBoost
    4. 5.5.4 Optuna y el riesgo de sobreajustar la validación
    5. 5.5.5 Aprendizaje no supervisado: PCA, clustering y autoencoders
    6. 5.5.6 Learning to rank para la selección de acciones
  6. 5.6 · Deep learning con Keras 3

    1. 5.6.1 Keras 3: un modelo, varios motores de cálculo
    2. 5.6.2 Un MLP sobre un panel de acciones: regularizar y comparar
    3. 5.6.3 CNN 1D, LSTM y GRU: ventanas, escalado y fugas
    4. 5.6.4 Callbacks, una pérdida de Sharpe y el modelo en producción
  7. 5.7 · Deep learning con PyTorch

    1. 5.7.1 PyTorch: tensores, autograd y el bucle de entrenamiento
    2. 5.7.2 Arquitecturas de series: TCN, N-BEATS, PatchTST e iTransformer
    3. 5.7.3 Modelos probabilísticos: pérdida cuantílica, DeepAR e intervalos
    4. 5.7.4 Redes de grafos para relaciones entre activos
    5. 5.7.5 Optimización de carteras end-to-end: capas diferenciables y pérdida de Sharpe
  8. 5.8 · Modelos fundacionales de series temporales

    1. 5.8.1 Modelos fundacionales de series: preentrenar una vez, prever sin entrenar
    2. 5.8.2 Las familias de modelos fundacionales: arquitectura, datos y licencia
    3. 5.8.3 Uso práctico: contexto, cuantiles, covariables y ajuste fino
    4. 5.8.4 Modelos fundacionales en finanzas: qué dice la evidencia
    5. 5.8.5 Laboratorio: modelos fundacionales frente a GARCH, HAR y LightGBM
  9. 5.9 · Aprendizaje por refuerzo

    1. 5.9.1 MDP, Q-learning, PPO y entornos Gymnasium
    2. 5.9.2 RL para ejecución, market making y cobertura dinámica
    3. 5.9.3 Por qué el RL sobreajusta en trading direccional
  10. 5.10 · Interpretabilidad, robustez y riesgo de modelo

    1. 5.10.1 SHAP, dependencia parcial y estabilidad de las importancias
    2. 5.10.2 Deriva de datos y de concepto: detectarla y qué hacer
    3. 5.10.3 Ensembles, combinación de señales y datos sintéticos

La pregunta que contesta cada métrica

Las métricas habituales del ML contestan preguntas de estadística: ¿cuántas veces acierta la clase?, ¿cuánto se equivoca en media al cuadrado?, ¿ordena bien positivos y negativos? Un sistema de trading hace otra pregunta: ¿cuánto dinero deja la cartera que se construye con estas predicciones, después de pagar por construirla? Las dos familias de preguntas no ordenan los modelos igual, y el resto de la lección lo mide con seis señales sobre el mismo panel y el mismo periodo.

MétricaQué mideQué ignora
AciertoFracción de signos (o clases) correctosMagnitudes, clase mayoritaria, costes
AUCProbabilidad de ordenar bien un positivo frente a un negativoMagnitudes, escala, costes
R², error cuadráticoError de la predicción en sus unidadesQue para ordenar solo cuenta el orden
IC, ICIRCalidad del orden transversal y su estabilidadCostes y rotación
Sharpe de la señal, netoRendimiento por unidad de riesgo de la cartera tras costesCapacidad, colas (se miran aparte)
Brier, log loss, fiabilidadSi las probabilidades significan lo que dicenEl orden (un modelo calibrado puede no ordenar nada)

El acierto engaña: la clase mayoritaria

El primer problema del acierto es su referencia. Los rendimientos diarios del activo indice de vol5_diario tienen deriva positiva y, por construcción, son impredecibles: su media condicional es constante (el README del nivel lo usa como control). Un clasificador que siempre dice «sube»:

IN [01]python
import numpy as np
import pandas as pd
from sklearn.metrics import accuracy_score, balanced_accuracy_score

v = pd.read_parquet("vol5_diario.parquet")
ind = v[(v["activo"] == "indice") & (v["fecha"] >= "2018-01-01")]
sube = (ind["rendimiento"] > 0).astype(int)
siempre = np.ones(len(sube), dtype=int)
print(f"Acierto: {accuracy_score(sube, siempre):.1%}")
print(f"Acierto equilibrado: "
      f"{balanced_accuracy_score(sube, siempre):.1%}")
OUT [01]Siempre «sube»: acierto y acierto equilibrado
Acierto: 56.6%
Acierto equilibrado: 50.0%

Un 56,6 % de acierto sin ninguna información: es la frecuencia de días al alza. Cualquier clasificador direccional se compara con esa cifra, no con el 50 %. El acierto equilibrado (la media del acierto en cada clase) quita el efecto: un clasificador constante da exactamente 0,5. En el panel la etiqueta es «por encima de la mediana de la semana», que está equilibrada por construcción, y el problema se traslada a la magnitud y los costes.

Seis señales, seis rankings distintos

Las seis señales se evalúan en 2019-2025 sobre panel5:

  • oráculo: el rendimiento esperado verdadero (alfa_verdadero), el techo de la lección 5.1.1.
  • ridge: una ridge con las 21 features en rango, entrenada con 2012-2018 (como en la lección 5.1.1).
  • baseline: la suma de cuatro rangos con el signo de la literatura (lección 5.1.2).
  • value, ey y reversión: features sueltas (valor_bp, ey y ret_1s con el signo cambiado).
IN [02]python
from sklearn.linear_model import Ridge

f = pd.read_parquet("panel5_features.parquet")
et = pd.read_parquet("panel5_etiquetas.parquet")
ver = pd.read_parquet("panel5_verdad.parquet")
d = (f.merge(et[["fecha", "ticker", "ret_sig_semana"]],
             on=["fecha", "ticker"])
      .merge(ver[["fecha", "ticker", "alfa_verdadero"]],
             on=["fecha", "ticker"])
      .dropna(subset=["ret_sig_semana"]).reset_index(drop=True))
g = d.groupby("fecha")
d["y"] = d["ret_sig_semana"] - g["ret_sig_semana"].transform("mean")
d["arriba"] = (d["ret_sig_semana"]
               > g["ret_sig_semana"].transform("median")).astype(int)
fuera = ("fecha", "ticker", "sector", "revision_analistas")
feats = [c for c in f.columns if c not in fuera]
X = g[feats].rank(pct=True).sub(0.5).fillna(0)
ent = (d["fecha"] < "2019-01-01").to_numpy()
pru = (d["fecha"] >= "2019-01-08").to_numpy()

rk = g[["mom_12_1", "ret_1s", "valor_bp", "sue"]].rank(pct=True)
d["oraculo"] = d["alfa_verdadero"]
d["ridge"] = Ridge(alpha=10.0).fit(X[ent], d.loc[ent, "y"]).predict(X)
d["baseline"] = (rk["mom_12_1"] - rk["ret_1s"] + rk["valor_bp"]
                 + rk["sue"])
d["value"], d["ey_"], d["reversion"] = (d["valor_bp"], d["ey"],
                                        -d["ret_1s"])
senales = ["oraculo", "ridge", "baseline", "value", "ey_",
           "reversion"]
t = d[pru].reset_index(drop=True)
print(t["fecha"].nunique(), "semanas,", len(t), "filas")
OUT [02]Las seis señales de 2019-2025
364 semanas, 145600 filas

Primero, las métricas de clasificación. La predicción de cada señal se convierte en «por encima de la mediana de la semana» y se compara con la etiqueta binaria. El acierto ponderado pesa cada acierto por el tamaño del movimiento, ∣yi∣|y_i|: un modelo que acierta los movimientos grandes y falla los pequeños sale mejor parado que en el acierto simple. El AUC usa la señal continua y mide la probabilidad de que una acción de la mitad buena tenga una señal mayor que una de la mitad mala:

IN [03]python
from sklearn.metrics import roc_auc_score


def clasificacion(s, col):
    alta = s[col] > s.groupby("fecha")[col].transform("median")
    ok = alta.astype(int) == s["arriba"]
    return {"acierto": ok.mean(),
            "acierto_pond": (s["y"].abs() * ok).sum()
            / s["y"].abs().sum(),
            "auc": roc_auc_score(s["arriba"], s[col])}


pd.DataFrame({c: clasificacion(t, c) for c in senales}).T.round(4)
OUT [03]Acierto, acierto ponderado y AUC
           acierto  acierto_pond     auc
oraculo     0.5077        0.5108  0.5124
ridge       0.5061        0.5106  0.5087
baseline    0.5056        0.5086  0.5089
value       0.5041        0.5062  0.5055
ey_         0.5034        0.5051  0.5046
reversion   0.5034        0.5073  0.5052

Todas las señales están entre el 50,3 % y el 50,8 % de acierto: es la escala de la lección 5.1.1. El acierto ponderado cambia el orden: la reversión sube del 50,34 % al 50,73 % porque acierta más en los movimientos grandes (una caída fuerte de la semana anterior se corrige más), y adelanta al value y a ey. El AUC ordena casi igual que el acierto. Ninguna de las tres métricas dice nada de cuánto cuesta operar cada señal, que es lo que decide el resultado.

R² y error cuadrático: escala frente a orden

Un modelo de regresión se evalúa por defecto con el R² o el error cuadrático. Para ordenar acciones, la escala de la predicción es irrelevante; para el R², es casi todo:

IN [04]python
from sklearn.metrics import r2_score


def ic_semanal(s, col, y="y"):
    r = s.groupby("fecha")[[col, y]].rank()
    r = r - r.groupby(s["fecha"]).transform("mean")
    num = (r[col] * r[y]).groupby(s["fecha"]).sum()
    den = ((r[col] ** 2).groupby(s["fecha"]).sum()
           * (r[y] ** 2).groupby(s["fecha"]).sum()) ** 0.5
    return num / den


t["oraculo_x5"] = 5 * t["oraculo"]
for c in ["oraculo", "oraculo_x5", "ridge"]:
    print(f"{c:11s} R² {r2_score(t['y'], t[c]):+.3%}   "
          f"IC {ic_semanal(t, c).mean():.4f}")
OUT [04]El mismo orden, tres R²
oraculo     R² +0.044%   IC 0.0254
oraculo_x5  R² -2.531%   IC 0.0254
ridge       R² +0.040%   IC 0.0190

El oráculo explica un 0,044 % de la varianza de la etiqueta. Multiplicado por 5 tiene exactamente el mismo IC y produciría la misma cartera por deciles, pero su R² cae a −2,5 %: peor que predecir siempre cero. La ridge tiene un R² parecido al del oráculo y un IC menor. El R² sirve cuando la magnitud de la predicción se usa tal cual (para dimensionar, para la volatilidad de la lección 5.8.5); para elegir entre señales de ordenación, confunde.

IC, ICIR y la ley fundamental

El IC semanal mide la calidad del orden; el ICIR, su media dividida por su desviación entre semanas, mide su estabilidad. Anualizado (×52\times\sqrt{52}) es comparable a un Sharpe: si la cartera pesa cada acción en proporción a su rango, su rendimiento semanal es aproximadamente proporcional al IC de esa semana por la dispersión de los rendimientos.

La ley fundamental de la gestión activa (Grinold, 1989) da una cota del ratio de información con NN apuestas independientes por periodo:

undefined

Respuesta plegada en cada pregunta

Autoevaluación

  1. Un clasificador que predice «sube» todos los días acierta el 56,6 % de los días del índice en 2018-2025. ¿Qué vale como predictor?

    • AMucho: acierta más que un modelo del 52 %
    • BDepende del horizonte
    • CNada: es la frecuencia de días al alza (la deriva del índice); su acierto equilibrado es exactamente el 50 % y en estos datos el rendimiento es impredecible por construcción
    • DEs una buena baseline para operar
    Ver respuesta

    Respuesta C. Nada: es la frecuencia de días al alza (la deriva del índice); su acierto equilibrado es exactamente el 50 % y en estos datos el rendimiento es impredecible por construcción

    El acierto se compara con la frecuencia de la clase mayoritaria, no con el 50 %. El acierto equilibrado (media del acierto en cada clase) quita el efecto: un clasificador constante da 0,5.

  2. En 2019-2025, el value como señal suelta tiene uno de los peores aciertos de las seis señales (50,41 %) y el mejor Sharpe neto (1,01). ¿Por qué?

    • APor azar
    • BPorque rota un 10 % semanal frente a 250-340 % de las demás: su coste de equilibrio es de 140 pb por lado, y con 10 pb casi no pierde nada
    • CPorque el value tiene el mayor IC
    • DPorque el acierto está mal calculado
    Ver respuesta

    Respuesta B. Porque rota un 10 % semanal frente a 250-340 % de las demás: su coste de equilibrio es de 140 pb por lado, y con 10 pb casi no pierde nada

    El acierto no ve ni la magnitud ni la rotación. El oráculo tiene más IC y más Sharpe bruto (1,67), pero su cartera se renueva cada semana y solo aguanta 12 pb por lado; con 10 pb queda en 0,29.

  3. Multiplicar por 5 la predicción del oráculo cambia su R² fuera de muestra de +0,04 % a −2,5 %. ¿Qué pasa con su cartera larga-corta por deciles?

    • ANada: el orden de las acciones es el mismo, así que el IC y la cartera son idénticos. El R² castiga la escala, que en una cartera por rangos no importa
    • BPierde dinero
    • CGana cinco veces más
    • DSu rotación se multiplica por 5
    Ver respuesta

    Respuesta A. Nada: el orden de las acciones es el mismo, así que el IC y la cartera son idénticos. El R² castiga la escala, que en una cartera por rangos no importa

    El R² mide el error cuadrático de la predicción en sus unidades. Para ordenar acciones solo cuenta el orden; para dimensionar posiciones sí cuenta la escala, y entonces lo que se mira es la calibración.

  4. El IC semanal del oráculo es 0,025 y hay 400 acciones. La ley fundamental da un ratio de información de 0,025·√(400·52) ≈ 3,7, pero el ICIR anual medido es 1,8. ¿De dónde sale la diferencia?

    • ADe un error de cálculo
    • BDe los costes
    • CDe que el IC es de rangos
    • DDe que las 400 apuestas semanales no son independientes: comparten mercado, sectores y features. La desviación del IC entre semanas (≈ 0,1) corresponde a unas 100 apuestas independientes por semana, no a 400
    Ver respuesta

    Respuesta D. De que las 400 apuestas semanales no son independientes: comparten mercado, sectores y features. La desviación del IC entre semanas (≈ 0,1) corresponde a unas 100 apuestas independientes por semana, no a 400

    Con N apuestas independientes la desviación del IC sería ≈ 1/√N = 0,05. La medida es el doble, así que la amplitud efectiva es la cuarta parte. La amplitud de la ley fundamental es de decisiones independientes, no de activos.

  5. Un LightGBM da probabilidades de que una acción quede por encima de la mediana entre 0,31 y 0,68; en esos tramos la frecuencia observada es siempre ≈ 0,50. Si se dimensiona con Kelly (f = 2p − 1), ¿qué pasa?

    • ANada: el AUC es mayor que 0,5
    • BSe apuesta muy poco
    • CSe apuesta lo correcto
    • DSe apuesta de media un 10 % del capital por posición sin ventaja real: el modelo está sobreconfiado, su Brier y su log loss son peores que los de una moneda (0,2546 frente a 0,25)
    Ver respuesta

    Respuesta D. Se apuesta de media un 10 % del capital por posición sin ventaja real: el modelo está sobreconfiado, su Brier y su log loss son peores que los de una moneda (0,2546 frente a 0,25)

    Las probabilidades no calibradas convierten ruido en tamaño. Recalibrado con 2017-2018 (isotónica), las probabilidades se comprimen alrededor de 0,5 y el tamaño medio de Kelly baja al 0,9 %.

Ideas clave

  • El acierto se compara con la clase mayoritaria y no ve magnitudes: el acierto ponderado por |rendimiento| y el acierto equilibrado lo corrigen en parte.
  • El IC semanal (correlación de rangos) mide lo que importa para ordenar; su media dividida por su desviación, anualizada (ICIR), se parece al Sharpe bruto de la cartera larga-corta.
  • La ley fundamental IR ≈ IC·√amplitud usa apuestas independientes: con 400 acciones correlacionadas, la amplitud efectiva medida es de unas 100 por semana.
  • La métrica final es el Sharpe neto de la cartera: el oráculo pasa de 1,67 bruto a 0,29 neto con 10 pb por lado, y el value, con un acierto peor, da 1,01.
  • El coste de equilibrio (rendimiento bruto / rotación) dice cuántos pb por lado aguanta una señal; suavizarla sube el del oráculo de 12 a 23 pb y su Sharpe neto de 0,29 a 0,66.
  • Si la probabilidad decide el tamaño, se exige calibración (Brier, log loss, diagrama de fiabilidad): un modelo sobreconfiado apuesta sin ventaja.

Recursos