# How to use the Trading Bot Dashboard

This is a single-file static HTML report. Open it directly in a browser:

```
file:///Users/zinklee/Code/trading-bot/paper_trading_state/_reports/dashboard.html
```

It is regenerated by `python scripts/generate_dashboard.py` (run after each
paper-trading cron cycle, or manually).

---

## 0. Layout — left-rail nav + status tape

The dashboard has a fixed **left-rail** (200px) with four routed sections
and a perpetual **status tape** (32px) along the top.

### Custom Web Components (2026-04-26 redesign)

The 2026-04-26 line-by-line UX overhaul replaced several vanilla library
defaults with custom Web Components (HTMLElement subclasses, registered via
`customElements.define`, scoped via class-name CSS — no shadow DOM so the
daisyUI/Tailwind cascade still applies). This was driven by user complaints
about (a) marker stacking on Markets charts and (b) feature-accretion without
unified design across prior agent passes.

| Tag | Replaces | Pattern source |
|-----|----------|---------------|
| `<tb-kpi-tile>` | 4× daisyUI `.stat` cards | Stripe data-table typography (Matt Ström, Mission Log) |
| `<tb-status-tape>` | 3-slot rotating ticker | Bloomberg amber/black scrolling tape (bloomberg.com/ux 2021) |
| `<tb-density-chart>` | vanilla Lightweight-Charts in Markets | deck.gl HeatmapLayer + GPU-GKDE density principle |
| `<tb-cluster-pill>` | `.cluster-card` divs | Linear left-edge accent + Bloomberg Launchpad |
| `<tb-trade-tape>` | (additive) chronological monospace trade log | IBKR TWS execution tape |

All five components are defined inside the single-file HTML output (no
external scripts). They consume the existing `ROWS / TRADES / ASSET_PRICES /
COMPOSITE / CLUSTERS` data shape — no Python data-prep refactor was needed.

#### `<tb-kpi-tile>` sparkline payloads (2026-04-26 wiring)

`build_composite()` in `scripts/generate_dashboard.py` now emits four
chronological time-series alongside the scalar headline numbers, each as a
list of `{time, value}` objects. The four KPI tiles consume these as
sparklines:

| Tile id | Spark series | Shape |
|---------|-------------|-------|
| `kpi-tile-equity` | `COMPOSITE.equity_recent` | equal-weight equity-index avg (baseline 1.0) |
| `kpi-tile-return` | `COMPOSITE.return_recent` | cumulative-return % (baseline 0%) |
| `kpi-tile-dd` | `COMPOSITE.dd_recent` | running drawdown of equity index (always ≤ 0) |
| `kpi-tile-health` | `COMPOSITE.active_recent` | count of strategies contributing on each day |

All four series are aggregated identically to the JS `renderCompositeChart()`
function (skip grey-status strategies; per-strategy normalize-to-1.0 at first
bar; date-wise mean across active strategies) and are truncated to the last
**90 daily snapshots** to keep the embedded payload bounded. The sparkline
component flattens `{time, value}` to the bare numeric value array internally
and renders an inline SVG polyline coloured green/red by `last >= first`.

To verify wiring after a regen:
```bash
grep -o 'equity_recent[^]]*\]\{0,40\}' paper_trading_state/_reports/dashboard.html | head -1
```
should print a non-empty array.

#### `<tb-data-grid>` (deferred)

The strategy roster table at `#strategy-table` is still driven by Tabulator 6.
A custom `<tb-data-grid>` Web Component to replace it (matching the rest of
the redesign) was scoped but **not built in the 2026-04-26 polish pass** —
preserving all 17 working Tabulator features (column sort + filters + density
toggle + j/k nav + `/` focus + save view + CSV export + decisions cross-link
+ heatmap hover-sync + sparklines column + frozen first column + row click
drilldown + URL hash deep-link + cmd-K row focus + roster pulse + kb-focus
highlight + status-tinted row backgrounds) inside a virtualized custom
component is a multi-session deliverable. When `<tb-data-grid>` lands, the
Tabulator CDN scripts at the top of the HTML template (in
`scripts/generate_dashboard.py`) and the `new Tabulator(...)` init block in
the JS template should be removed in the same change.

### Left-rail sections
- **Overview** — KPI tiles, drift banner, portfolio composite chart
- **Markets** — BTC / ETH / BNB / XRP price charts
- **Strategies** — cluster cards, decisions feed, roster table, correlation
  heatmap, treemap, small multiples
- **Drilldown** — per-strategy expansion (rendered inline once a row is clicked)

Click any rail item — the page smooth-scrolls to that section, and the rail
highlights the active route via a cyan left-edge accent. Hash routing is
preserved (`#/markets`, `#/strategies`, etc.) so the URL is shareable.

