eod_reconcile, backfill_journal and the admin health block were hardwired
to AlpacaPaperClient — on a BROKER=tradier stack they would silently
reconcile/report against the wrong broker. make_trading_client() honors
BROKER env with no silent cross-broker fallback (missing Tradier keys =>
skip with reason, never fall back to Alpaca). Admin UI shows the active
broker label; JSON key stays 'alpaca' for compatibility.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
You wanted to compare the bot's success rate per market day, plus an all-time
total. Three pieces:
- Backfill (backfill_journal.py + storage/journal_backfill.py): reconstruct every
completed round-trip from Alpaca's full filled-order history (pair entries with
exits per symbol into episodes, read exit reason + bracket stop from the
orders), and emit position_closed events timestamped (ET) at the exit fill so
each lands on its own market day. Idempotent (re-run replaces prior backfill);
live-reconciled closes deduped by symbol+minute. Run once: it journaled 22
round-trips across 6/16-6/18, so each day's win-rate/avg-R/trades now populate
retroactively (6/17: 57% win, 6/18: 43%).
- All-Time score (query_alltime_score + dashboard panel): cumulative across every
closed round-trip — total realized, win rate, trades, avg R, trading days,
best/worst day. Always shown, not date-scoped.
- Per-day Trades panel: the individual round-trips for the viewed day (symbol,
color-coded exit reason, R, P/L, time) with a net/win-rate header — so you can
see exactly what happened each day. LIVE now scopes the journal to TODAY (was
unbounded, which would have shown the all-time list once the journal filled).
Tests: round-trip reconstruction (stop/target/scale-out/short/open/legs),
all-time aggregation, live=today scoping. Headless-verified both panels live and
on 6/18. No JS errors.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>