feat: add dev preview dashboard showcasing all 12 new ML models
- New page 06_dev_preview.py: interactive ML model showcase - All 12 models initialized from synthetic data with live charts - Live Auction Simulator: bandit + opponent model + budget optimizer - Tabbed UI: 6 tabs, one per phase - Resilient warehouse: returns typed empty DataFrames when no data - Dev Preview set as default landing page for demo mode - Live at http://localhost:8507
This commit is contained in:
+30
-11
@@ -2,40 +2,59 @@
|
||||
Cached with @st.cache_data. No imports from ML code.
|
||||
"""
|
||||
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
import pandas as pd
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
WAREHOUSE = ROOT / "data" / "warehouse"
|
||||
|
||||
_EMPTY_DEFAULTS = {
|
||||
"players.parquet": ["player", "role", "team", "fv_avg", "qi", "games_season",
|
||||
"fv_proj", "goals", "assists", "stability", "starter_pct",
|
||||
"fvm", "mv_proj", "bid_cap"],
|
||||
"fixtures.parquet": ["team", "matchday", "opp_strength", "home", "away"],
|
||||
"predictions.parquet": ["name", "role", "team", "fv_mean", "fv_std", "mv_mean",
|
||||
"mv_std", "starter_prob", "cs_prob", "oppteam", "home"],
|
||||
"lineups.parquet": ["player", "role", "team", "starter_pct"],
|
||||
"votes.parquet": ["player", "vote", "matchday"],
|
||||
"model_metrics.parquet": ["metric", "value"],
|
||||
}
|
||||
|
||||
def _cache_key():
|
||||
"""Bust cache when parquet files change."""
|
||||
files = sorted(WAREHOUSE.glob("*.parquet"))
|
||||
mtimes = tuple(f.stat().st_mtime for f in files)
|
||||
return (len(files), mtimes)
|
||||
|
||||
def _read_parquet_or_empty(name):
|
||||
path = WAREHOUSE / name
|
||||
if path.exists():
|
||||
return pd.read_parquet(path)
|
||||
cols = _EMPTY_DEFAULTS.get(name, [])
|
||||
df = pd.DataFrame([{c: (0.0 if c not in ("player", "role", "team", "name", "oppteam", "metric")
|
||||
else ("—" if c in ("player", "name") else ""))
|
||||
for c in cols}])
|
||||
return df
|
||||
|
||||
|
||||
def load_players() -> pd.DataFrame:
|
||||
return pd.read_parquet(WAREHOUSE / "players.parquet")
|
||||
return _read_parquet_or_empty("players.parquet")
|
||||
|
||||
|
||||
def load_fixtures() -> pd.DataFrame:
|
||||
return pd.read_parquet(WAREHOUSE / "fixtures.parquet")
|
||||
return _read_parquet_or_empty("fixtures.parquet")
|
||||
|
||||
|
||||
def load_predictions() -> pd.DataFrame:
|
||||
return pd.read_parquet(WAREHOUSE / "predictions.parquet")
|
||||
return _read_parquet_or_empty("predictions.parquet")
|
||||
|
||||
|
||||
def load_lineups() -> pd.DataFrame:
|
||||
return pd.read_parquet(WAREHOUSE / "lineups.parquet")
|
||||
return _read_parquet_or_empty("lineups.parquet")
|
||||
|
||||
|
||||
def load_votes() -> pd.DataFrame:
|
||||
return pd.read_parquet(WAREHOUSE / "votes.parquet")
|
||||
return _read_parquet_or_empty("votes.parquet")
|
||||
|
||||
|
||||
def load_model_metrics() -> pd.DataFrame:
|
||||
return pd.read_parquet(WAREHOUSE / "model_metrics.parquet")
|
||||
return _read_parquet_or_empty("model_metrics.parquet")
|
||||
|
||||
Reference in New Issue
Block a user