Phase 1 chiusa con tutti i 5 hard gate passati (run phase1-real-005): - Loop converge: 3 gen consecutive crescita median 0.0001 -> 0.0188. - Parse success: 100% (98/98) grazie a JSON grammar. - Top-5 vs median: 1116x ratio (top-1 fit 0.3347 vs median 0.0003). - Entropy fitness: 0.914 a gen 9 (sopra soglia 0.5). - Cost: $0.069 reale vs $700 cap. Decision: GO Phase 2 con 3 aggiustamenti (Adversarial soglie piu' strette, speciation di base, walk-forward 70/30). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
17 KiB
Phase 1 Lean Spike — Rapporto Tecnico
Autore: Adriano Dal Pastro Data: 10 maggio 2026 Versione: 1.0 (finalizzato) Status: ✅ Phase 1 chiusa, tutti 5 hard gate passati
Documenti correlati:
docs/superpowers/specs/2026-05-09-decisione-strategica-design.md(decisione strategica B3)docs/superpowers/plans/2026-05-09-phase1-lean-spike.md(piano implementativo)docs/decisions/2026-05-10-gate-phase1.md(decision memo finale)
1. Setup sperimentale
L'obiettivo della Phase 1 lean spike è dimostrare che il loop tecnico (LLM hypothesis → backtest falsification → adversarial check → GA selection) funziona end-to-end e produce output formalizzabile. I cinque hard gate definiti nello spec sez. 4.4 misurano feasibility, non alpha edge — quella è valutazione di Phase 2.
1.1 Configurazione del run di riferimento
Il run phase1-real-005 (id 1c526996160446b18c0fb57d94874975) è il primo a superare tutti i gate dopo 4 iterazioni di bug-fix (vedi sez. 3 del decision memo).
| Parametro | Valore |
|---|---|
| Population size (K) | 20 |
| Generazioni | 10 |
| Elite k | 2 |
| Tournament k | 3 |
| Crossover probability | 0.5 |
| Random seed | 42 |
| Symbol | BTC-PERPETUAL (Deribit) |
| Timeframe | 1h |
| Range storico | 2024-01-01 → 2026-01-01 (2 anni, 17545 candele) |
| Fees backtest | 5 basis points |
| n_trials_dsr | 50 |
| Tier LLM dominante | C (qwen3-235b-a22b-2507 via OpenRouter) |
| Cerbero MCP endpoint | http://localhost:9001 (locale) |
| Durata wall-clock | 29 minuti |
| Costo LLM | $0.069 |
1.2 Stack tecnologico
Python 3.13, uv 0.10.9. Test framework: pytest + pytest-mock + responses. Persistence: sqlite3 + sqlmodel. Parsing strategia: json.loads con dataclass-based AST. Analytics: pandas + numpy + scipy. LLM: openai SDK con base URL OpenRouter (route unica per tutti i tier S/A/B/C/D). HTTP: requests + tenacity. Dashboard: streamlit + plotly + canvas HTML5 custom.
1.3 Architettura del run
L'orchestrator (src/multi_swarm/orchestrator/run.py, 184 righe) coordina la pipeline end-to-end:
- OHLCV loading:
CerberoOHLCVLoaderchiamamcp-deribit/tools/get_historicalpaginando in chunk da 4500 barre (cap soft Deribit ~5000). Cache parquet su sha1 della query — il run v5 ha riusato cache popolata dai run precedenti, fetch istantaneo. - Market summary: statistiche return (mean, std, skew, kurt) + classificazione regime volatilità.
- Initial population: 20 genomi distribuiti uniformemente sui 6 cognitive style (physicist, biologist, historian, meteorologist, ecologist, engineer), temperature random in [0.7, 1.2], lookback random in {100, 150, 200, 300}.
- Per ogni generazione (10 totali):
- Hypothesis: chiamata LLM con prompt SYSTEM (regole grammar) + USER (market summary). Output JSON estratto via regex fence ```json. Se parse/validation fallisce: retry 1x con error message nel prompt utente.
- Falsification: AST compilato in
Callable[[df], Series[Side]], backtest event-driven con 1-bar exec delay, calcolo Sharpe + Deflated Sharpe (Bailey & López 2014, n_trials=50). - Adversarial: 4 check euristici (no_trades, degenerate, overtrading, undertrading).
- Fitness:
0.5*dsr + 0.25*(tanh(sharpe)+1)×1/(1+max_dd), range [0, ~1]. Kill (=0) su zero trade o HIGH adversarial finding. - Next generation: elitism 2 + tournament 3 + 50% crossover / 50% mutation.
- Persistence SQLite: ogni genome, evaluation, cost_record, adversarial_finding, generation summary persistito con indici per query rapide della dashboard.
1.4 Caveat metodologici noti
- In-sample: il backtest in Phase 1 lean spike non usa walk-forward; tutto il range 2024-2026 viene usato sia per la generazione delle ipotesi sia per la loro valutazione. La sopravvivenza out-of-sample è esplicitamente fuori scope di Phase 1 (gate Phase 2 #2).
- Compiler con indicatori built-in: il compiler JSON-based (
src/multi_swarm/protocol/compiler.py) calcola RSI, SMA, ATR, MACD, realized_vol localmente con pandas.CerberoToolsè plumbed ma non chiamato durante l'esecuzione delle strategie — è disponibile per agenti future-tense ma il fitness Phase 1 dipende solo dagli indicatori locali. - RSI epsilon-floor: il compiler ha un epsilon sul
roll_downper evitare RSI=100 esatto su serie monotonicamente crescenti (artefatto matematico irrilevante su dati reali ma documentato). - Top-1 strategia con DSR marginale: vedi sez. 3.
2. Loop convergence
2.1 Fitness per generazione
| Gen | Median | Max | P90 | Entropy |
|---|---|---|---|---|
| 0 | 0.0001 | 0.0601 | 0.0165 | 0.588 |
| 1 | 0.0042 | 0.1893 | 0.0731 | 1.261 |
| 2 | 0.0188 | 0.3347 | 0.2039 | 1.333 |
| 3 | 0.0069 | 0.3347 | 0.3347 | 1.347 |
| 4 | 0.0910 | 0.3347 | 0.3347 | 1.415 |
| 5 | 0.0016 | 0.3347 | 0.3347 | 0.611 |
| 6 | 0.0040 | 0.3347 | 0.3347 | 0.886 |
| 7 | 0.0151 | 0.3347 | 0.3347 | 0.982 |
| 8 | 0.0066 | 0.3347 | 0.3347 | 0.746 |
| 9 | 0.0061 | 0.3347 | 0.3347 | 0.914 |
2.2 Lettura
Convergenza tre-step iniziale: gen 0→1→2 mostra crescita mediana 4x-50x (0.0001 → 0.0042 → 0.0188) e crescita max 3x-6x (0.06 → 0.19 → 0.33). Gate 1 PASS su questa finestra.
Plateau dell'elite da gen 2: max stabile a 0.3347 per le restanti 7 generazioni — comportamento atteso con elite_k=2 che preserva il top performer attraverso le generazioni. P90 si allinea al max da gen 3, segno che almeno 2 elite mantengono la top fitness.
Median oscillante: dopo il picco a gen 4 (0.091), la median fluttua fra 0.0016 e 0.0151 nelle generazioni successive. Causa: turnover stocastico della popolazione (mutation + crossover) introduce genomi nuovi, alcuni dei quali parse correctly ma falliscono Adversarial (no_trades) e si attestano a fitness 0, abbassando la median. Non è regressione strutturale del GA.
Entropy: oscilla 0.6-1.4 dopo gen 0, sempre sopra soglia 0.5 → diversità di fitness preservata anche durante plateau dell'elite.
3. Top-5 genomi: ispezione qualitativa
| Rank | Genome ID | Gen | Style | Fitness | DSR | Sharpe | Max DD | Trades | Temp |
|---|---|---|---|---|---|---|---|---|---|
| 1 | 696052b8... |
2 | physicist | 0.3347 | 0.0021 | 0.381 | 0.0215 | 33 | 0.68 |
| 2 | 169376a2... |
1 | engineer | 0.3347 | 0.0021 | 0.381 | 0.0215 | 33 | 0.78 |
| 3 | eb0265ad... |
3 | ecologist | 0.2453 | 0.0006 | −0.019 | 0.0011 | 1 | 1.14 |
| 4 | 38d4c1d9... |
1 | engineer | 0.1893 | 0.0001 | −0.245 | 0.0028 | 1 | 0.82 |
| 5 | 3e355975... |
1 | physicist | 0.1893 | 0.0001 | −0.245 | 0.0028 | 1 | 0.78 |
3.1 Top-1 strategia (ispezione approfondita)
System prompt (engineer): "Cerca segnali con rapporto S/N favorevole, filtri causali, robustezza a perturbazioni di calibrazione."
Strategia JSON (3 regole, evaluation in ordine):
- LONG:
SMA(10) crossover SMA(30)ANDrealized_vol(20) > 0.3%ANDRSI(14) < 45. - SHORT:
SMA(10) crossunder SMA(30)ANDrealized_vol(20) > 0.3%ANDRSI(14) > 55. - EXIT: (
RSI(14) > 70ANDclose crossover SMA(50)) ORrealized_vol(20) < 0.1%.
Lettura economica: trend-following SMA-cross fast/slow modulato da filtro volatilità (entra solo quando il regime è abbastanza mosso, esce quando è troppo calmo) e filtro RSI come momentum confirmation (long solo se non già ipercomprato; short solo se non già ipervenduto). L'EXIT è sofisticato: esce su overbought confermato da break sopra MA50, OPPURE su collasso di volatilità.
Performance: 33 trade su 17545 candele (1 trade ogni 532 candele = 1 ogni 22 giorni). Sharpe positivo modesto, max drawdown 2.15% (basso). DSR praticamente zero (0.0021) — il segnale non è statisticamente significativo dopo correzione multiple testing, perché 33 trade su 2 anni è sample piccolo.
Plausibilità: pattern economicamente sensato, non casuale. Reminiscente di strategie trend-following classiche (Donchian, turtle-style) con filtri di regime. Lo stile cognitivo "engineer" (S/N favorable, filtri causali) si riflette nella struttura.
3.2 Top-2/3/4/5 brevemente
- Top-2 è una replica funzionale di Top-1 con metriche identiche. Plausibile elite duplicato o convergenza indipendente sulla stessa strategia (verifica per Phase 2: signal correlation fra duplicati).
- Top-3, 4, 5 hanno 1 trade ciascuno su 2 anni. Sono "lucky shot": una posizione tenuta a lungo che casualmente termina con leggera vincita. Adversarial flagga MEDIUM
undertradingma non HIGH, quindi sopravvivono. La fitness function continua dà loro valore non-zero perchétanh(sharpe)è leggermente sopra 0.5 e penalty drawdown è quasi 1.0 (max_dd <0.5%).
3.3 Ratio top-1 / median
Median fitness su 98 evals: 0.0003. Top-1 fitness: 0.3347. Ratio: 1116x — Gate 3 soddisfatto con margine drammatico (soglia 1.5x).
4. Parser failure modes
4.1 Statistiche aggregate v5
- Evaluations totali: 98
- Parse success: 98 (100.0%)
- Parse failure: 0 (0.0%)
4.2 Confronto con iterazioni precedenti
| Run | Grammar | Parse success | Note |
|---|---|---|---|
| v1 | S-expression | 33% | LLM nesta indicators non supportati |
| v4 | S-expression (con arity check post-fix) | 36% | 89 di 98 errori = indicator nested |
| v5 | JSON Schema | 100% | Refactor commit 44eb643 |
Il salto da 36% a 100% deriva interamente dal cambio di grammar. JSON è natively supported dal training dei modelli LLM moderni; S-expression è esotica e induce hallucination di sintassi creative.
4.3 Retry-with-feedback (commit d4fcb42)
Il sistema accetta 1 retry con error feedback. Nel run v5 il retry non è mai stato usato (zero retry per parse, dato il 100% di success). Il retry rimane comunque architetturalmente presente per Phase 2 / casi edge.
5. Costi reali vs preventivo
5.1 Breakdown costi LLM v5
| Tier | Calls | Input tokens | Output tokens | Cost USD |
|---|---|---|---|---|
| C (qwen3-235b) | 113 | 112369 | 60060 | $0.069 |
5.2 Costo cumulativo Phase 1 (5 run, inclusi bug-fix iterations)
| Run | Cost | Note |
|---|---|---|
| v1 (aborted) | $0.034 | 67% parse_error, max_dd bug |
| v2 (aborted) | $0.018 | macd 3 args, OHLCV cap discovery |
| v3 (aborted) | $0.015 | crash su indicator arity |
| v4 (completed FAIL) | $0.057 | 36% parse, fitness tutti 0 |
| v5 (completed PASS) | $0.069 | tutti gate passati |
| Totale Phase 1 | $0.193 | — |
5.3 Confronto con preventivo
- Preventivo originale (basato su pricing Anthropic Sonnet): $500-700.
- Spesa reale Phase 1 totale: $0.19.
- Deviazione: −99.97%.
La differenza non è dovuta a underuse — il run v5 ha fatto 113 chiamate LLM = full saturazione del budget previsto di calls. È un cambio di ordine di grandezza nei prezzi dovuto al pricing aggressivo di OpenRouter per modelli open-weights (qwen3-235b è 7.5x più economico di Sonnet su input, 37x su output). Il preventivo originale era calibrato su Sonnet 4.6.
5.4 Implicazioni per Phase 2
Il margine economico permette di pianificare Phase 2 con maggiore aggressività senza superare il cap ($700-1100):
- K=40 (×2), gen=15 (×1.5), tier mix 30% B / 70% C, ablation runs multiple.
- Estrapolazione lineare conservativa: $0.07 × 2 × 1.5 × ~3 (tier B factor) × 5 (ablation) = ~$3 totali. Possibile spingere a $30-50 senza preoccupazioni se serve per ablation più ricche.
Rischio cost-trap inverso: tentazione di sovra-dimensionare Phase 2 perché "tanto costa nulla". Mantenere disciplina budget invariata — investire i $700 cap in PIÙ ablation, non in run più grandi.
6. Diversity metrics
6.1 Entropy fitness per generazione
Vedi tabella sez. 2.1 colonna entropy. Mai sotto 0.5, picco a gen 4 (1.415).
6.2 Cognitive style sopravvissuti gen 9
| Stile | Count gen 9 | Avg fitness | Note |
|---|---|---|---|
| engineer | 3 | 0.0 | Dominante numericamente ma fitness 0 (genomi recent, non valutati su elite) |
| physicist | 1 | 0.0598 | Solo presente nel top-K |
| historian | 1 | 0.0002 | — |
| biologist | 0 | — | Estinto |
| meteorologist | 0 | — | Estinto |
| ecologist | 0 | — | Estinto |
Lettura: pressione selettiva ha eliminato 3 di 6 stili cognitivi alla generazione finale. Engineer è dominante numericamente, physicist domina nel valore (l'unico con fitness >0 della popolazione "live" gen 9). Phase 2 deve introdurre speciation esplicita per evitare questo collasso (minimum 2-3 specie protette).
6.3 Trade distribution sui 98 evals
| Categoria | n | % |
|---|---|---|
| Zero trade (HIGH no_trades, kill) | 42 | 42.9% |
| Undertrading (1-4 trade, MEDIUM) | 5 | 5.1% |
| Normal (5-100 trade) | 9 | 9.2% |
| Overtrading (>100 trade, NON flaggato) | 42 | 42.9% |
Issue identificato: il 42.9% di overtrading non viene catturato dall'Adversarial perché la soglia attuale è n_trades > n_bars/5 = 3509 — troppo alta per essere triggerata su 1000-2000 trade. Phase 2 dovrebbe abbassare a n_bars/20 = 877 o usare metrica relativa al regime.
6.4 Adversarial findings totali
| Finding | Severity | Count |
|---|---|---|
| no_trades | HIGH | 42 |
| undertrading | MEDIUM | 5 |
Niente degenerate né overtrading flaggato. Il primo è raro (richiede strategia sempre-LONG o sempre-SHORT puro), il secondo soffre della soglia troppo alta.
7. Threats to validity
Lista esplicita dei limiti metodologici da non sovra-interpretare:
- In-sample fitting: tutto il backtest è in-sample. Il top-1 ha Sharpe 0.38 ottenuto guardando i dati su cui è stato selezionato. Phase 2 (walk-forward + hold-out Q1-Q2 2026 intoccabile) misura overfitting reale.
- Tier C unico: nessun confronto contro tier B/S. Possibile underperformance del LLM economico vs Sonnet/Opus. Phase 2 introduce ablation multi-tier.
- Adversarial hand-crafted: 4 check euristici (no_trades, degenerate, overtrading, undertrading). Phase 2 introduce 5 prompt LLM-driven dedicati (data snooping, lookahead, regime fragility, crowding, transaction cost erosion).
- Fitness function v1: lineare in DSR + tanh(Sharpe) normalizzato + drawdown moltiplicativa. Non multi-livello (per-team, anti-collusion). Phase 2 introduce.
- No speciation, no novelty bonus: cognitive style scendono da 6 a 3 a gen 9. Phase 2 deve mitigare.
- DSR del top-1 = 0.0021: il "successo" del Gate 3 è guidato da Sharpe (positivo modesto), non da significatività statistica vera. Senza walk-forward + multiple testing rigoroso, non si può affermare alpha edge.
- Top-3/4/5 sono "lucky shot" 1-trade: la fitness function continua li promuove perché drawdown bassissimo + sharpe leggermente negativo, ma sono artefatti. Phase 2 promuove undertrading a HIGH se
n_trades < 10. - Cerbero/Deribit data quality: nessuna detection di gap, outlier, exchange downtime. Da affrontare prima di forward-test (Phase 3).
- Cost predictability inverso: Phase 2 deve resistere alla tentazione di sovra-dimensionare perché Phase 1 è costata $0.19.
8. Conclusioni e implicazioni per Phase 2
Hard gate sintesi: ✅ 5 su 5 passati.
Decisione finale: GO Phase 2 (formalizzata nel decision memo).
Apprendimenti chiave per Phase 2:
- JSON >> S-expression per grammar LLM-generated. Phase 2 non rivisita.
- Fitness continua è essenziale per dare gradient al GA, ma può promuovere strategie degeneri (1-trade) che vanno killate diversamente.
- OpenRouter qwen3-235b è sorprendentemente capace per generare strategie strutturate, dato un prompt schema-rigoroso. Tier B (Sonnet) potrebbe non essere necessario al 30% come pianificato; ablation Phase 2 misurerà il vero contributo.
- Cerbero MCP come single source of truth funziona: paginazione, cache parquet, audit log integrati senza fragility.
- Bug-fix discovery via run reale è efficiente: 4 cicli, ognuno ha esposto un problema specifico (max_dd math, macd arity, validator arity, fitness clamp, grammar choice). Phase 2 può aspettarsi pattern simile per nuove componenti (speciation edge cases, OOS overfitting, multi-tier dispatch).
Riusabilità del codebase Phase 1: il design modulare (data, backtest, metrics, cerbero, protocol, genome, llm, agents, ga, persistence, orchestrator, dashboard) è riusabile direttamente. Estensioni Phase 2:
ga/speciation.py(nuovo) — clustering cosine similarity prompt, quota tournament per specie.ga/fitness.py— versione v2 con novelty bonus + per-team aggregation.orchestrator/run.py— integrazione walk-forward.agents/adversarial_llm.py(nuovo) — 5 prompt LLM-driven.baseline/random_forest.py(nuovo) — RF baseline per benchmark.
Costo stimato Phase 2: $3-15 (estrapolazione molto conservativa). Cap rimane $700-1100 invariato per disciplina.
Tempo stimato Phase 2: 4-6 settimane di lavoro calendar, includendo i 3 aggiustamenti del decision memo (Adversarial soglie, speciation, walk-forward).
Documento finalizzato 10 maggio 2026. Versione 1.0.