Dónde queda tu resultado después de barajar los retornos unos miles de veces, y qué no responde ese número.
El backtest termina y el Sharpe se ve decente. Pero la pregunta que tienes en la cabeza sigue sin respuesta: ¿la estrategia captó algo de verdad, o simplemente diste unos cuantos tajos al azar dentro de un tramo alcista? Una forma de responderla es barajar los datos unos miles de veces y ver en qué puesto queda tu resultado dentro de ese montón de ruido — que es exactamente lo que hace la fila «Valor p de MCPT» en la pestaña Backtest del espacio de trabajo. Este artículo cuenta qué contrasta, cómo se lee y qué pregunta sigue sin responder incluso después de aprobar.
MCPT (Monte Carlo Permutation Test, prueba de permutación de Monte Carlo) es un contraste estadístico: reordena al azar muchísimas veces la serie de retornos del período de backtest, recalculando el Sharpe cada vez sobre el mismo conjunto de posiciones de entrada y salida, para construir toda una distribución de «qué aspecto tendría la pura suerte», y luego mira en qué punto de esa distribución cae tu resultado real.
| Elemento | Contenido |
|---|---|
| Hipótesis nula | Los períodos de retorno que eligió esta estrategia no son mejores que unos elegidos al azar |
| Definición del valor p | La proporción de Sharpes barajados que son mayores o iguales que el Sharpe real |
| Lectura | p < 0.05 → Hay una ventaja estadísticamente significativa al nivel de confianza del 95% |
| Alcance del contraste | Todos los datos del backtest, sin división entre entrenamiento y prueba |
Cuanto más pequeño es el valor p, más raro resulta que «barajando a lo tonto también te ganen». Con las 2000 permutaciones por defecto, p = 0.05 significa que en esas 2000 veces hubo 100 resultados aleatorios que no quedaron por debajo del tuyo; p = 0.005 significa que solo hubo 10.
Este es el punto más crítico de todo el diseño, y también el que más se malinterpreta: lo que se baraja es la serie de retornos futuros, mientras que tu serie de posiciones queda fija de principio a fin.
Lo que hace cada permutación: position(tus posiciones) ← fijo, se calcula una sola vez fuera del bucle × vol_scalar(escalado de posición) ← fijo, se calcula una sola vez fuera del bucle − fee_cost(comisiones) ← fijo, se calcula una sola vez fuera del bucle × serie de retornos barajada ← el único término que se vuelve a sortear cada vez = Sharpe de esta permutación
Como las comisiones y el escalado de posición se calculan fuera del bucle, cada permutación soporta el mismo coste de transacción y el mismo apalancamiento. La única variable que queda es el orden en que aparecen los retornos — es decir, ¿son los momentos que elegiste mejores que unos momentos elegidos al azar?
Porque eso sería regalar el resultado. Barajar un array binario de posiciones genera muchísimos más cambios de entrada y salida que los que hace la propia estrategia; con fee = 0.0005, cada permutación cargaría aproximadamente 30 a 40 veces el lastre de comisiones, y todos los Sharpes barajados quedarían empujados a terreno profundamente negativo. Tenga o no tu estrategia una ventaja real, el valor p saldría bonito y sin ningún sentido.
Es automático, no opcional. Se ejecuta una vez en cada backtest de una estrategia Tipo A, y el resultado se escribe directamente en las estadísticas del backtest y se muestra en la pestaña Backtest del espacio de trabajo.
| Ajuste | Por defecto | Nota |
|---|---|---|
| Permutaciones | 2000 | Se puede sobrescribir con MCPT_N en la estrategia, pero sigue sujeto a la fórmula de presupuesto de abajo |
| Semilla aleatoria | 42 | Un generador privado que no toca la semilla global — el mismo backtest siempre da el mismo valor p |
| Comisión | El FEE de la propia estrategia | Se pasa lo mismo que use el backtest |
| Apagarlo | MCPT = False | Se salta entero y no escribe ningún campo de MCPT |
Dos comportamientos que conviene recordar: durante un barrido de parámetros no se ejecuta MCPT (un barrido son decenas o cientos de backtests, y añadirlo lo volvería inservible de lento), así que el valor p que ves viene siempre del backtest que se corrió una vez adoptados los parámetros; y una vez que la estrategia está en marcha, cada disparo en vivo o programado arrastra los mismos campos de MCPT tal cual — mismo código, mismos parámetros, así que el valor p sigue en pie, y por eso una estrategia en marcha lo sigue mostrando siempre.
La pestaña Backtest del espacio de trabajo no dictamina si pasa o no; solo muestra el número y añade una línea de explicación. Cuando p < 0.05 dice:
Cuando no pasa, dice:
El «pasa o no pasa» de verdad aparece en los tres filtros de calidad de la Biblioteca de estrategias. El filtro 2 se llama «Estadísticamente significativa» y su descripción dice «Prueba de permutación MCPT p < 0.05», mientras que el veredicto real exige dos condiciones a la vez:
| Condición | Umbral |
|---|---|
| Valor p | < 0.05 |
| Permutaciones | ≥ 1000 |
| Estrategia de cartera (Tipo C) | Muestra «MCPT no aplica (estrategia de cartera)»; no cuenta como fallo |
Solo cuando los tres filtros se superan o no aplican lleva la estrategia la insignia «Verificada». Dicho claramente, el reparto es este: tu máquina solo se encarga de calcular el valor p y el número de permutaciones; si eso cuenta como aprobado lo decide el lado de la publicación.
Toma el ejemplo del tutorial btc_sma_cross que viene con el espacio de trabajo y ejecútalo una vez (BTCUSDT 1h, desde 2022-01-01, SMA_FAST = 45 / SMA_SLOW = 100, sin tocar ni una letra de los parámetros, 41,287 velas). Todos los números de abajo vienen de esa única ejecución del 2026-09-17.
| Backtest | Valor |
|---|---|
| Rentabilidad total | +123.95% |
| Referencia (comprar y mantener) | +64.36% |
| Caída máxima | −44.93% |
| Sharpe Ratio | 0.6751 |
| Operaciones | 478 |
| Comisiones pagadas (sobre el capital) | 23.90% |
| MCPT | Valor |
|---|---|
| Valor p | 0.0160 |
| Permutaciones | 2000 |
| Línea roja del histograma, «Sharpe real» | 0.8985 |
| Rango de la distribución | −0.8565 ~ 1.4218 |
La línea que el propio backtest imprime por stdout es esta:
MCPT p-value: 0.0160 (n=2000, significant edge at 95%)
Cómo leerlo: p = 0.0160 significa que de 2000 mezclas aleatorias hubo 32 cuyo Sharpe no quedó por debajo del suyo — dicho de otro modo, sobre este tramo de historia estos momentos de entrada y salida no parecen elegidos a lo tonto. Las 2000 permutaciones también están por encima de las 1000 que exige el filtro, así que este apartado está aprobado.
Esta es la sección más importante del artículo. Esa misma estrategia, el mismo día y con el mismo código, pasó además por una validación fuera de muestra walk-forward:
| Contraste | La pregunta que plantea | La ejecución del 2026-09-17 | Resultado |
|---|---|---|---|
| MCPT | Sobre esta serie fija de posiciones, ¿se puede distinguir este resultado de la suerte? | p = 0.0160(n = 2000) | Aprobado |
| Walk-forward | El hecho mismo de elegir parámetros a partir del histórico, ¿sigue sirviendo en el tramo siguiente? | Eficiencia fuera de muestra −0.334(Sharpe fuera de muestra −0.45) | Muy por debajo del umbral |
Uno aprueba, el otro no, y ninguno de los dos está mal calculado — porque sencillamente no responden a la misma pregunta. MCPT contrasta que «este conjunto de entradas y salidas ya decidido, puesto sobre este tramo de historia, no parece adivinado»; walk-forward contrasta si «elegir parámetros a partir del histórico sigue sosteniéndose al pasar al tramo siguiente, que no ha visto». Aprobar lo primero no implica lo segundo.
Esto no es decir que la estrategia esté rota — es el ejemplo del tutorial que viene con el espacio de trabajo, y lo que importa aquí es la diferencia de significado entre los dos contrastes. Para los números completos del walk-forward y cómo leerlos, mira Cómo funciona la validación fuera de muestra.
Si le pides al agente que dibuje el histograma de MCPT y lo mande al chat, en la leyenda de ese gráfico aparecerá impresa una línea:
Actual OOS Sharpe = ⟨tu número⟩
OOS es la abreviatura de out-of-sample (fuera de muestra). Esa línea es una etiqueta que quedó de un comentario antiguo; no la entiendas al pie de la letra. MCPT corre de principio a fin sobre todos los datos del backtest, sin ninguna ventana de entrenamiento, ninguna ventana de prueba ni ninguna división por proporción — no puede ser una cifra fuera de muestra, y la tabla comparativa de arriba es la prueba.
El gráfico de la pestaña Backtest del espacio de trabajo no tiene este problema: su línea roja está etiquetada como «Sharpe real». Además, el gráfico del chat se genera con una reejecución manual, y una reejecución manual no usa necesariamente los mismos parámetros que la automática, así que los números del gráfico tampoco tienen por qué coincidir con esa fila de la pestaña.
Cuántas veces corre realmente el MCPT automático no depende del todo de ti. Hay una fórmula de presupuesto de ejecución:
permutaciones reales = min( MCPT_N, 20000, max( 200, 4e8 ÷ número de velas ) )
Cuantas más velas, más pequeño se vuelve 4e8 ÷ número de velas. La ejecución de arriba tenía 41,287 velas, muy lejos del techo, así que no se recortó ni una de las 2000. Pero la comparativa que recoge la documentación oficial dice: 40,000 velas → 2000; 200,000 velas (dos años de 5 minutos) → 2000; 1,000,000 de velas (dos años de 1 minuto) → 400.
El problema es que el filtro de publicación corta en permutaciones ≥ 1000. Despejando la fórmula, en cuanto el número de velas supera las 400,000 aproximadamente, las permutaciones reales caen por debajo de 1000 — y el filtro te suspende aunque tengas p = 0.001. Y en pantalla no hay el menor indicio: el aviso del recorte solo se escribe en el log de la máquina, el texto explicativo del espacio de trabajo inserta tan tranquilo el número ya recortado, y no hay ningún estilo de advertencia.
Vuelve a mirar esas dos tablas: para el mismo backtest, la tarjeta de Sharpe Ratio pone 0.6751 y el «Sharpe real» del histograma pone 0.8985, una diferencia de 0.22 que se ve a simple vista. No es un bug, son dos formas de cálculo distintas:
| Elemento | El Sharpe interno de MCPT(0.8985) | El Sharpe Ratio de la pestaña Backtest(0.6751) |
|---|---|---|
| Cómo se calculan los retornos | Retornos simples, sin separar el tramo de apertura del de cierre | El tramo nocturno y el intradía se valoran por separado |
| Escalado de posición | Siempre se aplica:30% de volatilidad objetivo、2 de tope de apalancamiento | Solo si la propia estrategia lo escribió |
La clave está en la segunda fila: el MCPT automático no le pasa el ajuste de volatilidad objetivo de la propia estrategia, usa siempre los valores por defecto de la función. btc_sma_cross no hace objetivo de volatilidad, pero su Sharpe de MCPT sigue siendo el número «después de aplicar un 30% de volatilidad objetivo y un tope de 2×» (para qué hace la volatilidad objetivo, mira Cómo funciona el objetivo de volatilidad). Que los dos números no coincidan es normal; hoy por hoy la interfaz no explica esto.
Cuando falla lo hace en silencio: ningún mensaje de error, el backtest termina bien como siempre, y en el front simplemente falta esa fila. Hay al menos cuatro causas, y la pantalla no las distingue:
| Causa | Qué ocurrió |
|---|---|
| La estrategia escribió MCPT = False | Se salta directamente |
| Este backtest hizo 0 operaciones | No hay posiciones que contrastar, así que se salta |
| La lib de la máquina es una versión antigua | Falla la carga, así que se salta |
| Datos demasiado cortos, Sharpe que sale NaN, o cualquier excepción | Se salta; las estadísticas del backtest se escriben como siempre |
El motivo de no escribir nada antes que escribir algo mal es muy práctico: cualquier NaN o inf hace que se rechace la subida de estrategias de la máquina entera, así que en cuanto los números no están limpios, estos campos se dejan sin escribir como grupo.
Los backtests de Tipo C (estrategias de cartera: N símbolos con un vector de pesos) no ejecutan MCPT. La razón es que la estructura de este contraste es «una serie de precios contra una serie de posiciones», y una estrategia de cartera no tiene esa estructura. Lo que merece decirse con honestidad: no hay contraste sustituto.
| Lo que quieres hacer | Lo que pasa en realidad |
|---|---|
| Aplastar toda la cartera en una sola serie de retornos y volver a remuestrear | Eso es un bootstrap sobre retornos ya realizados, responde a otra pregunta y además no puede producir un valor p — y el valor p es justamente todo el sentido de que MCPT exista. Este camino está prohibido por escrito, y al agente tampoco se le permite fabricarse algo a mano para sustituirlo |
| Lo que esperas que muestre la tarjeta del filtro | «MCPT no aplica (estrategia de cartera)», no «No superado» — no cuenta como fallo y no afecta a la insignia «Verificada» |
¿Cuántas permutaciones son? Si ese número del texto explicativo está por debajo de 1000, este valor p no pasa el filtro de publicación por pequeño que sea. Mira primero el número, después el valor p.
¿De qué backtest es este valor p? El barrido de parámetros no ejecuta MCPT. El valor p que tienes pertenece solo «al backtest que se corrió una vez adoptados los parámetros»; si tocaste el código por el camino, hay que volver a ejecutarlo para que cuente.
¿La línea roja no cuadra con la tarjeta? Es normal. La ejecución de arriba era 0.8985 frente a 0.6751, solo cambia la forma de calcularlo; no hay nada que depurar.
¿No estarás leyendo «significativa» como «va a ganar»? La misma estrategia puede aprobar con p = 0.016 y hundirse con una eficiencia fuera de muestra de −0.334. El valor p no afirma absolutamente nada sobre el futuro.
¿Es que esa fila no aparece? Primero averigua cuál de las cuatro causas es (la estrategia lo apagó / 0 operaciones / lib antigua / datos insuficientes); no lo tomes como «el contraste no pasó».
Entendido el valor p, la siguiente pregunta es la mitad derecha de esa tabla comparativa: ¿se sostiene al cambiar a un tramo de datos que no ha visto? Ese camino es la validación fuera de muestra, y el espacio de trabajo tiene una pestaña propia para ella. Las estrategias oficiales de la Biblioteca de estrategias que llevan la insignia «Verificada» superaron en el filtro 2 exactamente este contraste del que habla el artículo — todas vienen con su backtest real y puedes leer los números directamente: Biblioteca de estrategias.