# 2026-06-13 — Dashboard web PORT06 (stato live + PnL + grafici + trade)

Richiesta utente: frontend per visualizzare lo stato con PnL totale e per-strategia,
grafici, e liste trade (attivi in tempo reale + chiusi).

## Cosa

`src/live/dashboard.py` — server **stdlib `http.server`** (zero nuove dipendenze),
legge i file `data/` e serve:
- `GET /api/state` → JSON con tutto lo stato calcolato
- `GET /` → single-page HTML (vanilla JS, polling ogni 5s)

Contenuto della pagina:
- **KPI**: equity, PnL totale (€ e %), max DD, peak
- **Grafico equity** (Chart.js da CDN, fallback testuale se offline) dalla
  `equity.jsonl` del ledger (downsample a 400 punti)
- **PnL per strategia** (barre verdi/rosse): realizzato netto fee = Σ `pnl` reali
  dai CLOSE (REAL-TRUTH), n trade, win-rate, capitale; tag `paper` per i
  multi-asset non eseguiti, `•aperta` se in posizione
- **Trade attivi in tempo reale**: lato, entry, **mark corrente** (Cerbero
  best-effort, cache 20s), **PnL non realizzato** (€ e %, da `real_entry_notional`),
  barre/max_bars, distanza al TP, età dello status (⚠ se >15min = stantio)
- **Trade chiusi** (ultimi 50): ora, strategia, motivo, PnL reale, sim, esito

## Deploy

Servizio docker-compose `dashboard` (stessa immagine del runner, monta gli stessi
`data/`, porta **8787**), `restart: unless-stopped` + healthcheck sull'API.
Accesso: `http://<host>:8787`. **Nessuna auth** → solo rete interna/VPN, non
esporre pubblicamente. Avvio: `docker compose up -d --build dashboard` (il runner
non viene toccato).

    uv run python -m src.live.dashboard --port 8787   # anche standalone su host

## Note

- Il PnL per-strategia usa il PnL REALE (real_truth), coerente col report orario.
- I 6 fade 1h ritirati dallo swap restano in lista (hanno storico CLOSE): flat,
  mostrano il loro PnL realizzato storico accanto ai gemelli 15m attivi.
- Unrealized € sui pairs non mostrato (posizione a 2 gambe, z-based) → "pairs (z)".
