"""Loss-guard Hurst: le fade saltano i segnali in regime persistente/trending (rolling-Hurst >=
soglia), dove si concentrano stop-loss e perdite. Validato 2026-06-02: filtrare hurst>=0.55
DIMEZZA il DD del PORT06 alzando lo Sharpe. Filtro CAUSALE (close<=i), default off (None)."""
import numpy as np
import pandas as pd

from src.strategies.fade_base import hurst_skip_mask


def _df(close):
    n = len(close)
    return pd.DataFrame({"timestamp": range(n), "open": close, "high": close,
                         "low": close, "close": close, "volume": [1.0] * n})


def test_mask_off_when_none():
    df = _df(np.cumsum(np.random.default_rng(0).normal(size=400)) + 100)
    m = hurst_skip_mask(df, None)
    assert m.dtype == bool and not m.any()             # None -> nessuno skip


def test_mask_flags_persistent_regime():
    # serie fortemente TRENDING (persistente, Hurst alto) -> deve essere mascherata (skip) molto
    trend = np.linspace(100, 300, 600)
    df = _df(trend)
    m = hurst_skip_mask(df, hurst_max=0.55, window=100)
    # dopo il warmup, una rampa pulita e' persistente -> gran parte mascherata
    assert m[150:].mean() > 0.5


def test_fade_strategy_filters_signals():
    """Una fade con hurst_max produce <= segnali del baseline, e tutti i superstiti sono in
    regime non-persistente (la maschera e' False alla loro barra)."""
    import importlib
    rng = np.random.default_rng(1)
    # serie mean-reverting (anti-persistente) con qualche estensione -> genera fade
    n = 1200
    c = 100 + np.cumsum(rng.normal(scale=0.5, size=n))
    c = 100 + (c - c.mean()) * 0.3                      # comprimi verso la media (mean-revert)
    df = _df(c)
    ts = pd.to_datetime(df["timestamp"], unit="s", utc=True)
    m = importlib.import_module("scripts.strategies.MR01_bollinger_fade")
    Strat = next(v for k, v in vars(m).items()
                 if isinstance(v, type) and getattr(v, "__module__", "") == m.__name__
                 and hasattr(v, "generate_signals"))
    s = Strat()
    base = s.generate_signals(df, ts, bb_window=50, k=2.0, sl_atr=2.0)
    filt = s.generate_signals(df, ts, bb_window=50, k=2.0, sl_atr=2.0, hurst_max=0.55)
    assert len(filt) <= len(base)                       # il filtro non aggiunge mai segnali
    skip = hurst_skip_mask(df, 0.55, 100)
    assert all(not skip[sig.idx] for sig in filt)       # nessun superstite in regime persistente
