refactor(dashboard): move multi_swarm_core/dashboard → strategy_crypto/frontend
- 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) <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -7,7 +7,7 @@ from typing import Any
|
|||||||
|
|
||||||
import pandas as pd # type: ignore[import-untyped]
|
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:
|
def get_repo(db_path: str | Path) -> Repository:
|
||||||
+30
-19
@@ -1,6 +1,6 @@
|
|||||||
"""NiceGUI dashboard — port progressivo da Streamlit.
|
"""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.
|
Default port 8080. Streamlit resta su 8501 durante la migrazione.
|
||||||
|
|
||||||
Riusa ``dashboard.data`` (Repository helpers) senza modifiche al backend.
|
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]
|
import plotly.graph_objects as go # type: ignore[import-untyped]
|
||||||
from nicegui import app, ui
|
from nicegui import app, ui
|
||||||
|
|
||||||
from multi_swarm_core.dashboard.data import (
|
from strategy_crypto.frontend.data import (
|
||||||
evaluations_df,
|
evaluations_df,
|
||||||
generations_df,
|
generations_df,
|
||||||
genomes_df,
|
genomes_df,
|
||||||
@@ -43,7 +43,11 @@ from multi_swarm_core.dashboard.data import (
|
|||||||
paper_trades_df,
|
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
|
REFRESH_INTERVAL_S = 3.0
|
||||||
|
|
||||||
# --- Neon Trading Dashboard palette ---
|
# --- Neon Trading Dashboard palette ---
|
||||||
@@ -384,11 +388,11 @@ def _build_header(active: str) -> None:
|
|||||||
with ui.row().classes("items-center gap-3"):
|
with ui.row().classes("items-center gap-3"):
|
||||||
ui.html(f'<span style="color:{COLOR_TEXT_MUTED};font-size:12px;'
|
ui.html(f'<span style="color:{COLOR_TEXT_MUTED};font-size:12px;'
|
||||||
f'font-family:JetBrains Mono,monospace;">'
|
f'font-family:JetBrains Mono,monospace;">'
|
||||||
f'⛁ {Path(DB_PATH).resolve().name}</span>')
|
f'⛁ {Path(GA_DB_PATH).resolve().name} + {Path(PAPER_DB_PATH).resolve().name}</span>')
|
||||||
|
|
||||||
|
|
||||||
def _runs_options() -> dict[str, str]:
|
def _runs_options() -> dict[str, str]:
|
||||||
repo = get_repo(DB_PATH)
|
repo = get_repo(GA_DB_PATH)
|
||||||
runs = list_runs_df(repo)
|
runs = list_runs_df(repo)
|
||||||
if runs.empty:
|
if runs.empty:
|
||||||
return {}
|
return {}
|
||||||
@@ -399,7 +403,7 @@ def _runs_options() -> dict[str, str]:
|
|||||||
|
|
||||||
|
|
||||||
def _snapshot(run_id: str) -> dict[str, Any]:
|
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)
|
ov = get_run_overview(repo, run_id)
|
||||||
evals = evaluations_df(repo, run_id)
|
evals = evaluations_df(repo, run_id)
|
||||||
gens = generations_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")
|
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")
|
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(DB_PATH), state["run_id"]))).classes("w-full q-mt-md")
|
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.separator()
|
||||||
ui.label("Tabella generazioni").classes("text-subtitle1 q-mt-md")
|
ui.label("Tabella generazioni").classes("text-subtitle1 q-mt-md")
|
||||||
@@ -656,8 +660,8 @@ def convergence() -> None:
|
|||||||
if not run_id:
|
if not run_id:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
gens = generations_df(get_repo(DB_PATH), run_id)
|
gens = generations_df(get_repo(GA_DB_PATH), run_id)
|
||||||
ov = get_run_overview(get_repo(DB_PATH), run_id)
|
ov = get_run_overview(get_repo(GA_DB_PATH), run_id)
|
||||||
except Exception as e: # noqa: BLE001
|
except Exception as e: # noqa: BLE001
|
||||||
ui.notify(f"Errore: {e}", type="negative")
|
ui.notify(f"Errore: {e}", type="negative")
|
||||||
return
|
return
|
||||||
@@ -801,7 +805,7 @@ def genomes() -> None:
|
|||||||
if not run_id:
|
if not run_id:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
repo = get_repo(DB_PATH)
|
repo = get_repo(GA_DB_PATH)
|
||||||
evals = evaluations_df(repo, run_id)
|
evals = evaluations_df(repo, run_id)
|
||||||
gens = genomes_df(repo, run_id)
|
gens = genomes_df(repo, run_id)
|
||||||
except Exception as e: # noqa: BLE001
|
except Exception as e: # noqa: BLE001
|
||||||
@@ -874,7 +878,7 @@ def genomes() -> None:
|
|||||||
|
|
||||||
|
|
||||||
def _paper_runs_options(only_running: bool = False) -> dict[str, str]:
|
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:
|
if runs.empty:
|
||||||
return {}
|
return {}
|
||||||
if only_running:
|
if only_running:
|
||||||
@@ -1014,11 +1018,11 @@ def paper() -> None:
|
|||||||
if not run_id:
|
if not run_id:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
summary = paper_run_summary(DB_PATH, run_id)
|
summary = paper_run_summary(PAPER_DB_PATH, run_id)
|
||||||
eq = paper_equity_df(DB_PATH, run_id)
|
eq = paper_equity_df(PAPER_DB_PATH, run_id)
|
||||||
positions = paper_positions_df(DB_PATH, run_id)
|
positions = paper_positions_df(PAPER_DB_PATH, run_id)
|
||||||
ticks = paper_ticks_df(DB_PATH, run_id, limit=30)
|
ticks = paper_ticks_df(PAPER_DB_PATH, run_id, limit=30)
|
||||||
trades = paper_trades_df(DB_PATH, run_id, limit=50)
|
trades = paper_trades_df(PAPER_DB_PATH, run_id, limit=50)
|
||||||
except Exception as e: # noqa: BLE001
|
except Exception as e: # noqa: BLE001
|
||||||
ui.notify(f"Errore: {e}", type="negative")
|
ui.notify(f"Errore: {e}", type="negative")
|
||||||
return
|
return
|
||||||
@@ -1081,14 +1085,21 @@ def paper() -> None:
|
|||||||
|
|
||||||
|
|
||||||
def main() -> 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(
|
ui.run(
|
||||||
host="0.0.0.0",
|
host="0.0.0.0",
|
||||||
port=int(os.environ.get("SWARM_DASHBOARD_PORT", "8080")),
|
port=int(os.environ.get("SWARM_DASHBOARD_PORT", "8080")),
|
||||||
title="Multi-Swarm Dashboard",
|
title="Strategy Crypto Dashboard",
|
||||||
reload=False,
|
reload=False,
|
||||||
show=False,
|
show=False,
|
||||||
dark=True,
|
dark=True,
|
||||||
|
root_path=DASHBOARD_ROOT_PATH,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user