scripts/run_paper_trading.py: AssetConfig ETH ora usa timeframe="5m" invece del default 1h. Il winner c04dff7086 e' stato trovato dal GA su dati 5m e a 1h la strategia perde: - ETH @ 5m (native): +359.50% cum 7y, 77% winrate, max DD/yr 19% - ETH @ 1h (precedente): -33.03% cum 7y, 67% winrate, max DD 74% BTC resta a 1h (winner 238e4812 native a 1h, +104% 7y, Sharpe 2+ in 3 anni). Nuovi script di analisi: - scripts/yearly_strategies.py: breakdown per anno (2019-2025) di 4 strategie su tick di discovery (trade/winrate/return/maxDD/Sharpe). - scripts/multi_tick_strategies.py: confronto cross-tick (5m/15m/1h) per i 2 winner correnti. Documenta la divergenza tick-paper di ETH. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Multi_Swarm_Coevolutive
Proof-of-concept di sistema co-evolutivo multi-agente per trading quantitativo. Un genetic algorithm fa evolvere una popolazione di agenti LLM (Hypothesis swarm) che generano strategie di trading espresse in JSON strutturato; un layer Falsification deterministico le backtesta su dati storici (default BTC-PERPETUAL Deribit) via Cerbero MCP; un layer Adversarial euristico le sottopone a red-team checks; la fitness combina Deflated Sharpe Ratio (Bailey & López 2014), Sharpe normalizzato e penalizzazione di drawdown, con opzioni v2 soft-kill e combined IS/OOS per Walk-Forward Validation.
Repository
Gitea Tielogic (privato, accesso SSH):
git clone ssh://git@git.tielogic.xyz:222/Adriano/Multi_Swarm_Coevolutive.git
Layout monorepo (uv workspace)
Il repo è un workspace uv con due member packages indipendenti, principio "core = framework, strategy = contenuto":
multi_swarm_coevolutive/ repo root (workspace coordinator)
├── pyproject.toml workspace + dev deps + ruff/mypy/pytest
├── docker-compose.yml 3 servizi su immagine condivisa
├── Dockerfile immagine multi-swarm-coevolutive:dev
├── uv.lock lock unico del workspace
├── data/, series/, state/ cache OHLCV + DB (runtime, gitignored)
├── scripts/ CLI entrypoints (run_phase1, run_paper_trading, ...)
└── src/
├── multi_swarm_core/ WORKSPACE MEMBER (wheel: multi-swarm-core)
│ ├── pyproject.toml core deps (pandas, numpy, openai, pydantic, nicegui, ...)
│ ├── multi_swarm_core/ GA + genome + protocol + backtest + cerbero +
│ │ data + llm + agents + ga + orchestrator +
│ │ metrics + persistence + config + dashboard (GA-only)
│ ├── tests/ unit + integration
│ └── docs/ design/ + decisions/ + reports/
│
└── strategy_crypto/ WORKSPACE MEMBER (wheel: strategy-crypto)
├── pyproject.toml deps: multi-swarm-core (workspace) + nicegui + plotly
├── README.md overview strategia + pattern per nuove strategie
├── strategy_crypto/
│ ├── backend/ paper-trading (executor, portfolio, persistence, schema)
│ ├── frontend/ NiceGUI paper-only dashboard
│ ├── strategies/ JSON freezate (btc_*.json, eth_*.json)
│ └── prompts.json v3.2: agent_role/pattern_guidance/instruction/
│ domain_warnings/anti_patterns/output_priorities +
│ 7 stili cognitive (directive + focus_metrics)
└── tests/ smoke regression
DB separati per dominio: state/runs.db (GA core universale) + state/strategy_crypto.db (paper della strategia crypto). Pattern scala a N strategie senza naming collision.
Pattern N strategie future: aggiungere src/strategy_<asset>/ con stesso scheletro (backend/, frontend/, strategies/, tests/, prompts.json), DB dedicato state/strategy_<asset>.db, servizi Docker strategy-<asset>-paper + strategy-<asset>-gui, GUI su /strategy_<asset>_gui. Zero modifiche al core richieste.
Architettura prompt (v3.2)
Compositor: il SYSTEM prompt al LLM viene COMPOSTO at-runtime da scaffold core + contenuto strategy:
[1] agent_role ← strategy (prompts.json — chi è l'agente)
[2] cognitive_style + directive ← genome (evoluti dal GA)
[3] GRAMMAR_SPEC ← core scaffold (operatori, indicatori, units rules)
[4] pattern_guidance ← strategy (forme di curva astratte, no indicatori prescritti)
[5] domain_warnings ← strategy (es. "crypto trada 24/7, NON inferire funding rate")
[6] CONSTRAINTS ← core scaffold (validator semantics)
[7] anti_patterns ← strategy (7 voci: no >4 AND, no chattering, isteresi, ecc.)
[8] output_priorities ← strategy (5 voci, #1 coerenza con lente cognitiva)
[9] EXAMPLE ← core scaffold
Input USER (calcolato da build_market_summary):
- Base (5): mean, std, skew, kurt, vol_regime
- Regime recente rolling 500 (6): autocorr_lag1 (recent + baseline), hurst, vol_percentile, seasonality (hour + dow)
- Geometria & frattali (7): efficiency_ratio (Kaufman), tail_index (left + right Hill), structural_uptrend (HH/HL), compression, spectral_entropy, dominant_cycle (gated)
- Feature accessibili dal genome + lookback_window
- Focus per la tua lente: blocco style-aware (4 metriche prioritarie da
focus_metricsdi prompts.json) - Instruction finale (da strategy)
Grammar protocol JSON (8 indicatori):
| Indicatore | Output | Range |
|---|---|---|
sma(length) |
media mobile | unità prezzo |
sma_pct(length) |
(close-sma)/sma | ±0.1 frazione |
rsi(length) |
oscillator | 0-100 |
atr(length) |
true range | unità prezzo |
atr_pct(length) |
atr/close | 0-0.1 frazione |
realized_vol(window) |
std returns | 0-0.1 frazione |
macd(fast,slow,signal) |
momentum | unità prezzo |
macd_pct(...) |
macd/close | ±0.02 frazione |
7 stili cognitive (in prompts.json, editable): physicist, biologist, historian, meteorologist, engineer, military_strategist, psychologist. Ognuno con directive 800-950 char, ASCII-strict, archetipo dominante + lookback consigliato + 4 focus_metrics.
Stato del progetto
Phase 3 (paper-trading forward-test) in corso dal 13 maggio 2026 su VPS. Runner scripts/run_paper_trading.py long-running in Docker, dashboard NiceGUI su https://swarm.tielogic.xyz/strategy_crypto_gui/. Due strategie freezate in src/strategy_crypto/strategy_crypto/strategies/:
btc_fb63e851.json— BTC-PERPETUAL, RSI estremi + ATR vs SMA + filtro orario 9-17 (Sharpe OOS +0,26 su 7,33 anni).eth_facd6af85d5d.json— ETH-PERPETUAL, regime-based (conatr_pctpost-fix bug unità).
Phase 1 → 2.7 chiuse (30 run GA, $3.74 cumulato LLM). Sessione refactor 15 maggio 2026:
- Split repo invertito, monorepo unificato come uv workspace
- Family
*_pctcompleta (atr_pct, sma_pct, macd_pct) per fix bug unità - Dashboard split: core (GA) vs strategy (paper)
- Prompt architecture compositor + prompts.json v3.2 (vedi decision log)
Documenti:
- Stato progetto e roadmap (14 maggio 2026)
- Decision log:
src/multi_swarm_core/docs/decisions/(gate Phase 1, nemotron, atr_pct fix) - Design docs concettuali:
src/multi_swarm_core/docs/design/
Stack: Python 3.13, uv workspace, hatchling, pytest+pytest-mock+responses, openai SDK (verso OpenRouter), requests+tenacity, pandas+numpy+scipy, sqlmodel+sqlite, nicegui+plotly, yfinance.
Setup
uv sync # installa entrambi i workspace member come editable
cp .env.example .env # compila CERBERO_*_TOKEN e OPENROUTER_API_KEY
uv run pytest # 252 test attesi (248 core + 4 smoke strategy_crypto)
Variabili .env richieste
# Cerbero MCP (locale o VPS https://cerbero-mcp.tielogic.xyz)
CERBERO_BASE_URL=http://localhost:9001
CERBERO_TESTNET_TOKEN=<testnet bearer>
CERBERO_MAINNET_TOKEN=<mainnet bearer> # serve per dati storici reali
CERBERO_BOT_TAG=swarm-poc-phase1
# LLM provider (unico endpoint via OpenRouter)
OPENROUTER_API_KEY=<sk-or-v1-...>
# DB paths (split per dominio: core GA vs paper della strategia)
GA_DB_PATH=./state/runs.db
STRATEGY_CRYPTO_DB_PATH=./state/strategy_crypto.db
# Deploy Docker — DASHBOARD_ROOT_PATH ora per-servizio (vedi docker-compose.yml)
DOMAIN_NAME=tielogic.xyz
SWARM_DASHBOARD_PORT=8080
Backcompat: DB_PATH legacy continua a funzionare come alias di GA_DB_PATH.
Comandi principali
# Quality gates
uv run pytest # tutti i test
uv run pytest src/multi_swarm_core/tests/unit -v # solo unit core
uv run pytest src/strategy_crypto/tests/ -v # smoke strategy_crypto
uv run ruff check src/ scripts/
uv run mypy src/ scripts/
# Smoke run (MockLLM + OHLCV sintetico, no API calls)
uv run python scripts/smoke_run.py
# Run reale Phase 1/2 (Cerbero + OpenRouter, ~$0.15-0.25 per run K=20 10gen,
# ~$0.40-0.55 per run esteso K=40 20gen con WFA OOS).
# Default --start ora 2018-09-01 (7.3y, copre bear+halving+covid+ATH+winter+ETF).
uv run python scripts/run_phase1.py \
--name run-XXX \
--exchange deribit --symbol BTC-PERPETUAL --timeframe 1h \
--population-size 20 --n-generations 10 \
--prompt-mutation-weight 0.30 --fitness-v2 \
--llm-concurrency 8 # 5-8x speedup wall time (default 1)
# fitness-v2 hardened: hard-kill su {no_trades, degenerate, undertrading,
# fees_eat_alpha, negative_net_pnl}. Override via --fitness-hard-kill CSV.
# Default --prompt-library: importlib.resources del package strategy_crypto/prompts.json
# Multi-fold validation di un run esistente (anti-overfit, 7y expanding-window)
uv run python scripts/validate_run.py \
--run-id <run_id> \
--top-k 10 --n-folds 4 --train-ratio 0.5 \
--start 2018-09-01T00:00:00+00:00 --end 2026-01-01T00:00:00+00:00 \
--fitness-v2 \
--output-json state/validation-XXX.json
# Ranking per "robust_score" = min(fitness_oos) su tutti i fold.
# Backtest standalone di una strategia JSON
uv run python scripts/backtest_strategy.py \
--strategy src/strategy_crypto/strategy_crypto/strategies/btc_fb63e851.json \
--start 2018-09-01 --end 2026-01-01
# Paper-trading forward-test (Phase 3)
uv run python scripts/run_paper_trading.py \
--name phase3-papertrade-XXX \
--initial-capital 1000 --poll-seconds 300
# Dashboard NiceGUI locale (2 distinte)
uv run python -m multi_swarm_core.dashboard.nicegui_app # GA core (/, /convergence, /genomes)
uv run python -m strategy_crypto.frontend.nicegui_app # Strategy crypto (/ paper)
Performance & Validation
Backtest engine vettorializzato (backtest/engine.py): rimosso il loop pd.iterrows() a favore di state machine numpy. Speedup misurati:
| Dataset | Before (iterrows) | After (vectorized) | Speedup |
|---|---|---|---|
| 2 anni (17545 bar) | 470 ms | 28 ms | 16.8× |
| 7 anni (64297 bar) | 1744 ms | 154 ms | 11.3× |
Equivalenza numerica garantita: 5 parity test parametrici vs. reference implementation legacy (test_backtest_engine_vectorized.py).
Parallel propose LLM (orchestrator/run.py): --llm-concurrency N lancia N chiamate hypothesis_agent.propose() concorrenti per generazione tramite ThreadPoolExecutor. OpenRouter qwen-2.5 regge 6-10 concorrenti senza rate-limit. Default 1 = backward-compat.
Multi-fold validation tool (scripts/validate_run.py): qualunque run completato puo' essere rivalutato post-hoc su N fold expanding-window di un dataset esteso (tipicamente 7 anni). Vital per evitare il single-hold-out overfit: il GA puo' selezionare un genome con fitness_is alta che collassa OOS (osservato su phase1-extended-001: elite IS Sharpe 1.93, OOS Sharpe -1.00). Ranking finale per robust_score = min(fitness_oos). Output JSON con per-fold breakdown + aggregati mean/min/std.
Dashboard (split core + strategy)
Due NiceGUI dashboard distinte (dark palette, palette neon):
Core GA — multi_swarm_core.dashboard.nicegui_app → https://swarm.tielogic.xyz/multi_swarm_core_gui/:
- Overview (
/): lista runs GA, costo cumulato, metriche aggregate evaluations. - GA Convergence (
/convergence): fitness median/max/p90 per generazione + entropy. - Genomes (
/genomes): top-K ordinati per fitness, ispezione system_prompt + JSON strategy.
Strategy crypto — strategy_crypto.frontend.nicegui_app → https://swarm.tielogic.xyz/strategy_crypto_gui/:
- Paper (
/): forward-test live con equity curve, posizioni aperte, trade list, tick log.
In produzione subpath gestiti via DASHBOARD_ROOT_PATH (per-servizio) + Traefik replacepathregex (NB: NON stripprefix, vedi sezione Deploy). La root del dominio resta libera per future GUI di altre strategie.
Deploy
docker-compose.yml definisce 3 servizi su immagine condivisa multi-swarm-coevolutive:dev:
strategy-crypto-paper— runnerscripts/run_paper_trading.pylong-running.strategy-crypto-gui— NiceGUI paper dashboard suhttps://swarm.${DOMAIN_NAME}/strategy_crypto_gui/.multi-swarm-core-gui— NiceGUI GA dashboard suhttps://swarm.${DOMAIN_NAME}/multi_swarm_core_gui/.
Persistenza via bind mount: ./data/, ./series/, ./state/. Strategie JSON bind-mounted in read-only dal package: ./src/strategy_crypto/strategy_crypto/strategies/.
docker compose up -d --build
docker compose logs -f strategy-crypto-paper
docker compose ps
Note operative:
- Bind-mount dir devono essere
chown 1000:1000(uid utenteappnel container). Anchesrc/strategy_crypto/strategy_crypto/strategies/(creata dagit mv, defaultroot:root). - Override del command paper via env (
PAPER_RUN_NAME,PAPER_INITIAL_CAPITAL, ecc.). SWARM_DASHBOARD_PORTcontrolla la porta interna del container (Traefik fa il TLS).- Traefik subpath: usa
replacepathregexmiddleware (NONstripprefix) per evitare doppio root_path (uvicorn leggeX-Forwarded-Prefixda stripprefix + applicaroot_pathdi NiceGUI = doppio prefix). Vedi commit436613b. - Dopo cambio label Traefik:
docker restart traefik-traefik-1per forzare refresh discovery.
Sviluppo
Conventional commits con prefix feat: fix: chore: docs: refactor: test:. Body italiano. Footer Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> su ogni commit collaborativo.
Branch attuale: main. Workspace single-repo, monorepo unificato dal 15 maggio 2026 (split temporaneo monorepo→figlio invertito, vedi tag v0.1.0-pre-split come bookmark).
Modificare il prompt LLM senza toccare codice: edita src/strategy_crypto/strategy_crypto/prompts.json. Schema documentato in _design_invariants del JSON stesso. I 3 regression guard test (test_strategy_crypto_directives_ascii_safe, ..._have_archetype_marker, ..._have_lookback_hint) bloccano regressioni accidentali sulle invarianti di design.