export const meta = { name: 'mr02eth-replace-search', description: 'Cerca sostituto/miglioria a MR02/ETH: 112 strategie distinte su harness onesto + verifica avversariale', phases: [ { title: 'Generate', detail: '112 agenti, una strategia ETH distinta ciascuno, backtest onesto fee-aware OOS' }, { title: 'Verify', detail: 'verifica avversariale dei survivor (look-ahead audit + re-run + robustezza)' }, ], } // ---------------------------------------------------------------- baseline & recipe const BASELINE = `BASELINE DA BATTERE (MR02/ETH sullo STESSO engine explore_lab, ETH 1h, fee 0.10% RT, lev 3x, pos 0.15): - canonico (Donchian n=20, sl 2*ATR, max_bars 24, TP a centro canale): full Sharpe 7.49, OOS Sharpe 10.94, full DD 42%, OOS DD 18%, exposure 31%, 2392 trade, fee0.2% positivo. - trend-filtrato (come sopra + salta se |close-EMA200|/ATR(14) > 3.0): full Sharpe 8.45, OOS Sharpe 11.96, full DD 25%, OOS DD 13%, exposure 16%, 1148 trade, fee0.2% positivo. Il PROBLEMA di questo sleeve e' il DD/whipsaw (fada il trend al ribasso, poi shorta il rimbalzo). Un buon SOSTITUTO deve: battere OOS Sharpe ~12 E/O tagliare il full DD sotto ~20%, restando OOS positivo, sopravvivere a fee 0.20% RT, con la maggior parte degli anni 2021+ positivi. DD piu' basso a Sharpe comparabile e' GIA' valore. Anche un buon DIVERSIFICATORE (Sharpe decente + decorrelato, esposizione diversa) e' utile.` const RECIPE = `Lavora in /opt/docker/PythagorasGoal. Testa UNA idea di strategia come candidata a SOSTITUIRE/MIGLIORARE MR02/ETH. Usa l'harness ONESTO condiviso (no look-ahead, fee-aware, OOS). Scrivi UNO script self-contained in /tmp/cand_KEY.py (KEY = la tua key, univoca) ed eseguilo: cd /opt/docker/PythagorasGoal && uv run python /tmp/cand_KEY.py API (import from scripts.analysis.explore_lab): - get_df(asset, tf) -> df [open,high,low,close,volume,timestamp,dt]. Usa asset="ETH", tf="1h" (puoi testare anche tf="4h"). - atr(df,n=14)->np.array ; ema(x,n)->np.array ; rsi(close,n=14)->np.array - simulate(entries, df, fee_rt=0.001, lev=3.0, pos=0.15, split=-1) -> dict(trades,win,ret,dd,sharpe,yearly,exposure) - evaluate(name, entries, df, fees=(0,0.0005,0.001,0.002)) -> dict(full,oos,sweep,sweep_oos,pos_yrs,n_yrs) e stampa una riga. - robust(res)->bool. Se la tua idea usa DVOL/funding/Hurst/fractali, puoi importare da scripts.analysis.regime_lab: load(asset,tf), regime_features(df), frac_features(df), load_features(asset,tf) (cache; vedi il file se serve). Se non sono disponibili, ripiega su feature calcolate dalle sole OHLCV. Se la tua idea e' shape/kNN, vedi scripts.analysis.shape_lab (analog_entries, analog_signals). entries = list di {"i":int, "d":+1/-1, "max_bars":int, "tp":float|None, "sl":float|None}. L'ingresso esegue a close[i]. TP/SL sono intrabar al livello (SL valutato PRIMA del TP). split>0 nel simulate = solo entries con i>=split (OOS). ANTI-LOOK-AHEAD (non negoziabile): direzione e prezzo alla barra i usano SOLO dati [0..i] (close[i] incluso). Mai usare high/low/close della barra i+ per decidere ingresso/direzione. Canali/rolling che devono escludere la barra corrente vanno .shift(1). Prezzo d'ingresso = close[i]. La famiglia squeeze e' stata scartata proprio per questo errore: NON ripeterlo. ${BASELINE} Procedura: implementa l'idea, fai uno sweep PICCOLO (2-4 config di parametri), scegli la MIGLIORE per OOS Sharpe a parita' di: sopravvive a fee 0.20% RT e full DD non peggiore della baseline. Verifica l'assenza di look-ahead (perturba le barre future e controlla che gli entries non cambino, oppure argomenta perche' non c'e'). Restituisci SOLO il risultato strutturato della tua MIGLIORE config. Sii ONESTO: se non batte la baseline, riporta i numeri VERI (peggiori) — un risultato negativo e' informazione utile. NON inventare numeri: devono venire dall'esecuzione reale dello script.` const SCHEMA = { type: 'object', additionalProperties: false, required: ['key','family','implemented','ran_ok','best_config','trades','exposure','full_sharpe','full_ret','full_dd','oos_sharpe','oos_ret','oos_dd','fee02_full','fee02_oos','pos_yrs','n_yrs','no_lookahead','beats_baseline','verdict','note'], properties: { key: { type: 'string' }, family: { type: 'string' }, implemented: { type: 'boolean' }, ran_ok: { type: 'boolean', description: 'lo script ha girato senza errori e i numeri vengono dall esecuzione reale' }, best_config: { type: 'string', description: 'parametri della config migliore' }, trades: { type: 'integer' }, exposure: { type: 'number', description: '% barre in posizione (full)' }, full_sharpe: { type: 'number' }, full_ret: { type: 'number', description: '% ritorno full' }, full_dd: { type: 'number', description: '% max drawdown full' }, oos_sharpe: { type: 'number' }, oos_ret: { type: 'number' }, oos_dd: { type: 'number' }, fee02_full: { type: 'number', description: 'ritorno % full a fee 0.20% RT' }, fee02_oos: { type: 'number', description: 'ritorno % OOS a fee 0.20% RT' }, pos_yrs: { type: 'integer', description: 'anni positivi' }, n_yrs: { type: 'integer' }, no_lookahead: { type: 'boolean' }, beats_baseline: { type: 'boolean', description: 'batte la baseline MR02/ETH trend-filtrata (OOS Sharpe ~12 e/o DD<20%)' }, verdict: { type: 'string', enum: ['substitute','improvement','diversifier','reject'] }, note: { type: 'string', description: '1-2 frasi: perche funziona o perche no, e l angolo distintivo' }, }, } // ---------------------------------------------------------------- 112 idee distinte // [key, family, idea] const SPECS = [ // A. fade gated da regime (il fix del whipsaw) ['adx_gate_fade','gated-fade','Donchian/Bollinger fade su ETH ma SALTA quando ADX(14) e alto (regime trending). Calcola ADX causale; entra in fade solo se ADXsoglia (range). Sweep finestra/soglia.'], ['rsq_gate_fade','gated-fade','Fade gated dall R^2 di una regressione lineare rolling sul log-prezzo: alto R^2 = trend pulito (salta), basso = range (fada). Sweep finestra/soglia.'], ['bbw_gate_fade','gated-fade','Bollinger fade gated dalla band-width (BBW): fada solo quando BBW in regime medio/alto ma non esplosivo. Sweep soglie BBW percentile.'], ['atr_pct_gate_fade','gated-fade','Donchian fade ma salta quando ATR-percentile rolling e estremo (>p80): la coda di vol e dove il whipsaw uccide. Sweep percentile.'], ['htf_align_fade','gated-fade','Fade ETH 1h ma NON contro il trend 4h: salta i long-fade se EMA2090, exit su RSI2 che torna a 50 o max_bars. Sweep soglie e max_bars su ETH 1h.'], ['rsi14_bands','mr-alt','RSI(14) revert con bande: long RSI<30, short RSI>70, TP al ritorno a 50 (proxy prezzo), SL ATR. Sweep.'], ['pctb_fade','mr-alt','Bollinger %B fade: long quando %B<0, short quando %B>1, TP a media, SL ATR. Sweep finestra/sigma/max_bars. Confronta con MR01.'], ['zscore_price_fade','mr-alt','Z-score del prezzo vs SMA(n): entra quando |z|>soglia contro il movimento, TP a z=0 (SMA), SL ATR. Sweep n/soglia. Versione simmetrica del DIP.'], ['zscore_ret_fade','mr-alt','Z-score del rendimento di barra (MR07-like) ma ri-tunato per ETH: |z|>soglia su finestra n, exit in multipli ATR. Sweep n/soglia/exit.'], ['vwap_revert','mr-alt','Reversion a VWAP rolling (volume-weighted): entra quando il prezzo devia >k*sigma dal VWAP, TP al VWAP. Sweep finestra/k.'], ['keltner_fade_eth','mr-alt','Keltner channel fade ri-tunato per ETH (EMA +/- m*ATR): fada la rottura della banda Keltner, TP a EMA. Sweep m/finestra. MR03 era debole su BTC ma ETH puo differire.'], ['cci_revert','mr-alt','CCI(n) extreme revert: long CCI<-100, short CCI>+100, exit su CCI->0 o max_bars. Sweep.'], ['williamsr_revert','mr-alt','Williams %R revert: long %R<-80, short %R>-20, TP a media canale, SL ATR. Sweep.'], ['stoch_revert','mr-alt','Stochastic %K/%D extreme revert su ETH: long quando %K<20 e cross-up, short %K>80 cross-down. Sweep finestre.'], ['connors_rsi','mr-alt','Connors RSI (RSI3 del prezzo + RSI2 della streak + percentrank del rendimento) extreme revert. Sweep soglie.'], ['anchored_vwap_revert','mr-alt','Reversion a VWAP ancorato all ultimo swing-low/high (Williams): entra quando il prezzo si allontana >k*ATR dall AVWAP, TP all AVWAP.'], ['median_z_fade','mr-alt','Z robusto: (close - rolling median) / rolling MAD. Fada |z|>soglia, TP a mediana. Piu robusto agli outlier della SMA-z. Sweep.'], ['pctrank_fade','mr-alt','Percent-rank del close nella finestra rolling: long se rank<0.05, short se rank>0.95, TP al rank 0.5 (proxy). Sweep finestra.'], ['double_bollinger','mr-alt','Doppia Bollinger: entra fade alla banda esterna (2.5-3 sigma), esce alla banda interna (1 sigma) invece che alla media. Sweep sigma esterna/interna.'], ['fade_to_ema','mr-alt','Donchian/Bollinger fade ma TP all EMA(n) invece che SMA/centro-canale (target dinamico che segue il trend). Sweep n EMA.'], ['nbar_lowhigh_rsi','mr-alt','Entra long su nuovo minimo a N barre CON RSI<35 (doppia conferma di esaurimento), short speculare. TP a media, SL ATR. Sweep N.'], ['overshoot_swing_fade','mr-alt','Fada quando il prezzo supera lo swing-high/low precedente (Williams) di k*ATR e poi la barra chiude rientrando: false-breakout fade. Sweep k.'], // C. exit migliori sulla Donchian fade (stesso ingresso) ['tight_sl_confirm','exit','Donchian fade con SL piu stretto (1.0/1.5 ATR) ma close-confirm (esci solo se il close sfonda SL-0.5ATR). Replica EXIT-16. Sweep buffer.'], ['fast_tp_partial','exit','Donchian fade con TP a frazione del canale (0.25/0.5 width) invece che al centro: incassa prima il rimbalzo, riduce il tempo a rischio. Sweep frazione.'], ['short_timestop','exit','Donchian fade con time-stop corto (max_bars 6/8/12 invece di 24): esce prima che il whipsaw maturi. Sweep max_bars.'], ['atr_trailing_exit','exit','Donchian fade con uscita a ATR-trailing dopo l ingresso (trail il massimo favorevole di k*ATR). Sweep k. (la ricerca dice che il trailing spesso fallisce: verifica onestamente).'], ['breakeven_stop','exit','Donchian fade: dopo che il trade va in utile di +x*ATR, sposta lo stop a breakeven. Sweep x.'], ['rsi_exit','exit','Donchian fade con exit quando RSI torna oltre 50 (mean ripristinata) invece del TP fisso. Sweep.'], ['return_to_ema_exit','exit','Donchian fade con exit quando il prezzo ri-tocca l EMA(50) (ritorno alla media mobile) o max_bars. Sweep EMA.'], ['volscaled_maxbars','exit','Donchian fade con max_bars scalato sulla vol: meno barre in alta-vol, piu in bassa-vol. Sweep mapping.'], ['chandelier_exit','exit','Donchian fade con Chandelier exit (max favorevole - k*ATR). Sweep k.'], ['tp_opposite_band','exit','Donchian fade con TP alla banda OPPOSTA (reversione completa del canale) invece del centro. Piu ambizioso, meno frequente. Sweep.'], // D. trend-following su ETH (prende cio che la fade perde) ['ema_cross_4h','trend','EMA20/EMA100 cross su ETH 4h, long quando EMA20>EMA100, flat altrimenti (TR01-style su ETH solo). Niente fade. Valuta come diversificatore direzionale.'], ['donchian_breakout','trend','Donchian BREAKOUT trend (opposto del fade): long su rottura del massimo a N barre, stop sotto il minimo. La ricerca dice che i breakout crypto rientrano: verifica ONESTAMENTE se su ETH regge netto fee.'], ['macd_trend','trend','MACD(12,26,9) trend-following su ETH 1h/4h: long su cross rialzista sopra zero, exit su cross opposto. Sweep TF.'], ['dual_ma_atr','trend','Dual-MA (fast/slow) con filtro ATR sul gap: entra trend solo se separazione MA > k*ATR (evita whipsaw delle MA). Sweep.'], ['supertrend','trend','Supertrend (ATR band) su ETH: segui il flip. Sweep multiplier/periodo.'], ['momentum_sign','trend','Momentum semplice: long se rendimento a H barre > 0 (12h/24h/48h), tieni H barre. Time-series momentum su ETH. Sweep H.'], ['tsmom_eth','trend','TSMOM multi-orizzonte (3/6/12 mesi sul daily resample di ETH) con risk-off se sotto SMA100. Solo ETH. Valuta come diversificatore.'], ['breakout_vol_confirm','trend','Channel breakout con conferma di volume (rottura valida solo se volume>media*k). Sweep.'], ['heikin_trend','trend','Heikin-Ashi trend: long su serie di candele HA verdi, exit su prima rossa. Costruisci HA causale. Sweep.'], ['triple_screen','trend','Triple-screen: trend 4h (EMA) definisce il bias, ingresso 1h su pullback nella direzione del trend (no contro-trend). Sweep.'], // E. volatilita ['squeeze_expansion','vol','Bollinger-squeeze -> espansione, ma ingresso ONESTO: entra solo DOPO che la barra di espansione e CHIUSA, nella sua direzione, a close[i] (non anticipare). Verifica se l edge sparisce come per la famiglia squeeze scartata.'], ['atr_breakout','vol','ATR breakout: entra quando |close-close[-1]|>k*ATR nella direzione del movimento (continuazione) OPPURE contro (reversione) — testa entrambe e riporta quale regge. Sweep k.'], ['volofvol_revert','vol','Mean-reversion della vol-of-vol: quando la realized-vol fa uno spike estremo (z alto), fada il prezzo (gli spike di vol = capitolazione che rimbalza). Sweep.'], ['or_breakout_daily','vol','Opening-range breakout: definisci il range delle prime k ore UTC del giorno, entra sulla rottura con SL all altro lato. Sweep k. Trade ETH 1h.'], ['rv_regime_switch','vol','Switch fade/trend in base al regime di realized-vol: fade in bassa-vol (range), trend-follow in alta-vol. Una strategia adattiva. Sweep soglia.'], ['keltner_squeeze','vol','Keltner-inside-Bollinger squeeze: rileva la compressione, poi entra sulla direzione della prima rottura confermata (close oltre la banda). Onesto. Sweep.'], // F. cross-asset / relative ['btc_leadlag','cross','BTC lead-lag: il rendimento di BTC alla barra i predice ETH alla barra i+1. Entra ETH a close[i] nella direzione del segnale BTC (solo dati fino a i). Sweep soglia/horizon.'], ['ethbtc_ratio_revert','cross','Reversione del ratio ETH/BTC: quando il log-ratio devia >z*sigma dalla sua media, prendi posizione DIREZIONALE su ETH (long ETH se ratio depresso). Sweep n/z.'], ['eth_beta_residual','cross','Residuo beta: regredisci ETH su BTC (beta rolling causale), fada il residuo (ETH ricco/povero vs BTC). Posizione direzionale ETH. Sweep finestra.'], ['btc_trend_eth_fade','cross','Fade ETH SOLO quando BTC e in range (gia simile a btc_regime_fade ma qui il gate e la pendenza EMA di BTC + la sua DVOL). Combina due gate BTC.'], ['eth_vs_basket_mom','cross','Cross-sectional: ETH momentum relativo vs basket (BTC,BNB,SOL,XRP). Long ETH se sovra-performa il basket di recente (continuazione) o sotto-performa (reversione) — testa entrambe.'], ['funding_spread','cross','Spread di funding ETH-BTC (regime_lab): quando il funding di ETH e estremo vs BTC, prendi posizione di reversione su ETH. Sweep.'], // G. ML / shape ['sh01_logit_eth','ml','LogisticRegression stile SH01 su ETH: 17 feature di forma (body/shadow, rendimenti, pendenza, curvatura, pos max/min, RSI, estensione) su W24, predice segno a H12, walk-forward causale, entra se proba>0.58. Riusa scripts.analysis.shape_ml_research se possibile. ETH-specifico.'], ['analog_knn_eth','ml','Analog kNN sulla forma (shape_lab.analog_entries) su ETH: W/H/K sweep stretto, agree>0.6. Causale (KDTree ribuilt). Valuta come diversificatore.'], ['gbm_features_eth','ml','GradientBoostingClassifier walk-forward su feature ingegnerizzate (RSI, ATR-norm returns, distance-from-EMA, vol, Donchian-pos) per predire il segno a H barre. Train solo sul passato. Sweep H/threshold.'], ['logit_regime_mom','ml','LogReg walk-forward su feature di regime+momentum (DVOL, funding, ER, rendimenti multi-h) per predire direzione ETH a H. Da regime_lab. Sweep.'], ['rf_direction','ml','RandomForest walk-forward direzione ETH su feature tecniche. Train espandente. Sweep n_estimators/H/threshold. Onesto (no leakage temporale).'], ['ridge_return_sign','ml','Ridge regression walk-forward che prevede il rendimento a H barre; entra sul segno se |pred|>soglia. Feature: lag returns, RSI, ATR, distance-EMA. Sweep.'], // H. microstruttura / calendario ['intraday_seasonality','micro','Stagionalita oraria: trova le ore UTC con edge di reversione/continuazione su ETH (split-half per evitare overfit), trada solo quelle. Onesto su OOS.'], ['gap_fade','micro','Gap fade: quando una barra apre/chiude con un gap >k*ATR vs la precedente, fada il gap (reversione). Sweep k.'], ['hourofday_fade','micro','Fade Donchian condizionato all ora del giorno: attiva la fade solo nelle ore storicamente mean-reverting. Verifica OOS (rischio overfit alto: sii severo).'], ['dayofweek','micro','Effetto giorno-della-settimana su ETH: posizioni condizionate al weekday (es. weekend illiquido). Severo su OOS (probabile rumore).'], ['funding_settlement','micro','Timing settlement funding (00/08/16 UTC): fade del movimento attorno al settlement (over-reaction pre/post funding). Sweep finestra.'], ['large_candle_reversal','micro','Reversione dopo candela estesa: se |close-open|>k*ATR (barra-shock), entra contro alla chiusura della barra successiva. Sweep k.'], ['three_bar_reversal','micro','Pattern 3-barre: 3 chiusure consecutive nello stesso verso poi entra contro (esaurimento). Sweep n-barre/soglia.'], ['consecutive_exhaustion','micro','N candele rosse consecutive -> long (e speculare). Conta le streak causalmente, entra all N-esima. Sweep N. TP a media, SL ATR.'], // I. combinazioni / ensemble ['donchian_rsi_confirm','combo','Donchian fade CON conferma RSI (long solo se RSI<40 oltre alla rottura del canale): doppia conferma per ridurre i falsi segnali nei trend.'], ['bb_donchian_confluence','combo','Confluenza Bollinger + Donchian: fada solo quando ENTRAMBE le bande sono rotte simultaneamente (segnale piu forte, meno frequente, meno whipsaw).'], ['volspike_fade','combo','Fade solo su spike di volume (volume>media*k): la capitolazione su volume rimbalza meglio del drift silenzioso. Sweep k.'], ['funding_tailwind_fade','combo','Donchian fade con vento di funding: fada gli short (entra long) solo se funding positivo (i long pagano = pressione di unwind ribassista esaurita) e viceversa. Da regime_lab.'], ['regime_switch_classifier','combo','Classificatore di regime (trend vs range via ADX/ER/Hurst) che decide SE fadare o trend-followare ad ogni barra: una sola strategia adattiva. Sweep soglie del classificatore.'], ['vote_ensemble_mr','combo','Ensemble a voto di 3 segnali MR indipendenti (Bollinger, Donchian, z-return): entra solo se >=2 concordano sulla direzione. Riduce i falsi.'], ['adaptive_donchian','combo','Donchian a lookback ADATTIVO: n scalato sulla vol (canale piu lungo in alta-vol, piu corto in bassa-vol). Sweep mapping vol->n.'], // J. statistico-robusto ['ou_halflife','stat','Ornstein-Uhlenbeck: stima half-life e media di reversione (rolling, causale), entra quando la deviazione dalla media OU supera z*sigma, exit a half-life. Sweep.'], ['kalman_meanrev','stat','Kalman filter sul prezzo (livello+trend) come media dinamica; fada la deviazione dal livello stimato. Causale (filtro one-pass). Sweep Q/R.'], ['quantile_band_fade','stat','Bande a quantili rolling (5/95 percentile su finestra n) invece di sigma: fada la rottura del quantile, TP al quantile 50. Piu robusto a code fat. Sweep n/quantili.'], ['theilsen_residual','stat','Detrend Theil-Sen rolling (pendenza robusta), fada il residuo quando estremo. Sweep finestra.'], ['hampel_outlier_fade','stat','Hampel filter: identifica gli outlier (|x-median|>k*MAD) e fada l outlier (reversione). Sweep k/finestra.'], ['rollreg_residual_z','stat','Regressione lineare rolling (prezzo~tempo), z del residuo; fada |z|>soglia, TP a residuo 0. Sweep finestra/soglia.'], ['dominant_cycle_revert','stat','Stima del ciclo dominante (autocorrelazione/zero-cross rolling), entra in reversione in fase con il ciclo. Causale. Sweep.'], // K. ulteriori gate/varianti per arrivare a 112 ['choppiness_donchian','gated-fade','Choppiness Index + Donchian: fada solo se CI>61.8 (range conclamato). Variante severa di choppiness_gate_fade con soglia fissa Fibonacci. Sweep secondario su n.'], ['er_bollinger','gated-fade','Efficiency-Ratio gate su Bollinger fade (non Donchian): fada la banda solo se ER|2|), fada il prezzo nella direzione dell unwind atteso. Da regime_lab. Sweep.'], ['range_day_fade','gated-fade','Filtro range-day: fada solo se il range della sessione corrente (rolling 24h) < media*soglia (giornata compressa = reversione affidabile). Sweep.'], ['mtf_donchian','combo','Donchian multi-timeframe: ingresso su rottura del canale 1h ma con canale di riferimento 4h (TP al centro del canale 4h). Sweep n1/n4.'], ['volweighted_fade','combo','Fade pesata dal volume: ingresso solo se il volume della barra di segnale e nel quartile alto (conferma di partecipazione). Sweep.'], ['false_break_fade','mr-alt','Fade del falso breakout: il prezzo rompe il canale Donchian ma la barra SUCCESSIVA chiude di nuovo dentro -> entra contro la rottura a quella chiusura. Onesto. Sweep n.'], ['band_walk_exhaustion','mr-alt','Esaurimento del band-walk: dopo k chiusure consecutive fuori dalla banda Bollinger (band walking), fada il rientro alla prima chiusura dentro. Sweep k/sigma.'], ['pivot_revert','stat','Reversione ai pivot floor classici (P, R1/R2, S1/S2 calcolati sul giorno precedente): fada il tocco di R2/S2 verso P. Causale (pivot da ieri). Sweep.'], ['fractal_swing_revert','stat','Reversione agli swing di Williams (frattali a 5 barre confermati con ritardo): fada il tocco di un nuovo frattale verso la media. Causale (conferma ritardata). Sweep.'], ['lrc_fade','stat','Linear Regression Channel: canale di regressione rolling +/- 2 std del residuo; fada il tocco dei bordi verso la linea centrale. Sweep finestra.'], ] // ---------------------------------------------------------------- esecuzione phase('Generate') log(`Lancio ${SPECS.length} agenti, una strategia ETH distinta ciascuno (harness onesto fee-aware OOS)`) const results = await parallel(SPECS.map(([key, family, idea]) => () => agent( `${RECIPE}\n\n========\nLA TUA IDEA — key="${key}", family="${family}":\n${idea}\n\nUsa /tmp/cand_${key}.py come file. Restituisci il risultato strutturato (campi key e family valorizzati con i tuoi).`, { label: `gen:${key}`, phase: 'Generate', schema: SCHEMA } ).then(r => r ? { ...r, key, family } : null) )) const ran = results.filter(Boolean) log(`${ran.length}/${SPECS.length} agenti rientrati. Filtro i survivor per la verifica avversariale.`) // survivor: ha girato davvero, e o batte la baseline o e' chiaramente interessante // (OOS Sharpe alto, oppure DD ben piu basso a Sharpe decente), e regge la fee 0.2%. const survivors = ran.filter(r => r.ran_ok && r.implemented && r.no_lookahead && r.full_ret > 0 && r.oos_ret > 0 && r.fee02_oos > 0 && r.fee02_full > 0 && ( r.beats_baseline || r.oos_sharpe >= 11.0 || (r.full_dd <= 20.0 && r.oos_sharpe >= 8.0) || (r.full_dd <= 12.0 && r.oos_sharpe >= 5.0) // diversificatore a basso DD ) ) // ordina per una metrica composita: premia OOS Sharpe e penalizza DD const score = r => r.oos_sharpe - 0.10 * r.full_dd survivors.sort((a, b) => score(b) - score(a)) const toVerify = survivors.slice(0, 24) // cap la verifica ai 24 migliori log(`${survivors.length} survivor; verifico avversarialmente i top ${toVerify.length}`) phase('Verify') const VSCHEMA = { type: 'object', additionalProperties: false, required: ['key','confirmed','reproduced','lookahead_found','overfit_risk','full_sharpe','full_dd','oos_sharpe','oos_dd','beats_mr02eth','note'], properties: { key: { type: 'string' }, confirmed: { type: 'boolean', description: 'edge reale, eseguibile, fee-robusto, dopo audit indipendente' }, reproduced: { type: 'boolean', description: 'ho ri-eseguito e ho ottenuto numeri coerenti (entro ~15%)' }, lookahead_found: { type: 'boolean' }, overfit_risk: { type: 'string', enum: ['low','med','high'] }, full_sharpe: { type: 'number' }, full_dd: { type: 'number' }, oos_sharpe: { type: 'number' }, oos_dd: { type: 'number' }, beats_mr02eth: { type: 'boolean', description: 'batte davvero MR02/ETH (OOS Sharpe>=~12 a DD<=25, o DD<20 a Sharpe comparabile)' }, note: { type: 'string' }, }, } const verified = await parallel(toVerify.map(r => () => agent( `Verifica AVVERSARIALE di una strategia candidata a sostituire MR02/ETH. Lavora in /opt/docker/PythagorasGoal con l'harness onesto scripts.analysis.explore_lab (get_df, simulate, evaluate, robust, atr, ema, rsi). Default: il tuo compito e' SMENTIRE.\n\n${BASELINE}\n\nCandidata key="${r.key}" (family ${r.family}).\nConfig dichiarata: ${r.best_config}\nNumeri dichiarati: full Sharpe ${r.full_sharpe}, OOS Sharpe ${r.oos_sharpe}, full DD ${r.full_dd}%, OOS DD ${r.oos_dd}%, trade ${r.trades}, exposure ${r.exposure}%, fee0.2% full ${r.fee02_full}, fee0.2% OOS ${r.fee02_oos}.\nDescrizione idea: la trovi rifacendola da zero.\n\nRI-IMPLEMENTA tu stesso la strategia (in /tmp/verify_${r.key}.py) sulla SUA config dichiarata, eseguila sull'harness, e controlla: (1) LOOK-AHEAD — l'ingresso/direzione usa solo dati fino a close[i]? Perturba le barre future e verifica che gli entries non cambino. (2) RIPRODUCIBILITA — i numeri tornano entro ~15%? (3) ROBUSTEZZA/OVERFIT — regge a fee 0.20% RT, a piccole variazioni dei parametri (plateau, non picco isolato), ed e' positiva nella maggior parte degli anni 2021+? (4) batte DAVVERO MR02/ETH (OOS Sharpe e/o DD)?\n\nSe non riesci a riprodurre o trovi look-ahead, confirmed=false. Riporta i TUOI numeri ri-eseguiti, non quelli dichiarati. Sii severo: meglio bocciare un falso positivo che promuovere un artefatto.`, { label: `verify:${r.key}`, phase: 'Verify', schema: VSCHEMA } ).then(v => v ? { ...v, key: r.key, family: r.family, gen: r } : null) )) const vok = verified.filter(Boolean) const confirmed = vok.filter(v => v.confirmed && !v.lookahead_found && v.beats_mr02eth) confirmed.sort((a, b) => (b.oos_sharpe - 0.1 * b.full_dd) - (a.oos_sharpe - 0.1 * a.full_dd)) log(`Verifica completata: ${confirmed.length} confermati che battono MR02/ETH`) return { n_specs: SPECS.length, n_ran: ran.length, n_survivors: survivors.length, n_verified: vok.length, n_confirmed: confirmed.length, confirmed, all_survivors: survivors.map(s => ({ key: s.key, family: s.family, best_config: s.best_config, full_sharpe: s.full_sharpe, full_dd: s.full_dd, oos_sharpe: s.oos_sharpe, oos_dd: s.oos_dd, exposure: s.exposure, trades: s.trades, fee02_oos: s.fee02_oos, verdict: s.verdict, note: s.note })), verified: vok.map(v => ({ key: v.key, confirmed: v.confirmed, reproduced: v.reproduced, lookahead_found: v.lookahead_found, overfit_risk: v.overfit_risk, beats_mr02eth: v.beats_mr02eth, full_sharpe: v.full_sharpe, full_dd: v.full_dd, oos_sharpe: v.oos_sharpe, oos_dd: v.oos_dd, note: v.note })), }