Referencia técnica · Paso 8d · Backtest — régimen
Clasificar cada barra en uno de 6 regímenes (tendencia × volatilidad) y dejar que el trader excluya, por combo y con hipótesis, los regímenes donde su estrategia no debería operar. El sistema informa; el trader decide.
Dos ejes independientes. La macro tendencia exige consenso de dos indicadores; la volatilidad parte el percentil del ATR en tranquilo/volátil.
Exigir consenso evita señales débiles: si ROC y SMA no coinciden, es Neutral, no una tendencia dudosa. Períodos adaptativos por timeframe (ROC ~1 año, SMA ~200 D1 equivalente).
| Quiet | Volatile | |
|---|---|---|
| Up | Bull_Quiet0 | Bull_Volatile1 |
| Neutral | Neutral_Quiet2 | Neutral_Volatile3 |
| Down | Bear_Quiet4 | Bear_Volatile5 |
Los códigos 0-5 y las etiquetas son inmutables: los comparten el pipeline, el live Python y los EAs MQL5 (contrato de 3 motores). Un cambio semántico debe replicarse en los tres.
Dos decisiones que protegen la integridad: el warm-up nunca se disfraza de Neutral, y en intraday el régimen se toma de D1 con desfase.
Si el warm-up se etiquetara como Neutral genuino, inflaría ese régimen en las etapas posteriores y contaminaría el breakdown. Por eso el gate exige ambos ejes definidos.
Calcular el macro sobre D1 da un contexto de ~1 año calendario consistente, independiente del TF operado. El .shift(1) garantiza que la barra de hoy solo ve el régimen cerrado de ayer.
El filtro apaga las señales que caen en un régimen excluido, antes de que el motor genere el trade. No borra barras: enmascara entradas.
Sin columna regime en los datos, el filtro no se aplica (pasa todas las señales). Cada trade guarda su regime de entrada, que alimenta el breakdown per-régimen del refinamiento.
El pool tiene combos de naturaleza distinta (breakout, mean-reversion, momentum…). Un mismo excluded_regimes para todos no tiene sentido conceptual: cada uno necesita un tratamiento propio.
Ejemplo: "Breakout long con ATR squeeze: excluir Bear_Quiet porque en bajista tranquilo los squeezes se resuelven a la baja, no al alza." El sistema RECHAZA hipótesis vacías, tags faltantes, o excluir 0/4+ regímenes.
| Decisión | Efecto en el ranking |
|---|---|
| Accept | El combo CON filtro reemplaza al combo sin filtro (no coexisten → no duplica la superficie de multiple testing). |
| Burn | El combo sale del ranking definitivamente. |
| Skip | Queda sin filtro, marcado como revisado. |
Cada decisión se registra append-only (auditoría). El excluded_regimes aceptado es inmutable: los Steps 10-12 recalculan el régimen sobre sus ventanas pero aplican las mismas etiquetas — no permiten cambiarlas.
Al analizar un filtro se muestran cuatro cosas de costo bajo — sin re-backtest. Base de la decisión del trader.
El ratio de perdedores excluidos es el chequeo más honesto y directo: si sacaste trades pero eran mayormente ganadores (ratio < 0.5), la UI muestra warning naranja — algo va mal con la hipótesis.
El JK clásico asume dos series paired de igual longitud; acá filtered ⊂ baseline (subset, tamaños distintos). La implementación real es un bootstrap no-paramétrico, más honesto que forzar el supuesto — el nombre se conserva por familiaridad.
Sharpe interno simple (mean/std, sin anualizar) para comparabilidad. Si baseline o filtered tienen < 2 trades → None (no computable). Cost bajo: bootstrap sub-segundo sobre los retornos ya calculados.
Tests más caros o redundantes con lo que ya hacen WFV/OOS/transfer más adelante en el pipeline. No se corren por default: el trader los invoca si tiene duda sobre un combo puntual.
| Test | Qué responde | Cost |
|---|---|---|
| Placebo | ¿La mejora es real o artefacto del efecto-N (menos varianza al sacar N trades cualesquiera)? Excluye N trades al azar × 1000 y compara el Sharpe real vs. la distribución placebo. | ~1-2 s/combo |
| FDR-BH | Lectura estadística global del batch: de las hipótesis aceptadas, ¿cuántas sobreviven la corrección por multiplicidad? Denominador = familia completa (aceptadas + burned, no solo aceptadas). | <1 s |
Viene de 8c (exit policies). Con esto cierra el backtest; sigue la validación (walk-forward, OOS, transfer).
Fuentes:
· domain/regime_detector/ — classify (macro consenso + ATR percentil), constants (6 regímenes 0-5, −1)
· domain/backtester/engine.py — _apply_regime_filter
· domain/regime_filter/ — breakdown, metrics_delta, losers_ratio, jobson_korkie (bootstrap), placebo, fdr
· webapp/docs/REGIME_FILTER_DESIGN.md — diseño per-combo, decisión trader, auditoría