Files
PythagorasGoal/Old/scripts/analysis/exit_policies/14_giveback.py
T
Adriano Dal Pastro 14522262e6 chore(reset): v2.0.0 — storico certificato Deribit mainnet, ripartenza pulita
Reset del progetto su fondamenta verificate dopo la scoperta che l'intera
libreria "validata OOS" era artefatto di feed contaminato (print fantasma del
feed Cerbero TESTNET + storico Binance/USDT).

- Storico ricostruito da Deribit MAINNET (ccxt pubblico, tokenless) e
  CERTIFICATO (certify_feed.py): BTC/ETH puliti su TUTTA la storia
  (mediana 2-6 bps vs Coinbase USD), integrita' OHLC + coerenza resample
  (maxΔ 0.00) + cross-venue OK. Alt esclusi (illiquidi/divergenti: LTC/DOGE
  50-82% barre flat; XRP/BNB non certificabili).
- Verdetto sul feed pulito: FADE / PAIRS / XS01 / TSM01 morti (ogni
  portafoglio Sharpe -2.3..-3.0, DD ~40%); solo SH01 e frammenti HONEST
  con segnale residuo, da ri-validare in isolamento.
- Cleanup "restart pulito": strategie, stack live (src/live, src/portfolio,
  runner/executor, yml, docker), ~100 script ricerca/gate, waste/games/
  portfolios, dati non certificati + cache e 60+ diari -> archiviati in Old/
  (preservati, non cancellati). Diario consolidato in un unico documento.
- Skeleton ricerca tenuto: Strategy ABC + indicatori + src/fractal +
  src/backtest/engine + load_data; tool dati certificati (rebuild_history,
  certify_feed, audit_feed, multi_source_check).
- Universo dati ATTIVO: solo BTC/ETH (5m/15m/1h); guardrail fisico
  (load_data su alt -> FileNotFoundError). Esecuzione DISABILITATA, conto flat.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 15:20:59 +00:00

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)