feat(live): attiva loss-guard Hurst sulle fade PORT06 (hurst_max=0.55)
Attivazione live: hurst_max=0.55 nei params delle 6 fade (MR01/MR02/MR07 x BTC/ETH) in _defs.py. hurst_skip_mask step=6 (5.9s/fade su 10560 barre live, ~35s per le 6 -> OK su poll 60s, e coincide con la cache di validazione). Calcolato dalle SOLE close -> nessun feed esterno, il worker lo computa inline. NB live/backtest: il filtro agisce solo sul path LIVE (spec.params); il backtest canonico (build_everything/regression-lock, via risk_management) NON e' filtrato -> il live FARA' meglio del backtest sul DD (FULL 4.10%->2.39% atteso). Divergenza intenzionale (miglioramento). Backtest-parity aggiornabile in seguito. Suite: 54 passed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -18,8 +18,14 @@ UNIVERSE8 = ["ADA", "BNB", "BTC", "DOGE", "ETH", "LTC", "SOL", "XRP"]
|
|||||||
# MR02/MR07 lo ignorano (**params). Vedi docs/diary/2026-06-01-tp-min-edge.md.
|
# MR02/MR07 lo ignorano (**params). Vedi docs/diary/2026-06-01-tp-min-edge.md.
|
||||||
MIN_TP_FRAC = 0.0015
|
MIN_TP_FRAC = 0.0015
|
||||||
|
|
||||||
|
# Loss-guard Hurst (live): salta le fade in regime PERSISTENTE/trending (rolling-Hurst >= 0.55),
|
||||||
|
# dove si concentrano stop-loss e perdite (stop-rate 43% vs 21% anti-persistente). DIMEZZA il DD
|
||||||
|
# del PORT06 (FULL 4.10%->2.39%) alzando lo Sharpe. Calcolato dalle SOLE close (no feed esterno).
|
||||||
|
# Validato 2026-06-02, vedi docs/diary/2026-06-02-fade-lossguard.md.
|
||||||
|
HURST_MAX = 0.55
|
||||||
|
|
||||||
FADE = [SleeveSpec(kind="single", name=c, sid=f"{c}_{a}", asset=a, cluster=f"{a}-rev",
|
FADE = [SleeveSpec(kind="single", name=c, sid=f"{c}_{a}", asset=a, cluster=f"{a}-rev",
|
||||||
params={"min_tp_frac": MIN_TP_FRAC})
|
params={"min_tp_frac": MIN_TP_FRAC, "hurst_max": HURST_MAX})
|
||||||
for a in ("BTC", "ETH") for c in ("MR01", "MR02", "MR07")]
|
for a in ("BTC", "ETH") for c in ("MR01", "MR02", "MR07")]
|
||||||
HONEST = [
|
HONEST = [
|
||||||
# DIP01: single-asset 1h -> StrategyWorker (Strategy DIP01_dip_buy). TR01/ROT02: multi-asset.
|
# DIP01: single-asset 1h -> StrategyWorker (Strategy DIP01_dip_buy). TR01/ROT02: multi-asset.
|
||||||
|
|||||||
@@ -18,17 +18,21 @@ from src.data.downloader import load_data
|
|||||||
from src.fractal.indicators import rolling_hurst
|
from src.fractal.indicators import rolling_hurst
|
||||||
|
|
||||||
|
|
||||||
def hurst_skip_mask(df: pd.DataFrame, hurst_max: float | None, window: int = 100) -> np.ndarray:
|
def hurst_skip_mask(df: pd.DataFrame, hurst_max: float | None, window: int = 100,
|
||||||
|
step: int = 6) -> np.ndarray:
|
||||||
"""Loss-guard Hurst: maschera bool (True = SALTA il segnale) per regime PERSISTENTE/trending,
|
"""Loss-guard Hurst: maschera bool (True = SALTA il segnale) per regime PERSISTENTE/trending,
|
||||||
dove la rolling-Hurst >= hurst_max. Le fade concentrano stop-loss e perdite proprio li'
|
dove la rolling-Hurst >= hurst_max. Le fade concentrano stop-loss e perdite proprio li'
|
||||||
(diagnosi: stop-rate 43% per hurst>0.55 vs 21% anti-persistente). Filtrare hurst>=0.55
|
(diagnosi: stop-rate 43% per hurst>0.55 vs 21% anti-persistente). Filtrare hurst>=0.55
|
||||||
DIMEZZA il DD del PORT06 (FULL 4.10%->2.39%) alzando lo Sharpe (validato 2026-06-02).
|
DIMEZZA il DD del PORT06 (FULL 4.10%->2.39%) alzando lo Sharpe (validato 2026-06-02).
|
||||||
CAUSALE: rolling_hurst usa solo i rendimenti fino a close[i]. hurst_max=None -> nessuno skip.
|
CAUSALE: rolling_hurst usa solo i rendimenti fino a close[i]. hurst_max=None -> nessuno skip.
|
||||||
Calcolata dalle SOLE close -> nessun feed dati esterno necessario (a differenza di DVOL)."""
|
Calcolata dalle SOLE close -> nessun feed dati esterno necessario (a differenza di DVOL).
|
||||||
|
step=6: calcola l'Hurst ogni 6 barre (ffill) -> ~6x piu' veloce per il worker live su finestre
|
||||||
|
lunghe (440g/10560 barre), e coincide con la cache di validazione (frac_step=6). L'Hurst varia
|
||||||
|
lentamente -> differenza trascurabile vs step=1."""
|
||||||
n = len(df)
|
n = len(df)
|
||||||
if hurst_max is None:
|
if hurst_max is None:
|
||||||
return np.zeros(n, dtype=bool)
|
return np.zeros(n, dtype=bool)
|
||||||
h = rolling_hurst(df["close"].values.astype(float), window=window)
|
h = rolling_hurst(df["close"].values.astype(float), window=window, step=step)
|
||||||
return h >= hurst_max
|
return h >= hurst_max
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user