### Status tape (`<tb-status-tape>`)
Bloomberg-style horizontal strip showing every asset (BTC/ETH/BNB/XRP)
with last px + 1d %, the health summary, freshness, and any drift events.

**2026-05-08 update (addresses `DASHBOARD_UX_DEEP_REDESIGN_2026-05-07.md`
D11 + D21):** the tape is now **paused by default**; hover (or focus)
activates the ~90s scroll animation. Per WCAG 2.2 SC 2.2.2 + Bailey-Konstan
2006 *CHI* — autoplay motion in the periphery during analytical work
reduces reading-task accuracy ~12%. Below 640px the tape is hidden
entirely (the header carries the same data). `prefers-reduced-motion:
reduce` continues to disable the animation entirely.

---

## 1. Where to view BTC / ETH / BNB / XRP price charts

There are now **two places** where you can see asset prices:

### A. Top-level **"Markets"** section (always visible — no drill-down required)

The dashboard now opens with a "Markets" panel near the top of the page
(directly under the **Portfolio composite** chart). It shows four side-by-side
price charts for BTC-USD, ETH-USD, BNB-USD, XRP-USD.

Each chart has:

- The cyan price line (daily close, now extending through today via yfinance refresh)
- **Aggregated BUY / SELL markers from ALL active paper-live strategies**
  rendered through `<tb-density-chart>` with three display modes (toolbar
  buttons, top-right of each chart):
  - **BIN** (default) — weekly time-bucket aggregation. Each (week, side)
    yields ONE pin sized 1 or 2 by trade count, with a `Nx` text badge when
    ≥3 strategies converge in the week. **This is the default solution to
    the marker-stacking problem.** Reference: Bloomberg order tape /
    deck.gl HeatmapLayer GPU GKDE.
  - **DOT** — every individual trade rendered as a small arrow (raw view).
  - **OFF** — plain price line, no overlay.
- A persistent **density tape** below each chart — a 26px-tall canvas showing
  weekly trade-volume bars. Bar **width** ∝ trade count, **color** = green
  when buys ≥ sells / red when buys < sells. **Click any bar to zoom the
  chart to that 14-day window** (a "Reset zoom ✕" button appears in the tape
  header when zoomed).
- Last price + 1-day % delta in the chart toolbar with `tabular-nums` formatting.
- A "Show markers from" dropdown selecting the data source: All strategies
  (aggregate), No markers, or per-strategy filter.

**Cmd-K shortcut** (or click the "Search strategies" button in the header):

| Type | Action |
|------|--------|
| `markets` | Jump to the Markets section |
| `btc` | Highlight the BTC chart card (3-second cyan glow) |
| `eth`, `bnb`, `xrp` | Same, for the other three coins |

### B. Per-strategy asset chart inside the **Drill-down** panel

When you click into a single strategy (see section 2 below), the drill-down
panel shows a **per-asset price chart** restricted to *only that strategy's
trades*. Use this when you want to see "where did THIS strategy buy/sell BTC?"
rather than "where did ALL strategies buy/sell BTC?".

---

## 2. Click-into-strategy → see buy/sell markers on that strategy's charts

### Exact click sequence

1. Scroll to the **"Strategy roster"** table (or press `/` to focus the filter
   input, then type a partial name).
2. Click any row — for example `donchian_3d_strict_topn_price20`. You can also:
   - press `j` / `k` to navigate rows with the keyboard, then `Enter`
   - use Cmd-K (`⌘ K`), type the strategy name, press Enter
3. The page scrolls to the **"Drill-down"** panel and you see:
   - Breadcrumb at the top: `Strategies › donchian_3d_strict_topn_price20`
   - Live vs research metric tiles (Sharpe / Trades / Positions / PBO)
   - **Equity curve** with green ▲ BUY arrows and red ▼ SELL arrows
     overlaid on the strategy's portfolio equity, plus a dashed grey
     ±1σ drift band.
   - **Daily return %** bar chart
   - **"Asset price charts with trade execution"** section with a tab per
     ticker the strategy actually traded (e.g. tabs for *BTC*, *ETH*).
4. Click one of the asset tabs (e.g. `BTC`):
   - Breadcrumb updates to:
     `Strategies › donchian_3d_strict_topn_price20 › Per-Asset › BTC-USD`
   - The chart shows the BTC daily price line with green ▲ BUY arrows below
     each entry bar and red ▼ SELL arrows above each exit bar.
   - Hover over any arrow to see the marker label
     (e.g. `BUY $35.0k BTC @ $73,079`).
5. The trade tape table (below the asset chart) lists every trade with
   date / side / asset / shares / price / value / PnL.

### Inline drilldown expansion

