fix(live): win netto-fee + filtro TP edge-minimo sulle fade
Due correzioni emerse da close live con win=True ma pnl<0. 1) Metrica win lorda -> netta. _close_position contava is_win=trade_return>0 (lordo), gonfiando l'accuracy: un take-profit colpito con mossa < fee RT risultava "win" pur perdendo. 51 close live: 39 win (76,5%) -> 13 falsi win -> accuracy netta reale 52,9%. Fix: is_win = net > 0. Capitale/PnL erano già corretti (netti). Contatori persistiti riconciliati a parte (MR01/DIP01 BTC 7->1). 2) Filtro edge-minimo min_tp_frac. I 13 falsi win erano tutti MR01/DIP01 BTC in regime piatto: TP (la media) entro il costo round-trip -> perdenti garantiti. Aggiunto param min_tp_frac (default 0.0=off) a tutte e 4 le fade (MR01 banda, MR02 midpoint, MR07 ATR, DIP01): salta i segnali col TP entro la soglia. Non si "allarga" il TP (rischierebbe di perdere di piu'): si evita la trade. Cablato live a 0.0015 (1,5x fee) in _defs.py. Validazione backtest BTC+ETH 1h: neutro su tutte le fade (0-1 trade rimossi, pnl invariato o +leggero su DIP01). I micro-scalp sotto-fee non esistono nello storico -> artefatto del regime attuale. Filtro puro-upside. Test: test_win_net_of_fees.py, test_min_tp_frac.py (monotonia + gap > soglia + default-off invariato). Suite: 50 passed. NB deploy: il sorgente e' COPY nell'immagine, non montato -> serve `docker compose up -d --build`, non un semplice restart (vale anche per il fix SH01 horizon-exit, andato live solo con questo rebuild). Volume ./data persiste, 14 worker in RESUME puliti. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -42,11 +42,15 @@ class Dip01DipBuy(Strategy):
|
||||
sd = pd.Series(c).rolling(n).std().values
|
||||
a = _atr(df, 14)
|
||||
z = (c - ma) / np.where(sd == 0, np.nan, sd)
|
||||
# Edge minimo: salta i dip il cui TP (la media) è entro il costo round-trip. 0 = off.
|
||||
min_tp_frac = params.get("min_tp_frac", 0.0)
|
||||
out: list[Signal] = []
|
||||
for i in range(n + 14, len(c)):
|
||||
if np.isnan(z[i]) or np.isnan(a[i]) or np.isnan(ma[i]):
|
||||
continue
|
||||
if z[i] <= -z_in and z[i - 1] > -z_in:
|
||||
if min_tp_frac > 0 and abs(ma[i] - c[i]) / c[i] <= min_tp_frac:
|
||||
continue # TP entro le fee -> non eseguibile in utile
|
||||
out.append(Signal(idx=i, direction=1, entry_price=float(c[i]),
|
||||
metadata={"tp": float(ma[i]),
|
||||
"sl": float(c[i] - sl_atr * a[i]),
|
||||
|
||||
Reference in New Issue
Block a user