From 37bf64012b84e3d9b88a0b6ce691983d1f1bfaa9 Mon Sep 17 00:00:00 2001 From: Adriano Dal Pastro Date: Fri, 15 May 2026 17:56:55 +0000 Subject: [PATCH] =?UTF-8?q?refactor(dashboard):=20move=20multi=5Fswarm=5Fc?= =?UTF-8?q?ore/dashboard=20=E2=86=92=20strategy=5Fcrypto/frontend?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - git mv data.py + nicegui_app.py al frontend strategy_crypto - Cancellato src/multi_swarm_core/multi_swarm_core/dashboard/ - Patch import in data.py: ..persistence → multi_swarm_core.persistence - Patch nicegui_app.py: * Import: multi_swarm_core.dashboard.data → strategy_crypto.frontend.data * Dual-DB: split DB_PATH in GA_DB_PATH + PAPER_DB_PATH (env separati) * Subpath routing: DASHBOARD_ROOT_PATH passato a ui.run(root_path=...) * Header dashboard mostra entrambi i DB * Docstring di avvio aggiornata: python -m strategy_crypto.frontend.nicegui_app * Title rinominato "Strategy Crypto Dashboard" - 6 occorrenze get_repo(DB_PATH) → get_repo(GA_DB_PATH) - 6 occorrenze paper_*_df(DB_PATH, ...) → paper_*_df(PAPER_DB_PATH, ...) Co-Authored-By: Claude Opus 4.7 (1M context) --- .../multi_swarm_core/dashboard/__init__.py | 0 .../strategy_crypto/frontend}/data.py | 2 +- .../strategy_crypto/frontend}/nicegui_app.py | 49 ++++++++++++------- 3 files changed, 31 insertions(+), 20 deletions(-) delete mode 100644 src/multi_swarm_core/multi_swarm_core/dashboard/__init__.py rename src/{multi_swarm_core/multi_swarm_core/dashboard => strategy_crypto/strategy_crypto/frontend}/data.py (98%) rename src/{multi_swarm_core/multi_swarm_core/dashboard => strategy_crypto/strategy_crypto/frontend}/nicegui_app.py (96%) diff --git a/src/multi_swarm_core/multi_swarm_core/dashboard/__init__.py b/src/multi_swarm_core/multi_swarm_core/dashboard/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/multi_swarm_core/multi_swarm_core/dashboard/data.py b/src/strategy_crypto/strategy_crypto/frontend/data.py similarity index 98% rename from src/multi_swarm_core/multi_swarm_core/dashboard/data.py rename to src/strategy_crypto/strategy_crypto/frontend/data.py index 33503ff..738a008 100644 --- a/src/multi_swarm_core/multi_swarm_core/dashboard/data.py +++ b/src/strategy_crypto/strategy_crypto/frontend/data.py @@ -7,7 +7,7 @@ from typing import Any import pandas as pd # type: ignore[import-untyped] -from ..persistence.repository import Repository +from multi_swarm_core.persistence.repository import Repository def get_repo(db_path: str | Path) -> Repository: diff --git a/src/multi_swarm_core/multi_swarm_core/dashboard/nicegui_app.py b/src/strategy_crypto/strategy_crypto/frontend/nicegui_app.py similarity index 96% rename from src/multi_swarm_core/multi_swarm_core/dashboard/nicegui_app.py rename to src/strategy_crypto/strategy_crypto/frontend/nicegui_app.py index 184cc83..eca9201 100644 --- a/src/multi_swarm_core/multi_swarm_core/dashboard/nicegui_app.py +++ b/src/strategy_crypto/strategy_crypto/frontend/nicegui_app.py @@ -1,6 +1,6 @@ """NiceGUI dashboard — port progressivo da Streamlit. -Avvio: ``uv run python -m multi_swarm_core.dashboard.nicegui_app`` +Avvio: ``uv run python -m strategy_crypto.frontend.nicegui_app`` Default port 8080. Streamlit resta su 8501 durante la migrazione. Riusa ``dashboard.data`` (Repository helpers) senza modifiche al backend. @@ -28,7 +28,7 @@ import pandas as pd # type: ignore[import-untyped] import plotly.graph_objects as go # type: ignore[import-untyped] from nicegui import app, ui -from multi_swarm_core.dashboard.data import ( +from strategy_crypto.frontend.data import ( evaluations_df, generations_df, genomes_df, @@ -43,7 +43,11 @@ from multi_swarm_core.dashboard.data import ( paper_trades_df, ) -DB_PATH = os.environ.get("DB_PATH", "./runs.db") +# Dual-DB: GA core e paper strategy_crypto vivono in DB separati. +GA_DB_PATH = os.environ.get("GA_DB_PATH", "./state/runs.db") +PAPER_DB_PATH = os.environ.get("STRATEGY_CRYPTO_DB_PATH", "./state/strategy_crypto.db") +# Subpath per Traefik: "" in dev, "/strategy_crypto_gui" in prod. +DASHBOARD_ROOT_PATH = os.environ.get("DASHBOARD_ROOT_PATH", "") REFRESH_INTERVAL_S = 3.0 # --- Neon Trading Dashboard palette --- @@ -384,11 +388,11 @@ def _build_header(active: str) -> None: with ui.row().classes("items-center gap-3"): ui.html(f'' - f'⛁ {Path(DB_PATH).resolve().name}') + f'⛁ {Path(GA_DB_PATH).resolve().name} + {Path(PAPER_DB_PATH).resolve().name}') def _runs_options() -> dict[str, str]: - repo = get_repo(DB_PATH) + repo = get_repo(GA_DB_PATH) runs = list_runs_df(repo) if runs.empty: return {} @@ -399,7 +403,7 @@ def _runs_options() -> dict[str, str]: def _snapshot(run_id: str) -> dict[str, Any]: - repo = get_repo(DB_PATH) + repo = get_repo(GA_DB_PATH) ov = get_run_overview(repo, run_id) evals = evaluations_df(repo, run_id) gens = generations_df(repo, run_id) @@ -632,8 +636,8 @@ def convergence() -> None: ) ui.button("🔄 Refresh", on_click=lambda: refresh()).props("outline color=primary") - fitness_plot = ui.plotly(_convergence_figure(generations_df(get_repo(DB_PATH), state["run_id"]))).classes("w-full") - entropy_plot = ui.plotly(_entropy_figure(generations_df(get_repo(DB_PATH), state["run_id"]))).classes("w-full q-mt-md") + fitness_plot = ui.plotly(_convergence_figure(generations_df(get_repo(GA_DB_PATH), state["run_id"]))).classes("w-full") + entropy_plot = ui.plotly(_entropy_figure(generations_df(get_repo(GA_DB_PATH), state["run_id"]))).classes("w-full q-mt-md") ui.separator() ui.label("Tabella generazioni").classes("text-subtitle1 q-mt-md") @@ -656,8 +660,8 @@ def convergence() -> None: if not run_id: return try: - gens = generations_df(get_repo(DB_PATH), run_id) - ov = get_run_overview(get_repo(DB_PATH), run_id) + gens = generations_df(get_repo(GA_DB_PATH), run_id) + ov = get_run_overview(get_repo(GA_DB_PATH), run_id) except Exception as e: # noqa: BLE001 ui.notify(f"Errore: {e}", type="negative") return @@ -801,7 +805,7 @@ def genomes() -> None: if not run_id: return try: - repo = get_repo(DB_PATH) + repo = get_repo(GA_DB_PATH) evals = evaluations_df(repo, run_id) gens = genomes_df(repo, run_id) except Exception as e: # noqa: BLE001 @@ -874,7 +878,7 @@ def genomes() -> None: def _paper_runs_options(only_running: bool = False) -> dict[str, str]: - runs = paper_runs_df(DB_PATH) + runs = paper_runs_df(PAPER_DB_PATH) if runs.empty: return {} if only_running: @@ -1014,11 +1018,11 @@ def paper() -> None: if not run_id: return try: - summary = paper_run_summary(DB_PATH, run_id) - eq = paper_equity_df(DB_PATH, run_id) - positions = paper_positions_df(DB_PATH, run_id) - ticks = paper_ticks_df(DB_PATH, run_id, limit=30) - trades = paper_trades_df(DB_PATH, run_id, limit=50) + summary = paper_run_summary(PAPER_DB_PATH, run_id) + eq = paper_equity_df(PAPER_DB_PATH, run_id) + positions = paper_positions_df(PAPER_DB_PATH, run_id) + ticks = paper_ticks_df(PAPER_DB_PATH, run_id, limit=30) + trades = paper_trades_df(PAPER_DB_PATH, run_id, limit=50) except Exception as e: # noqa: BLE001 ui.notify(f"Errore: {e}", type="negative") return @@ -1081,14 +1085,21 @@ def paper() -> None: def main() -> None: - app.on_startup(lambda: print(f"DB: {Path(DB_PATH).resolve()}")) + app.on_startup( + lambda: print( + f"GA DB: {Path(GA_DB_PATH).resolve()} | " + f"Paper DB: {Path(PAPER_DB_PATH).resolve()} | " + f"root_path: {DASHBOARD_ROOT_PATH or '/'}" + ) + ) ui.run( host="0.0.0.0", port=int(os.environ.get("SWARM_DASHBOARD_PORT", "8080")), - title="Multi-Swarm Dashboard", + title="Strategy Crypto Dashboard", reload=False, show=False, dark=True, + root_path=DASHBOARD_ROOT_PATH, )