ad65a0b344
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>
74 lines
3.2 KiB
Python
74 lines
3.2 KiB
Python
"""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)
|