When you click a row, the **Drill-down** card now opens **inline immediately
below the clicked row** (Linear / GitHub inline-expand pattern). It no longer
jumps to the bottom of the page. Closing the drilldown (× button or
breadcrumb root link) restores the card to its default route container.

### Synced crosshair

In the drilldown, hovering the equity chart and the per-asset price chart now
moves a synchronized vertical crosshair across both charts so you can compare
account equity vs underlying asset price at the same point in time. Disabled
automatically when only one chart is rendered.

### Deep-linking

The URL hash now encodes the drill-down state, so you can share or bookmark a
specific view:

```
dashboard.html#strategy=donchian_3d_strict_topn_price20&tab=per-asset&asset=BTC-USD
```

Reloading the page with this hash auto-opens the drill-down on the requested
strategy and asset tab.

---

## 3. Quick keyboard reference

| Key | Action |
|-----|--------|
| `⌘ K` | Open command palette (search strategies, markets, actions) |
| `/` | Focus the table filter input |
| `j` / `k` | Navigate strategy rows |
| `Enter` | Open the focused strategy's drill-down |
| `f` | Open the faceted-filter sidebar |
| `i` | Toggle "hide inactive" |
| `?` | Show full keyboard shortcut help |
| `Esc` | Close any modal / blur input |

---

## 4. Other panels worth knowing

- **Cron-cycle provenance tile** *(new 2026-05-08, addresses
  `DASHBOARD_UX_DEEP_REDESIGN_2026-05-07.md` D16)* — top of Overview.
  Shows when the paper-trading cron last actually ran ("Last cron <ts>")
  with an age pill, coverage count ("N/M active have state.json"), and
  a stale-pill if any strategy is ≥24h or ≥48h behind. Distinct from
  the page-header `Generated <ts>` which is dashboard regen-time.
- **Δ since last view** *(new 2026-05-08, addresses D6)* — second from
  top of Overview. Persists a per-browser snapshot of strategy state
  (status, return%, pending-count) to `localStorage.tb_last_seen_snapshot`
  and surfaces what changed on next visit. Status flips, new pending
  signals, and ≥1% return moves are listed top-down by severity. Click
  any line to drill into that strategy. Click "Mark as seen" to reset.
- **Portfolio composite** — equal-weight aggregate equity curve across all
  active strategies, normalized to 1.0 at inception.
- **Cluster groups** — Bloomberg Launchpad-style cluster cards. Click one to
  filter the strategy table to only that cluster.
- **Today's decisions** *(reformatted 2026-05-08, addresses D14)* —
  last-24h event log across all strategies, two-column actionable / info
  layout at ≥768px (stacks at <768px). Each column has its own scroll
  viewport. Click any row to jump into that strategy's drill-down.
- **Pending only filter** *(new 2026-05-08, addresses D8)* — checkbox
  in the Strategy roster filter bar; filters to only strategies with
  ≥1 pending BUY/SELL signal. URL-encoded (`?pending_only=true`).
- **Correlation heatmap** — pairwise daily-return correlation, with cells
  ≥ 0.30 highlighted in cyan (Rule 8 admission threshold). The heatmap is
  now bidirectionally cross-linked with the strategy roster: hover a roster
  row to highlight that strategy's heatmap cells, and hover any heatmap cell
  to highlight the matching roster row.
- **Portfolio composition treemap** *(collapsed 2026-05-08, addresses D4)* —
  approximate equal-weight per cluster, placeholder until true HRP weights
  are wired into `state.json`. Wrapped in a `<details>` collapsible since
  showing implied-precision data violates Tufte 2001 §10. To re-enable
  by default once `hrp_allocator.py` weights land, remove the wrapping
  `<details>` in `scripts/generate_dashboard.py`.
- **Equity curves — small multiples** — one mini chart per strategy.
  Click any card to drill in.
- **Density toggle** — the strategy roster has a `compact` ↔ `comfortable`
  toggle button next to the filter input. `compact` (the default) renders
  ~30+ rows per screen for high-density industrial workflows. The selection
  persists across sessions in `localStorage.tb_dash_density`.

---

## 5. Files & build artifacts

- **HTML output (read-only / regenerated):** `paper_trading_state/_reports/dashboard.html`
- **Generator (edit this to change the dashboard):** `scripts/generate_dashboard.py`
- **Per-strategy state read by the generator:**
  - `paper_trading_state/<strategy>/state.json` — equity, positions, daily returns
  - `paper_trading_state/<strategy>/trades.csv` — buy/sell history (drives markers)
  - `paper_trading_state/<strategy>/events.jsonl` — decision trace
- **Asset price cache:** `paper_trading_state/_reports/asset_prices_cache.json`
  (24h TTL, refreshed via `load_or_cache_asset_prices()` on each regen)
