Run phase1.5-nemotron-001 completato in 2h26min, costo $0.1244. Max fitness 0.0215 stagnante (15x peggio del baseline qwen 0.3347), DSR=0 universale, Sharpe -1.08/-1.15. Loop non converge. Adversarial Phase 1.5 attivo: 98 finding totali, 35 fees_eat_alpha HIGH + 15 flat_too_long + 8 time_in_market — i 3 nuovi check killano correttamente, ma popolazione non ha materiale sano da cui evolvere. Tre direzioni candidate per Phase 2: A) rollback qwen-2.5-72b, B) prompt re-tuning nemotron, C) promuovere deepseek-v4-flash. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8.5 KiB
Phase 1.5 — Run nemotron tier C — Decision Memo
Data: 11 maggio 2026
Run di riferimento: phase1.5-nemotron-001 (id 434c417e2b6f42bb8cf32514e5d0db1d)
Tier LLM: C → nvidia/nemotron-3-super-120b-a12b:free
Durata wallclock: 2 h 26 min (08:15 → 10:11 UTC, gen 0 → gen 9)
Spesa totale: $0.1244 (price-table tier C; il modello effettivo è :free su OpenRouter, ma il cost tracker applica la pricing nominale del tier)
Status: ✅ Completato, ma esito strategico NO-GO sulla configurazione corrente
1. Premessa
Il run phase1.5-nemotron-001 è la prima esecuzione end-to-end del loop GA con:
- l'Adversarial layer aggiornato in Phase 1.5 (commits
56a631f+d3662f6), con tre nuovi check HIGH (flat_too_long,fees_eat_alpha,time_in_market_too_high) più i due esistenti rinforzati; - il tier C ribindato a
nvidia/nemotron-3-super-120b-a12b:free, modello scelto in benchmark contro sette alternative per stabilità JSON e costo nullo; - il fix
EmptyCompletionErrorsullm/client.py(commit9d0deb3) introdotto durante la stessa sessione per gestire le risposte vuote che alcuni provider:freeritornano sporadicamente.
L'obiettivo dichiarato del run era verificare se il nuovo budget di vincoli adversarial — più stretto del v5 — fosse compatibile con la capacità generativa di nemotron, e se la popolazione riuscisse a esplorare una zona di fitness positiva non degenere.
2. Hard gate Phase 1 — ripercorrenza
I 5 hard gate originali (definiti nello spec strategico di Phase 1) sono stati rivalutati su questo run come sanity check, non come passaggio formale di gate.
| # | Gate | Soglia | Misura | Esito |
|---|---|---|---|---|
| 1 | Loop converge | mediana cresce ≥3 gen consecutive | Gen 0→8: median oscilla tra 0.0 e 0.0073 senza crescita strutturale | ❌ FAIL |
| 2 | Parse success | ≥80% proposte LLM parse-OK | 81/89 = 91.0% | ✅ PASS |
| 3 | Top-5 ratio | top-5 fitness ≥10× mediana | top-5 = 0.0162–0.0215; mediana ≈ 0 → ratio indefinito | ⚠️ N/A |
| 4 | Entropy | ≥0.5 a fine run | 0.845 alla gen 9 | ✅ PASS |
| 5 | Budget | costo ≤ cap | $0.1244 vs cap $700 (0.02%) | ✅ PASS |
Il gate critico è il numero 1. La popolazione non converge: il max_fitness resta inchiodato a 0.0215 dalla generazione 0 fino alla 9, segnale che l'elite preservation cattura un singolo genoma poco peggiore degli altri ma altrettanto inadatto, mentre il resto della popolazione non riesce a superarlo. La mediana è zero in 9 generazioni su 10 (singolo picco a 0.0073 in gen 8).
3. Lettura dei top genomi
I cinque genomi a fitness più alta hanno tutti caratteristiche economicamente disastrose:
| Genome ID | Fitness | DSR | Sharpe | Total return | n_trades |
|---|---|---|---|---|---|
0e1f9d7af25cfd6a |
0.0215 | 0.000 | −1.083 | −115.9% | 385 |
85a8116ab2cd2735 |
0.0215 | 0.000 | −1.083 | −115.9% | 385 |
92aae563277b6f21 |
0.0193 | 0.000 | −1.129 | −131.0% | 597 |
01d0ca99bbdd7320 |
0.0180 | 0.000 | −1.112 | −131.7% | 602 |
194b096f7edab53c |
0.0162 | 0.000 | −1.154 | −150.7% | 369 |
Il fatto che DSR sia zero per tutti i top-5 indica che nessuna strategia passa il deflation test di Bailey & López 2014: il loop non sta generando proposte con edge statistico anche solo apparente. Il valore di fitness positivo che li seleziona deriva interamente dal termine tanh(sharpe) × penalty(dd) della fitness v1, che resta debolmente non nullo anche per Sharpe negativi grazie alla penalty di drawdown e a saturazioni numeriche. I primi due genomi hanno fitness identico a 0.0215 e total return identico — verosimilmente lo stesso elite riproposto a generazioni adiacenti.
4. Adversarial findings — il sistema fa il suo lavoro
Il layer Adversarial Phase 1.5 ha emesso 98 finding sul run:
| Severità | Check | Conteggio |
|---|---|---|
| HIGH | fees_eat_alpha (nuovo P1.5) |
35 |
| MEDIUM | overtrading |
19 |
| HIGH | no_trades |
16 |
| HIGH | flat_too_long (nuovo P1.5) |
15 |
| HIGH | time_in_market_too_high (nuovo P1.5) |
8 |
| HIGH | undertrading |
4 |
| HIGH | degenerate |
1 |
Il dato saliente è che i tre check introdotti in Phase 1.5 — fees_eat_alpha, flat_too_long, time_in_market_too_high — sono effettivamente attivi e killano strategie. In particolare fees_eat_alpha è la categoria più popolata: 35 occorrenze HIGH. Esempi tipici dai detail dei finding:
Fees $17073.82 = 2032.6% of gross $840.00;Fees $70646.03 = 12671.9% of gross $557.50;Signal flat for 98.8% of bars (>95% threshold).
Il messaggio è netto: il pool di strategie generato da nemotron, ai prompt e ai gradi di libertà attuali, oscilla tra due estremi degeneri — strategie inattive (flat 98%+) e strategie iperattive (overtrading + fee che divorano l'alpha lordo). Phase 1.5 cattura entrambi gli estremi, ma il loop GA non ha materiale di partenza sano da cui evolvere.
5. Decisione
Esito: NO-GO sulla combinazione tier C = nemotron + Phase 1.5 adversarial come configurazione di Phase 2.
Le ragioni a supporto della decisione sono tre.
Primo, la convergenza è assente per nove generazioni consecutive, non un plateau di selezione raggiunto dopo una fase di salita. Non si tratta cioè di un loop che ha già trovato il suo ottimo e lo conserva, ma di un loop che non ne ha trovato uno.
Secondo, la distanza dal baseline Phase 1 v5 è di un ordine di grandezza: max fitness 0.0215 qui contro 0.3347 nel run di gate Phase 1, mediana che oscilla sullo zero contro una mediana attorno a 0.005–0.09. Nemotron, in questa configurazione, sta producendo proposte qualitativamente più povere di qwen-2.5-72b nello stesso schema operativo.
Terzo, i finding adversarial non puntano a un bug del sistema ma a una mancanza di edge nelle proposte. Il loop sta sanzionando correttamente — il problema è a monte, nella generazione.
6. Tre direzioni per Phase 2
Tre opzioni si configurano per il passo successivo. Vanno valutate prima di una nuova esecuzione, non in parallelo a essa.
Direzione A — Riportare tier C a qwen/qwen-2.5-72b-instruct (configurazione di gate Phase 1). Il run di riferimento phase1-real-005 è già un baseline noto: max fitness 0.3347, top genome problematico (flat 99.8%) ma generato sotto Phase 1 adversarial. Rilanciare lo stesso pool con Phase 1.5 adversarial isolerebbe l'effetto del solo hardening sul medesimo motore generativo, senza confondere variabili. Questo è il percorso più informativo nel breve.
Direzione B — Mantenere nemotron ma rilassare i prompt di Hypothesis. L'ipotesi alternativa è che il prompting attuale, calibrato su qwen, sia troppo terso o troppo vincolato per la modalità di ragionamento di nemotron. Iterare due o tre versioni del prompt — più esempi few-shot, vincoli espliciti su n_trades minimo e time_in_market target — può cambiare radicalmente la qualità dell'output senza cambiare il modello.
Direzione C — Sostituire il tier C con un modello a pagamento di fascia comparabile. Tra i benchmark precedenti, deepseek/deepseek-v4-flash è già usato come tier A/B nel file .env; promuoverlo a tier C significa accettare una spesa marginale (stima $1–3 per run di 10 gen × 20 pop) in cambio di una qualità generativa nota.
La preferenza dell'operatore per modelli cost-conscious orienta verso A o B. La direzione C resta utile come benchmark di controllo se A e B fallissero a loro volta.
7. Operazioni di pulizia eseguite contestualmente
- Il run zombie
phase1-real-008(id6ebcff9f7f6544c18ced50313cf72ca9, marcatorunningda 07:11 UTC senza processo associato) è stato chiuso astatus='failed'direttamente inruns.db, per evitare contaminazione delle query di dashboard. - Il commit
9d0deb3(fix(llm): handle empty completions + missing usage) è già sumain. Ilclient.pyora trattaresp.choices == []eresp.usage is Nonecome errori retryable invece che assertion failure: precondizione necessaria per qualsiasi run successivo su provider:free.
8. Note per chi legge
Questo memo è un documento di decisione, non un rapporto tecnico completo. Il rapporto tecnico esteso del run può essere ricostruito da runs.db interrogando le tabelle runs, generations, evaluations, adversarial_findings, cost_records con run_id='434c417e2b6f42bb8cf32514e5d0db1d'. Il design Phase 1.5 e le motivazioni delle soglie adversarial restano definiti nel commit 56a631f e nei suoi file di test.