betting_combat.services.rounds_dashboards
Rows for strategy 4’s diagnostics tables (store.rounds_dashboards; contract:
ROUND_SYSTEM_FLOW.md §9), shaped from what each writer already holds. Pure: no IO.
card run decision_rows (one row per decision x market, from the decision's legs), card_limits_row (the money settings the card runs under)weekly refit layer_scores, auc, calibration_rows, importance_rows, fold_rows, path_row, uniqueness_summaryforward job forward_rows (live vs research replay, bet by bet)health job csw_cusum (the same statistic as the view ``rounds_edge_cusum``)Functions
auc
auc(y: Any, p: Any) -> floatThe area under the ROC curve (Mann-Whitney; ties count half).
brier
brier(y: Any, p: Any) -> floatcalibration_rows
calibration_rows(version: int, source: str, model: str, y: Any, p: Any, n_bins: int = 10) -> list[dict[str, Any]]Equal-width reliability bins over [0, 1] (bin i holds i/n <= p < (i+1)/n; p = 1 in the last); every bin is a row, an empty one with n = 0.
card_limits_row
card_limits_row(s: Settings | None, card_id: str, card_date: dt.date, session_id: str, mode: Literal['paper', 'live', 'shadow'], as_of: dt.datetime, card_name: str | None = None, portfolio: Any | None = None, live_cash_cap_usd: float | None = None, ids: Mapping[str, str] = IDS) -> dict[str, Any]The money controls a card runs under, written whenever they or the mode change — ALWAYS, also with no card cap, no stop loss or no sizing bankroll (the dashboards resolve every decision’s mode from these rows).
s: the decision’s settings (settings_of: the controls in dollars; None without
a sizing bankroll). portfolio: the portfolio row, for the controls as set
(card_risk / card_risk_type, stop_loss / stop_loss_type); its dollars
must equal s’s. live_cash_cap_usd: live, the Kalshi cash capping the sends.
The first draft’s columns are written as mirrors (card_budget_usd = cash_limit_usd =
card_risk_usd with card_loss_pct 1, daily_stop_usd = stop_loss_usd), NULL with them.
csw_cusum
csw_cusum(x: Iterable[float], b_alpha: float = B_ALPHA) -> list[dict[str, Any]]The one-sided Chu-Stinchcombe-White CUSUM (AFML 17.3.2) with a FIXED start (the
first residual given: the start of monitoring), exactly as the view
rounds_edge_cusum computes it within one segment: y_t = x_1 + … + x_t,
sigma_t^2 = mean of x_i^2 up to t, S_t = -y_t / (sigma_t sqrt t),
c_t = sqrt(b_alpha + ln t), stat_ratio = S_t / c_t, alarm = stat_ratio > 1, alarmed =
any alarm so far. (A start that moves with t — the max over n — false-alarms on a
calibrated model most of the time over a few hundred bets.)
decision_rows
decision_rows(record: DecisionRecord, round_idx: int, session_id: str, mode: Literal['paper', 'live'], fight: str | None = None, card_name: str | None = None, pair_draw_share: float = DRAW_SHARE, ids: Mapping[str, str] = IDS) -> list[dict[str, Any]]One row per candidate bet of a rounds decision (its legs); a decision without
candidates (no model, stale feed, …) has none — decision_log holds it.
fold_rows
fold_rows(version: int, target: str, kept: Sequence[Sequence[str]]) -> list[dict[str, Any]]kept[fold]: the features forward selection kept in that outer fold, in the
order it chose them.
forward_rows
forward_rows(live: Mapping[tuple[str, int, str], Mapping[str, Any]], replay: Mapping[tuple[str, int, str], Mapping[str, Any]], card_id: str, card_date: dt.date, mode: Literal['paper', 'live', 'shadow'], checked_at: dt.datetime, model_version: int | None, fights: Mapping[str, str] | None = None, tol: float = 1e-09, ids: Mapping[str, str] = IDS) -> list[dict[str, Any]]Every bet of a card, keyed (fight_id, round_idx, market), as the live run made it
and as the research code replays it, for the live run’s mode. Each side’s dict: side, p_side, edge, meta, entry,
intended, contracts, avg_price (and live: decision_id). A mismatch is any decision field
in COMPARED differing (numbers by more than tol); fills are not compared (the
replay’s are tape-simulated — the Performance dashboard sets them side by side).
importance_rows
importance_rows(version: int, model: str, method: str, importance: Mapping[str, float], sd: Mapping[str, float] | None = None) -> list[dict[str, Any]]Ranked importances: 1 = the largest; ties broken by the feature’s name.
layer_scores
layer_scores(prefix: Literal['l1', 'l2'], y: Any, p: Any, p_market: Any) -> dict[str, float]{prefix}_logloss, _brier and the market’s on the same rows.
log_loss
log_loss(y: Any, p: Any) -> floatorder_prices
order_prices(leg: Mapping[str, Any]) -> dict[str, float] | NoneEach order the bet sent -> the price its market showed AT THE DECISION: the engine’s
bought[].orders[].shown (pair legs included). The record is made before the paper
run re-reads the book a second later, so this is never the re-read price.
path_row
path_row(version: int, path: int, card_pnl: Sequence[float], bets: int) -> dict[str, Any]One CPCV path of the chosen setting: its per-card P&L -> total and Sharpe per card (mean / sample sd; None under two cards or with no spread).
sent_prices
sent_prices(leg: Mapping[str, Any]) -> dict[str, float] | NoneEach order sent -> the book’s price when it was repriced and sent (sent_price;
its limit is that + the cushion). Dropped orders have none.
uniqueness_summary
uniqueness_summary(weights: Any) -> dict[str, float]The meta model’s sample weights (average uniqueness, AFML ch. 4) in six numbers.