research(exit-lab): 34 agenti su exit dinamiche → EXIT-16 close-confirm SL PROMOSSO a livello PORT06

23 famiglie esplorate (harness condiviso exit_lab, train/OOS embargo nov-2023,
tutto lo storico 1h 2018-2026) + 10 verifiche avversariali + test PORT06.
'Cavalcare il prezzo' non esiste (4a conferma: oltre il TP=media non c'e' coda).
Scoperta: lo SL intrabar fisso e' il distruttore di valore n.1 delle fade
(stop da wick = falsi negativi). Forma robusta: SL solo su CHIUSURA oltre
sl0±0.5·ATR14 — PORT06 FULL Sharpe 6.47→7.84 DD 4.10→2.60, OOS 8.82→10.06.
Collaterali: bias gap-through dell'engine sugli stop stretti; ramo -2% del
worker morto con sl=0. Diario: docs/diary/2026-06-04-exit-lab.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Adriano Dal Pastro
2026-06-04 21:16:58 +00:00
parent 3accc91f84
commit ad65a0b344
36 changed files with 5116 additions and 0 deletions
@@ -0,0 +1,73 @@
"""EXIT-14 — protezione GIVEBACK dal picco (trailing sul PROFITTO, non sul prezzo).
Idea: una fade puo' correre a favore quasi fino al TP (alla media) e poi
ritracciare prima di toccarlo, restituendo gran parte del guadagno gia' maturato.
Questa policy traccia l'high-water-mark (hwm) del PROFITTO non realizzato sul
CLOSE; quando il profitto corrente scende sotto (1-g)*hwm_profit -- cioe' si e'
restituita una frazione g del picco -- e il picco era gia' "significativo"
(hwm_profit > soglia * dist(entry, tp0)), esce al close del bar (after_bar).
Il TP fisso tp0 e lo SL fisso sl0 RESTANO invariati e prioritari intrabar.
Razionale: protegge il profitto maturato senza toccare i livelli; non e' un
ladder (ieri scartato perche' al TP/media il movimento e' esaurito) ma un
trailing sul drawdown del trade quando ha gia' fatto buona parte del lavoro.
ANTI-LOOK-AHEAD:
- levels(j) NON e' toccato (TP/SL fissi): nessun dato futuro.
- after_bar(j) decide sul CLOSE del bar j (eseguibile al poll). Aggiorna l'hwm
con il profitto a close[j] e poi confronta: tutto con dati <= j. Il bar j e'
lecito in after_bar per contratto. L'hwm e' un cliquet (non scende mai).
GRID: g in {0.4, 0.6} x arm_frac in {0.3, 0.5} della distanza al TP (4 celle).
- g = frazione del picco di profitto restituita che fa scattare l'uscita.
- arm_frac = il giveback e' armato solo quando hwm_profit ha superato
arm_frac * dist(entry, tp0): finche' il trade non ha "fatto strada"
(frazione del cammino verso la media) non interviene -> non taglia i trade
che partono storti, solo quelli che hanno gia' guadagnato e poi mollano.
"""
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from exit_lab import ExitPolicy, evaluate # noqa: E402
class Giveback(ExitPolicy):
name = "giveback"
def __init__(self, ctx, i, d, entry, tp0, sl0, mb, **params):
super().__init__(ctx, i, d, entry, tp0, sl0, mb, **params)
self.g = float(params.get("g", 0.4))
self.arm_frac = float(params.get("arm_frac", 0.3))
self.close = ctx["close"]
# distanza (in prezzo, sempre positiva) dall'entrata al TP iniziale
self.dist_tp = abs(self.tp0 - entry) if self.tp0 is not None else 0.0
self.arm_level = self.arm_frac * self.dist_tp
self.hwm_profit = 0.0 # high-water-mark del profitto a favore (cliquet)
def after_bar(self, j: int) -> bool:
if self.dist_tp <= 0.0:
return False
# profitto NON realizzato a favore, valutato sul close del bar j (lecito qui)
profit = (self.close[j] - self.entry) * self.d
if profit > self.hwm_profit:
self.hwm_profit = profit # aggiorna il picco (non scende mai)
# arma solo se il picco ha superato la soglia (trade gia' "in cammino")
if self.hwm_profit < self.arm_level:
return False
# esci se il profitto corrente ha restituito >= g del picco
if profit < (1.0 - self.g) * self.hwm_profit:
return True
return False
GRID = [
{"g": 0.4, "arm_frac": 0.3},
{"g": 0.4, "arm_frac": 0.5},
{"g": 0.6, "arm_frac": 0.3},
{"g": 0.6, "arm_frac": 0.5},
]
if __name__ == "__main__":
evaluate(Giveback, GRID)