05.Reports — 17 cuts + R-multiple + Monte Carlo forecast + fill-quality TCA
Server-side aggregation, account-scoped, asset-class filters, date-range pickers, drill-down from any cell to the underlying trades. All numbers come from the materialized trades table — no on-the-fly re-derivation.
The 17 cuts
Each cut is a route in crates/traderview-web/src/routes/reports.rs. The frontend view is one of frontend/js/views/reports_*.js; each renders a small uPlot chart plus a sortable table.
| Route | What it answers |
|---|---|
/reports/overview | Win rate, expectancy, profit factor, gross / net P&L, SQN, Sharpe, Sortino, average winner / loser. |
/reports/by-symbol | Per-symbol P&L and trade count. The cell drills into Trades filtered by symbol. |
/reports/by-day-of-week | Monday–Friday R-distribution and expectancy. |
/reports/by-hour | Hour-of-day expectancy. Catches "I lose every trade after 14:00 ET" patterns. |
/reports/by-hold | Buckets by hold-time (sub-minute / 1-5 min / 5-30 min / intraday / overnight / multi-day / multi-week). |
/reports/r-distribution | Histogram of R-multiples. The forced-review cohort (|R| ≥ 2) is highlighted. |
/reports/comparison | A/B compare two filters side by side (e.g. "tagged breakout" vs "tagged fade"). |
/reports/exit-efficiency | How much of MFE you captured. Bucketed; low buckets are scalp-out-too-early evidence. |
/reports/liquidity | Average volume vs your sizing. Flags trades where you were > 1% of bar volume. |
/reports/drawdown | Drawdown curve, longest underwater stretch, days-to-recovery. |
/reports/risk-adjusted | Per-unit-risk return (Sharpe / Sortino / Calmar). |
/reports/calendar | Daily P&L heatmap (Github-graph style) over the year. |
/reports/by-asset | Stocks vs options vs futures vs forex vs crypto. |
/reports/by-tag | Per-tag expectancy + win rate. Validates that your setup labels actually matter. |
/reports/by-setup | If you maintain a setups table (Settings → Setups), this aggregates by setup. |
/reports/streaks | Win / loss streak distribution. Useful when calibrating "should I cut size after 3 losers in a row?" |
/reports/expectancy-curve | Rolling 50/200-trade expectancy over calendar time. Strategy-decay detector. |
R-multiple + planned risk
R-multiple is net_pnl / planned_risk — but only computed when planned_risk is set on the trade. The Trades view shows a discreet "no R" badge on trades without it; the reports view excludes them from R-distribution.
Set planned risk per-trade from the Trades row menu, or default a value at trade-creation time via Settings → Default Planned Risk. The position-size calculator (step 13) writes planned_risk automatically when you accept its sizing recommendation.
Monte Carlo equity forecast
POST /api/equity-forecast — feeds your historical per-trade R-distribution into a Monte Carlo simulator and projects forward N trades. Configurable:
- Simulations — number of independent equity paths to sample (default 10 000).
- Horizon — number of future trades to simulate (default 200).
- Sampling — bootstrap with replacement from your actual R distribution, or fit a parametric distribution and sample from that.
- Sizing — fixed-fractional or fixed-R, with cap.
Output: median / 25th / 75th / 5th / 95th percentile equity paths, ruin probability, max-drawdown distribution. The view renders a fan chart and a small table.
Fill-quality TCA
GET /api/fill-quality/{account_id} — transaction-cost analysis. For every fill the importer captured an executed_at; if quote_snapshots has an NBBO sample around that timestamp, slippage is computed:
- Marketable buy — slippage is
fill - ask(positive = paid up; negative = price-improved). - Marketable sell — slippage is
bid - fill. - Resting orders — relative to mid; lower confidence.
Aggregated per broker, per symbol, per asset class, per hour. Catches "Broker X gives me 3¢ worse fills on options than Broker Y" — a real $$ insight if you trade enough size.
Drill-down + export
Every report cell is a drill-down link: clicking a "Tuesday" bar in by-day-of-week opens the Trades view pre-filtered to Tuesday trades in the report's date range and account scope. Same for symbol cells, R buckets, tag buckets.
The toolbar above every report has Export CSV and Export JSON. The CSV honors the visible filter; the JSON is the raw API response (useful for piping into a separate analysis script).
Date-range & scope
Every report has the same scope picker at the top: account / asset-class / date-range / tag. The picker is sticky across the session (stored in sessionStorage) so flipping between reports keeps your scope. Cmd+R reloads the current report with the current scope; R alone refreshes (matches the view-scoped refresh chord on the topbar).