943aa38cf2
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>
283 lines
17 KiB
Markdown
283 lines
17 KiB
Markdown
# 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:
|
||
|
||
1. **OHLCV loading**: `CerberoOHLCVLoader` chiama `mcp-deribit/tools/get_historical` paginando 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.
|
||
2. **Market summary**: statistiche return (mean, std, skew, kurt) + classificazione regime volatilità.
|
||
3. **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}.
|
||
4. **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.
|
||
5. **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_down` per 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)` AND `realized_vol(20) > 0.3%` AND `RSI(14) < 45`.
|
||
- **SHORT**: `SMA(10) crossunder SMA(30)` AND `realized_vol(20) > 0.3%` AND `RSI(14) > 55`.
|
||
- **EXIT**: (`RSI(14) > 70` AND `close crossover SMA(50)`) OR `realized_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 `undertrading` ma 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:
|
||
|
||
1. **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.
|
||
2. **Tier C unico**: nessun confronto contro tier B/S. Possibile underperformance del LLM economico vs Sonnet/Opus. Phase 2 introduce ablation multi-tier.
|
||
3. **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).
|
||
4. **Fitness function v1**: lineare in DSR + tanh(Sharpe) normalizzato + drawdown moltiplicativa. Non multi-livello (per-team, anti-collusion). Phase 2 introduce.
|
||
5. **No speciation, no novelty bonus**: cognitive style scendono da 6 a 3 a gen 9. Phase 2 deve mitigare.
|
||
6. **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.
|
||
7. **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`.
|
||
8. **Cerbero/Deribit data quality**: nessuna detection di gap, outlier, exchange downtime. Da affrontare prima di forward-test (Phase 3).
|
||
9. **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**:
|
||
|
||
1. **JSON >> S-expression** per grammar LLM-generated. Phase 2 non rivisita.
|
||
2. **Fitness continua è essenziale** per dare gradient al GA, ma può promuovere strategie degeneri (1-trade) che vanno killate diversamente.
|
||
3. **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.
|
||
4. **Cerbero MCP come single source of truth** funziona: paginazione, cache parquet, audit log integrati senza fragility.
|
||
5. **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.*
|