- NEW src/multi_swarm_core/multi_swarm_core/dashboard/ con theme.py + data.py + nicegui_app.py
- theme.py condiviso (CSS + colors + _apply_theme + _json_to_html + _build_header parametrico)
- core GUI: pagine /, /convergence, /genomes — legge SOLO runs.db
- strategy GUI slim: solo /, legge SOLO strategy_crypto.db — importa theme dal core
- Aggiunto nicegui+plotly al core pyproject (uv.lock rigenerato)
- docker-compose: nuovo servizio multi-swarm-core-gui su /multi_swarm_core_gui
(Traefik PathPrefix + replacepathregex, NO stripprefix per evitare doppio root_path)
- .env.example: DASHBOARD_ROOT_PATH ora per-servizio
Pattern: ogni modulo possiede la sua GUI, ogni GUI legge solo il proprio DB.
N strategie future = duplica lo scheletro strategy_crypto/frontend/.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Tre fix di deploy emersi al primo build/up del nuovo compose:
1. Dockerfile: rimosso PYTHONPATH=/app/src
Con layout uv workspace doppio-nest, PYTHONPATH=/app/src faceva ombra
alla venv risolvendo le member-dir (multi_swarm_core/, strategy_crypto/)
come namespace packages PEP 420 senza i sub-package del codice
(cerbero, persistence, frontend, ecc.). I package sono installati come
editable dal `uv sync --frozen` nella venv: niente PYTHONPATH necessario.
2. pyproject root: aggiunto [project] dependencies = [multi-swarm-core, strategy-crypto]
I due member workspace erano in [dependency-groups.dev], escluse da
`uv sync --frozen --no-dev` del builder Docker -> "ModuleNotFoundError:
No module named multi_swarm_core". Spostati come dipendenze runtime del
deployable app root; dev group ora contiene solo pytest/ruff/mypy.
uv.lock rigenerato.
3. docker-compose.yml: aggiunto Traefik middleware StripPrefix
NiceGUI con root_path="/strategy_crypto_gui" assume che il proxy
strippi il prefix prima di girare al container (FastAPI route restano
"/", "/paper", ecc.). Senza StripPrefix, NiceGUI riceveva
"/strategy_crypto_gui/" e rispondeva 404. Aggiunte 2 label:
- strategy-crypto-stripprefix middleware
- router.middlewares = strategy-crypto-stripprefix
Verifica end-to-end:
- https://swarm.tielogic.xyz/strategy_crypto_gui/ -> HTTP 200 (31KB)
- https://swarm.tielogic.xyz/ -> HTTP 404 (root libera, atteso)
- paper run phase3-baseline-001 (fcf271d0...) tick=1 OK, $1000 equity
- state/strategy_crypto.db creato con 5 tabelle paper_trading_*
NB: permission fix per `src/strategy_crypto/strategy_crypto/strategies/`
fatto manualmente (chown 1000:1000) — i JSON migrati da git mv erano
root:root, container gira come uid 1000. Annotare per future strategies.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
NiceGUI è la dashboard ufficiale (port 8080, dark/neon palette, 3 pagine:
/, /convergence, /genomes). La porta è ora parametrica via env
SWARM_DASHBOARD_PORT, letta in ui.run() — Docker la usa anche per
healthcheck e label Traefik.
docker-compose.yml: entrypoint del servizio dashboard cambiato da
streamlit a python -m multi_swarm.dashboard.nicegui_app. Default porta
8080 ovunque (.env, .env.example, compose, healthcheck).
Rimossi i file legacy della vecchia GUI Streamlit:
- src/multi_swarm/dashboard/streamlit_app.py
- src/multi_swarm/dashboard/aquarium.py (helper canvas HTML5)
- src/multi_swarm/dashboard/pages/{01_overview,02_ga_convergence,
03_genomes,04_aquarium}.py
- tests/integration/test_streamlit_smoke.py
pyproject.toml: rimossa la dep streamlit; uv.lock rigenerato (10 deps
transitive eliminate: pydeck, watchdog, jsonschema, pillow, ecc.).
README aggiornato (architettura, comando dashboard, sezione Dashboard
ora descrive NiceGUI con riferimento al deploy Docker via Traefik).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Phase 2.7 portabilità: tentativo backtest top genome BTC/ETH su asset
tradFi via yfinance per stress-test universale del setup.
Esito documentato in memoria: yfinance 1h limitato a 730 giorni,
incompatibile con hour-gated strategy su 5+ anni.
Aggiunto .claude/ a .gitignore (scheduled_tasks.lock runtime artifact).
Prima fase migrazione da Streamlit a NiceGUI. Pagina indice riproduce
l'Overview con:
- run selector reattivo
- 2 progress bar live (generations, evaluations) con WebSocket push
- 4 metric card (top fitness, median, parse success %, cost)
- timer auto-refresh ogni 3s (no click manuale)
- status badge colorato (running/completed/failed)
- config JSON code block
Avvio: uv run python -m multi_swarm.dashboard.nicegui_app (porta 8080)
Streamlit resta attivo su 8501 durante la migrazione. Backend invariato:
riusa dashboard/data.py senza modifiche.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sostituisce la grammatica S-expression con uno schema JSON stretto. La
grammatica S-expression falliva il parsing nel 64% delle generazioni del
modello Qwen3-235B sul run reale; JSON e' nativo per gli LLM moderni e
si parsa con json.loads.
Cambiamenti principali:
- grammar.py: costanti rinominate LOGICAL_OPS / COMPARATOR_OPS /
CROSSOVER_OPS / ACTION_VALUES / KIND_VALUES.
- parser.py: nuovo AST a dataclass tipizzato (OpNode, IndicatorNode,
FeatureNode, LiteralNode, Rule, Strategy); parse_strategy ora consuma
JSON tramite json.loads.
- validator.py: walk dispatchato per tipo (isinstance) invece di
pattern-matching su 'kind'; arity check su operatori e indicator.
- compiler.py: traversal del nuovo AST tipizzato, dispatch per
isinstance; logica indicator/feature/literal invariata.
- hypothesis.py: prompt SYSTEM riscritto con esempi JSON e vincoli
espliciti su no-nesting; estrazione via fence ```json``` + fallback
brace-balanced.
- __init__.py: re-export pubblico delle entita' del protocollo.
- Tutti i test (parser, validator, compiler, hypothesis_agent,
falsification, adversarial, e2e, smoke_run) migrati a JSON.
- Rimossa dipendenza sexpdata da pyproject.toml + uv.lock.
Test: 135 passed (era 122; aggiunti casi parser/validator).
ruff + mypy strict clean. Smoke run end-to-end OK.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Cerbero MCP diventa unica fonte di verità per dati di mercato Phase 1.
Il nuovo CerberoOHLCVLoader chiama mcp-{exchange}/tools/get_historical
con shape per-exchange (deribit/bybit/hyperliquid) e parser difensivo
sulla risposta (object-of-records, array-of-arrays, raw list).
- src/multi_swarm/data/cerbero_ohlcv.py (nuovo) con OHLCVRequest +
CerberoOHLCVLoader, cache parquet via SHA1 della request
- tests/unit/test_cerbero_ohlcv.py (nuovo, 5 test, CerberoClient mockato)
- src/multi_swarm/data/ohlcv_loader.py + test ccxt rimossi
- scripts/run_phase1.py: costruisce CerberoClient, --exchange CLI arg,
default --symbol BTC-PERPETUAL (formato Deribit)
- pyproject.toml: rimosso ccxt>=4.4 (uv sync ha rimosso 16 transitivi)
- .env.example: CERBERO_BASE_URL=https://cerbero-mcp.tielogic.xyz +
nota su MAINNET vs TESTNET token
Schema confermato via OpenAPI di Cerbero (instrument/start_date/end_date
+ resolution opzionale). Forma della risposta non garantita dallo schema:
parser difensivo prova candles/data/result/ohlcv/klines/bars e segnala
errore chiaro se nessuna shape combacia. Live verification skippata
(nessun token in .env).
Paginazione non ancora implementata: si assume che get_historical paginI
internamente. Da rivedere se una live call mostra cap (~1000 candele).
Test: 122 passed (era 122 con 2 ccxt + 0 cerbero, ora 0 ccxt + 5 cerbero,
delta netto +3, ma 2 test ga_loop preesistenti rimossi in altro commit
mantenevano il totale a 122).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Tutti i tier (S/A/B/C/D) ora passano per OpenRouter via OpenAI SDK.
Modelli Anthropic raggiungibili via prefisso `anthropic/...`.
- pyproject: rimosso `anthropic>=0.39` da deps + uv.lock
- config: rimosso `anthropic_api_key` field
- LLMClient: dispatch unico, single client OpenAI con base_url OpenRouter
- defaults S/A/B → `anthropic/claude-{opus-4-7,sonnet-4-6}`
- retry exceptions: solo openai.* (drop anthropic.*)
- test rinominati e adattati: tier S/A/B mockano OpenAI con prefisso `anthropic/`
- rimosso test `tier_S_without_anthropic_key_raises` (non più rilevante)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Client minimale verso Cerbero MCP unified server con header
Authorization Bearer e X-Bot-Tag su ogni richiesta. Retry esponenziale
solo su ConnectionError (non su 4xx). 4xx/5xx -> RuntimeError.
Switch da httpx a requests per allineamento con libreria mock
`responses` (httpx richiederebbe respx). httpx resta in deps per usi
futuri. Aggiunto types-requests ai dev deps per mypy strict.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>