Portfolio dashboard
Your home base. Shows live positions, cumulative return chart, risk-return scatter, top winners/losers, and an always-on PM chat. This is the page you'll have open during a trading session.
Overview
The dashboard composes data from three sources: the active broker (positions + buying power), the audit ledger (decisions + orders), and the optimization engine (suggested target weights). Refresh cadence is 5 seconds for live broker state, on-demand for analytics.
Panel by panel
Header strip
Account state across the top. From left to right:
- Equity — current total account value (positions marked-to-last-close + cash).
- Day Δ — change since previous close, in $ and %.
- Buying power — broker-reported buying power (2× cash for Alpaca paper margin accounts).
- Cash — settled cash.
- Active broker chip — click to switch. The switch is instantaneous (no restart). See broker switcher.
Positions table
One row per non-zero position. Columns: symbol, shares, avg entry, last, mark, P&L $, P&L %. Sort by any column. Filter via the search box (substring match). Click a row to open the symbol's Research workbench tab.
Cumulative return chart
X-axis = time, Y-axis = % return from inception. Series shown:
- Portfolio — derived from broker fill history (each fill stamps a position change; chart aggregates).
- SPY benchmark — daily yfinance close, indexed at the same start date.
- Buy & hold equal-weight basket — what you would have if you'd just bought your top-3 names at start.
If there are no fills in the visible window (fresh account or weekend after a Friday submit), the chart renders flat with a note telling you what happened — not empty/blank.
Risk-return scatter
Each point is one symbol you hold. X = realized annualized vol over the last 60 trading days. Y = annualized return. Bubble size = position $ value. Click a bubble to focus the cumulative chart on that name.
Embedded PM chat
Bottom-right panel. Routes through Kimi K2.6 by default (configurable via CHAT_MODELS). 20 registered tools — order placement, backtest runs, sleeve compare, Setup Wizard, etc. See PM chat.
Triggering a rebalance
Click Rebalance → in the header. The modal opens:
- Pick a sleeve (Core/Sat/Tac).
- Review the optimizer's proposed weights (cuFOLIO solve, ~520 ms).
- Compliance section shows hard/soft/warn vetos. Anything red blocks submit.
- Three actions:
- Approve — submits orders to the active broker. Each order is logged with broker order id + rationale.
- Override — kills submit; logs your reason as a training signal for the DPO flywheel.
- Reject — kills submit; logs as "didn't like this whole plan."
Every choice writes to data/audit/rebalance_decisions.jsonl, the source of truth for the preference learning flywheel.
How to interpret what you see
| signal | likely cause | action |
|---|---|---|
| Cumulative chart is flat | No fills in window | Check Orders — pending vs filled. |
| Day Δ ≠ broker site | Out-of-hours mark vs intraday | Reload after market open. |
| Buying power vs cash mismatch | Margin account | Expected; 2× cash for Alpaca paper. |
| Rebalance modal red | Compliance hard veto | Read the rule that fired; either edit sleeve config or accept and override. |
Customize the dashboard
Per-tenant theming sits at Account → Tenant theme. Logo, primary/accent colors, custom CSS — all injected site-wide via the shared auth.js bootstrap. The dashboard layout itself is in mockups/dashboard.html; chart series colors honor the tenant accent.
To add a panel, drop another <section> into dashboard.html and wire its data via fetch('/api/<your-endpoint>'). The Tailwind utility classes + the panel/panelHi/border color tokens keep new panels visually consistent.
REST surface
| Verb | Path | Purpose |
|---|---|---|
| GET | /api/portfolio/state | Equity, day Δ, buying power, cash, positions, active broker. |
| GET | /api/portfolio/equity?since=ISO | Cumulative return series for the chart. |
| GET | /api/portfolio/risk_return | Per-holding vol+return for the scatter. |
| POST | /api/portfolio/rebalance | Returns optimizer plan + compliance verdict. |
| POST | /api/portfolio/decision | Approve/Override/Reject — writes audit + (optionally) submits orders. |