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:
@@ -0,0 +1,120 @@
|
||||
export const meta = {
|
||||
name: 'fade-lossguard',
|
||||
description: 'Sistema anti-perdite per le fade in regime trending/low-vol: test meccanismi su MR01/02/07',
|
||||
phases: [
|
||||
{ title: 'Test', detail: 'agenti: ogni meccanismo di filtro applicato alle fade reali (BTC+ETH)' },
|
||||
{ title: 'Synth', detail: 'classifica + miglior loss-guard, gate: riduce DD senza uccidere edge' },
|
||||
],
|
||||
}
|
||||
|
||||
const API = `
|
||||
=== Harness (gia pronto) ===
|
||||
import sys; sys.path.insert(0,'.')
|
||||
import numpy as np, pandas as pd, importlib
|
||||
from scripts.analysis.regime_lab import load_features, report
|
||||
from scripts.analysis.explore_lab import robust, atr
|
||||
|
||||
def load_strat(mod):
|
||||
m=importlib.import_module(mod)
|
||||
return next(v() for k,v in vars(m).items() if isinstance(v,type) and hasattr(v,'generate_signals') and getattr(v,'__module__','')==m.__name__)
|
||||
FADES={'MR01':('scripts.strategies.MR01_bollinger_fade',dict(bb_window=50,k=2.5,sl_atr=2.0,max_bars=24,trend_max=3.0)),
|
||||
'MR02':('scripts.strategies.MR02_donchian_fade',dict(n=20,sl_atr=2.0,max_bars=24,trend_max=3.0)),
|
||||
'MR07':('scripts.strategies.MR07_return_reversal',dict(n=50,k=3.5,tp_atr=2.0,sl_atr=1.5,max_bars=24,trend_max=3.0))}
|
||||
|
||||
# colonne regime_lab (causali): dvol, dvol_pct, vrp, funding_z, dvol_chg, hurst, higuchi, vratio, frac_up/dn
|
||||
# ADX (se ti serve) calcolalo causale da OHLC; efficiency-ratio Kaufman = |c[i]-c[i-n]| / sum|diff| su [i-n,i].
|
||||
|
||||
# PATTERN: genera i segnali fade, poi APPLICA IL TUO FILTRO scartando le entries in regime sfavorevole,
|
||||
# confronta BASELINE vs FILTRATA su ogni fade x asset:
|
||||
def entries_from(strat, df, par, keep=lambda df,i: True):
|
||||
ts=pd.to_datetime(df['timestamp'],unit='ms',utc=True)
|
||||
out=[]
|
||||
for s in strat.generate_signals(df,ts,**par):
|
||||
if keep(df, s.idx): # keep=False -> filtro scarta (loss-guard)
|
||||
out.append({'i':s.idx,'d':s.direction,'tp':s.metadata['tp'],'sl':s.metadata['sl'],'max_bars':s.metadata['max_bars']})
|
||||
return out
|
||||
# per ogni (fade,asset): res_base=report(.., entries_from(..., keep=tutto)); res_filt=report(.., col tuo keep)
|
||||
# confronta: Sharpe OOS, DD full/oos, ret, #trade (quanti scartati), e robust(). Aggrega sulle 6 combo.
|
||||
`
|
||||
|
||||
const CONTEXT = `
|
||||
PROBLEMA: le fade (MR01 Bollinger, MR02 Donchian, MR07 return-reversal) sono mean-reversion 1h con
|
||||
filtro trend EMA200 (trend_max=3.0). DIAGNOSI EMPIRICA (3022 trade, 2021+): le PERDITE e gli STOP
|
||||
si concentrano nel regime PERSISTENTE/TRENDING, NON nella bassa vol:
|
||||
- somma perdite per cella (Hurst x DVOL): la cella peggiore e' hurst>0.55 (-2695% in low-vol,
|
||||
dominante in ogni terzile vol). I peggiori 1% trade hanno hurst medio 0.61 (77% con hurst>0.55).
|
||||
- tasso STOP-LOSS: 43% quando hurst>0.55 vs 21% quando hurst<0.45 (anti-persistente). 2x.
|
||||
- net: le celle restano positive (i winner battono), quindi filtrare toglie anche winner -> il
|
||||
loss-guard e' utile SOLO se riduce DD/coda SENZA uccidere l'edge netto.
|
||||
RICERCA ESTERNA (confermata): (a) Hurst regime filter: MR solo H<0.45, in 0.45-0.55 ridurre size,
|
||||
evitare H>0.55. (b) ADX: MR profit factor 1.62 con ADX<20 vs -0.74 con ADX>30 (switch di regime piu'
|
||||
importante). (c) ATR/vol-EXPANSION ratio>1.5 disabilita MR -> ha prevenuto il 72% delle perdite
|
||||
maggiori. (d) time-stop: se non rientra in ~15 barre e' un trend, esci.
|
||||
|
||||
OBIETTIVO: trovare il MIGLIOR meccanismo (o combo) che, applicato alle fade reali, RIDUCE DD/coda/
|
||||
stop-rate MANTENENDO l'edge netto OOS. Metodologia: causale no-look-ahead (le colonne regime_lab
|
||||
sono causali; i filtri usano solo dati <= i), netto fee (report() fa OOS+sweep). LEZIONE FR01: un
|
||||
filtro che riduce le perdite ma anche i winner spesso NON migliora -> il gate vero e' DD giu' a
|
||||
parita' (o quasi) di Sharpe/ret, idealmente Sharpe SU e DD GIU'.
|
||||
|
||||
` + API
|
||||
|
||||
const SCHEMA = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
meccanismo: { type: 'string' },
|
||||
descrizione: { type: 'string' },
|
||||
base_oos_sharpe: { type: 'number' }, filt_oos_sharpe: { type: 'number' },
|
||||
base_dd_full: { type: 'number' }, filt_dd_full: { type: 'number' },
|
||||
base_oos_ret: { type: 'number' }, filt_oos_ret: { type: 'number' },
|
||||
trade_scartati_pct: { type: 'number' },
|
||||
riduce_perdite: { type: 'boolean', description: 'riduce DD/coda/stop-rate' },
|
||||
preserva_edge: { type: 'boolean', description: 'edge netto OOS preservato (Sharpe non crolla, robust resta)' },
|
||||
buon_lossguard: { type: 'boolean', description: 'riduce perdite SENZA uccidere edge -> candidato' },
|
||||
verdetto: { type: 'string', description: 'numeri base vs filtrato aggregati sulle 6 combo fade x asset' },
|
||||
},
|
||||
required: ['meccanismo', 'buon_lossguard', 'riduce_perdite', 'preserva_edge', 'verdetto'],
|
||||
}
|
||||
|
||||
const MECHS = [
|
||||
['Hurst-skip H>0.55', 'scarta le fade quando rolling-hurst(window=100) >= 0.55 (regime persistente). Test anche soglia 0.50 e 0.60, riporta la migliore.'],
|
||||
['Hurst-size transition', 'NON scartare ma RIDURRE: tieni tutte le entries ma pesa size 1.0 se hurst<0.45, 0.5 se 0.45-0.55, 0.25 se >0.55. (Per testare la riduzione size col report attuale: approssima scartando il 50%/75% delle entries nelle bin alte in modo deterministico per indice, oppure confronta solo le bin.)'],
|
||||
['ADX-skip', 'calcola ADX(14) causale; scarta le fade quando ADX>25 (trend). Test soglie 20/25/30.'],
|
||||
['vol-expansion vratio', 'scarta le fade quando vratio (vol breve/lunga, colonna regime_lab) > 1.5 (vol in espansione = breakout, non range). Test 1.3/1.5/1.8. (la ricerca dice -72% perdite maggiori)'],
|
||||
['efficiency-ratio Kaufman', 'ER = |c[i]-c[i-n]|/sum(|diff|) su finestra n=20; scarta quando ER>0.5 (moto efficiente/trending). Test 0.4/0.5/0.6.'],
|
||||
['time-stop piu corto', 'riduci max_bars da 24 a 12 o 15 (esci prima se non rientra = probabile trend). Confronta DD/edge.'],
|
||||
['Hurst + vol-expansion combo', 'scarta se hurst>0.55 OPPURE vratio>1.5. Verifica se la combo riduce piu DD del singolo senza perdere piu edge.'],
|
||||
['Hurst + ADX combo', 'scarta se hurst>0.55 E ADX>25 (doppia conferma di trend) -> piu selettivo, scarta meno winner.'],
|
||||
['vol-target sizing', 'scala la size per 1/realized_vol (target vol costante): approssima tenendo solo le entries in vol moderata, riporta effetto su DD/coda.'],
|
||||
['DVOL-rising skip', 'scarta le fade quando dvol_chg>0 forte (DVOL in salita = stress/espansione vol imminente). Test soglie su dvol_chg.'],
|
||||
]
|
||||
const ASSETS_NOTE = 'Applica a tutte e 3 le fade (MR01,MR02,MR07) su BTC E ETH (6 combo), aggrega base vs filtrato.'
|
||||
|
||||
phase('Test')
|
||||
// ogni meccanismo = 1 agente che testa su tutte le 6 combo; piu' 4 agenti che esplorano combo/parametri fini
|
||||
const tasks = MECHS.map(([nm, desc]) => () => agent(
|
||||
CONTEXT + `\n\nMECCANISMO DA TESTARE: ${nm}\n${desc}\n\n${ASSETS_NOTE}\n` +
|
||||
`Scrivi uno script in /tmp (cd /opt/docker/PythagorasGoal && uv run python /tmp/<file>.py), confronta ` +
|
||||
`BASELINE (fade senza filtro) vs FILTRATA su ogni combo, AGGREGA (media o somma equity) e riporta. ` +
|
||||
`Il filtro deve essere CAUSALE. Decidi buon_lossguard=true SOLO se riduce DD/coda/stop-rate MANTENENDO ` +
|
||||
`l'edge netto OOS (Sharpe non crolla, ret OOS resta ampiamente positivo). Cita i numeri base vs filtrato.`,
|
||||
{ label: `mech:${nm.slice(0, 18)}`, phase: 'Test', schema: SCHEMA }))
|
||||
|
||||
const results = (await parallel(tasks)).filter(Boolean)
|
||||
|
||||
phase('Synth')
|
||||
const good = results.filter(r => r.buon_lossguard)
|
||||
const synthesis = await agent(
|
||||
CONTEXT +
|
||||
`\n\nRisultati di ${results.length} meccanismi testati:\n${JSON.stringify(results, null, 1)}\n\n` +
|
||||
`SINTESI FINALE (italiano) per il decisore:
|
||||
1) Esiste un loss-guard che riduce le perdite/DD delle fade in regime trending SENZA uccidere l'edge?
|
||||
2) Tabella: meccanismo | base vs filtrato (OOS Sharpe, DD, ret, %trade scartati) | buon_lossguard?
|
||||
3) Il MIGLIORE (e l'eventuale combo) con i numeri. Quanto DD/coda si risparmia e a che costo di ret.
|
||||
4) Coerenza con la ricerca esterna (Hurst<0.45 / ADX / vol-expansion / time-stop).
|
||||
5) Raccomandazione: quale filtro applicare alle fade live, con che soglia, e il caveat (serve feed
|
||||
DVOL/regime live? il filtro va validato a livello PORT06 = riduce il DD del portafoglio?).
|
||||
Onesta: se nessuno migliora davvero (riduce solo ret), dillo. Cita NUMERI reali.`,
|
||||
{ label: 'synth-lossguard', phase: 'Synth' })
|
||||
|
||||
return { results, good, synthesis }
|
||||
Reference in New Issue
Block a user