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>
This commit is contained in:
Adriano Dal Pastro
2026-06-19 15:16:03 +00:00
parent 8401a280b9
commit 14522262e6
383 changed files with 1971 additions and 779 deletions
@@ -0,0 +1,77 @@
"""EXIT-08 — SL che si STRINGE linearmente col tempo (time-based stop tighten).
Lo stop iniziale sl0 si avvicina linearmente a un livello d'arrivo `target`
man mano che il trade invecchia. TP fisso (tp0) e horizon=max_bars invariati.
frac(j) = clamp( (j - i) / (mb * stretch), 0, 1 )
sl(j) = sl0 + frac(j) * (target - sl0)
target ("arrivo"):
- "entry" -> entry (a fine corsa lo stop e' a breakeven)
- "midpoint" -> (entry + sl0)/2 (a fine corsa lo stop e' a meta' strada)
Direzioni: il segno e' gestito dalla geometria di sl0 vs entry.
long (d=1): sl0 < entry -> target >= sl0 -> lo stop SALE verso entry
short (d=-1): sl0 > entry -> target <= sl0 -> lo stop SCENDE verso entry
In entrambi i casi lo stop si stringe (avvicina al prezzo d'ingresso) col tempo.
stretch:
- 1.0 : lo stop raggiunge `target` a max_bars (fine horizon).
- 2.0 : lo stop raggiunge `target` a 2*max_bars -> stringe a META' velocita',
quindi a max_bars e' solo a meta' del cammino sl0->target (piu' lasco).
ANTI-LOOK-AHEAD: sl(j) dipende SOLO da {i, j, mb, stretch, entry, sl0}, tutti
noti all'ENTRATA (close[i]). Nessun dato del bar j o successivi entra nel livello
attivo nel bar j. Il TP resta tp0. -> contratto rispettato per costruzione.
MECCANISMO ATTESO: stringere lo stop col tempo taglia prima i trade che ristagnano
(non vanno al TP ne' allo SL iniziale e scadrebbero a max_bars vicino al BE/in
perdita). Rischio: stoppa fuori trade che sarebbero rientrati verso il TP (la fade
e' mean-reversion: il movimento contrario e' spesso transitorio) -> puo' alzare lo
stop-rate effettivo e tagliare winner ritardatari.
GRID: stretch in {1.0, 2.0} x target in {entry, midpoint} (4 celle).
"""
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 SlTighten(ExitPolicy):
name = "sl_tighten"
def __init__(self, ctx, i, d, entry, tp0, sl0, mb, **params):
super().__init__(ctx, i, d, entry, tp0, sl0, mb, **params)
self.stretch = float(params.get("stretch", 1.0))
self.target_kind = str(params.get("target", "entry"))
if self.target_kind == "entry":
self.target = entry
elif self.target_kind == "midpoint":
self.target = 0.5 * (entry + sl0)
else:
raise ValueError(f"target sconosciuto: {self.target_kind}")
self.denom = max(self.mb * self.stretch, 1e-9)
def levels(self, j: int):
# frac dipende solo da i, j, mb, stretch -> noti all'entrata. No look-ahead.
frac = (j - self.i) / self.denom
if frac < 0.0:
frac = 0.0
elif frac > 1.0:
frac = 1.0
sl = self.sl0 + frac * (self.target - self.sl0)
return self.tp0, sl, 1.0
GRID = [
{"stretch": 1.0, "target": "entry"},
{"stretch": 1.0, "target": "midpoint"},
{"stretch": 2.0, "target": "entry"},
{"stretch": 2.0, "target": "midpoint"},
]
if __name__ == "__main__":
evaluate(SlTighten, GRID)