diff --git a/src/live/dashboard.py b/src/live/dashboard.py
index 385fb30..8db1053 100644
--- a/src/live/dashboard.py
+++ b/src/live/dashboard.py
@@ -19,6 +19,7 @@ from src.live.shadow import shadow_report, tp01_trades
from src.version import APP_VERSION
PAPER = PROJECT_ROOT / "data" / "paper_portfolio" / "state.json"
+PREVDAY = PROJECT_ROOT / "data" / "paper_prevday" / "state.json"
_CACHE = {"t": 0.0, "data": None}
_TTL = 120.0
@@ -33,6 +34,7 @@ def build():
step = max(1, len(eq) // 400)
spark = [(str(idx[i].date()), float(eq[i])) for i in range(0, len(eq), step)]
paper = json.loads(PAPER.read_text()) if PAPER.exists() else None
+ prevday = json.loads(PREVDAY.read_text()) if PREVDAY.exists() else None
try:
shadow = shadow_report() # mainnet sola lettura, best-effort
except Exception as e:
@@ -46,8 +48,8 @@ def build():
last_data=str(idx[-1].date()),
full=bt["full"], holdout=bt["holdout"], weights=bt["weights"],
per_sleeve=bt["per_sleeve"], yearly=bt["yearly"],
- positions=pf.current_positions(), spark=spark, paper=paper, shadow=shadow, trades=trades,
- bh=None,
+ positions=pf.current_positions(), spark=spark, paper=paper, prevday=prevday,
+ shadow=shadow, trades=trades, bh=None,
)
_CACHE.update(t=time.time(), data=data)
return data
@@ -86,6 +88,22 @@ def html():
f"{pp['last'][:10]}, {days}g) ret {ret*100:+.2f}% maxDD {pp['max_dd']*100:.1f}%")
else:
paper_html = "non inizializzato (gira paper_portfolio.py)"
+ pv = d.get("prevday")
+ if pv:
+ days = (pv["last_ts"] - pv["start_ts"]) / 86400_000
+ rm = pv["cap_modeled"] / 2000.0 - 1
+ rr = pv["cap_real"] / 600.0 - 1
+ prevday_html = (
+ f"${pv['cap_modeled']:,.2f} modeled (€2k nom.) · "
+ f"${pv['cap_real']:,.2f} real-$600 (min-order $5)
"
+ f"ret {rm*100:+.2f}% / {rr*100:+.2f}% · "
+ f"maxDD {pv['dd_modeled']*100:.1f}% / {pv['dd_real']*100:.1f}% · "
+ f"fill-haircut {(rm-rr)*100:+.2f}pp
"
+ f"posizione: BTC {pv['pos_real']['BTC']:+.3f} · ETH {pv['pos_real']['ETH']:+.3f} · "
+ f"{pv['n_bars']} barre 1h (~{days:.0f}g) · {pv['n_trades']} flip · "
+ f"forward da {pd.Timestamp(pv['start_ts'], unit='ms').date()}")
+ else:
+ prevday_html = "non inizializzato (gira scripts/live/paper_prevday.py)"
sh = d.get("shadow")
if sh and "error" not in sh:
bits = " · ".join(
@@ -157,6 +175,9 @@ th{{color:#8a93a0;font-weight:500}}.y{{display:inline-block;background:#161b22;b
| data | asset | azione | posizione | prezzo |
|---|
⚠️ LEAD in osservazione, NON deployato. Sopravvissuto alla verifica avversariale dell'onda intraday; lo teniamo in paper per validarlo fuori-campione-vero. I due libri (modeled vs real-$600) mostrano l'haircut di fill che lo scettico aveva segnalato.