feat(risk): filtro trend per alzare Acc e ridurre DD + modello portafoglio
Filtro opzionale trend_max/ema_long su tutte le fade (MR01/MR02/MR03/MR07): salta i segnali quando |close-EMA200|/ATR supera la soglia (non fadare un trend o crollo estremo). Con trend_max=3.0 (default in strategies.yml): accuratezza su e DD giu' su 7/8 sleeve, drastico su ETH (MR01 71->26%, MR02 42->25%, MR03 66->34%, MR07 46->21%); edge OOS confermato. MR03 BTC: filtro disattivo (unico sleeve dove peggiora entrambe). Scartate come non robuste: vol-target sizing e skip-alta-volatilita' (peggiorano sia Acc che DD). Aggiunto modello di portafoglio equipesato su sotto-conti indipendenti: DD aggregato ~14% full / ~10% OOS sul paniere di 8 sleeve, contro 20-70% del singolo -> vera leva anti-drawdown. Banco di prova: scripts/analysis/risk_improvements.py, risk_portfolio.py. Helper trend_distance() in fade_base. CLAUDE.md e diario aggiornati. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -57,16 +57,21 @@ class BollingerFade(Strategy):
|
||||
k = params.get("k", 2.5)
|
||||
sl_atr = params.get("sl_atr", 2.0)
|
||||
max_bars = params.get("max_bars", 24)
|
||||
trend_max = params.get("trend_max") # None = filtro disattivo
|
||||
ema_long = params.get("ema_long", 200)
|
||||
|
||||
ma = pd.Series(c).rolling(bb_w).mean().values
|
||||
sd = pd.Series(c).rolling(bb_w).std().values
|
||||
a = _atr(df, 14)
|
||||
up, lo = ma + k * sd, ma - k * sd
|
||||
el = pd.Series(c).ewm(span=ema_long, adjust=False).mean().values if trend_max is not None else None
|
||||
|
||||
signals: list[Signal] = []
|
||||
for i in range(bb_w + 14, n_len):
|
||||
if np.isnan(up[i]) or np.isnan(a[i]):
|
||||
continue
|
||||
if el is not None and (a[i] == 0 or np.isnan(el[i]) or abs(c[i] - el[i]) / a[i] > trend_max):
|
||||
continue
|
||||
if c[i] < lo[i] and c[i - 1] >= lo[i - 1]:
|
||||
d, sl = 1, c[i] - sl_atr * a[i]
|
||||
elif c[i] > up[i] and c[i - 1] <= up[i - 1]:
|
||||
|
||||
Reference in New Issue
Block a user