Skip to content

Dashboard walkthrough — from cold start to first paper fill

End-to-end tour of QE Dashboard.app: setup → research → backtest → live paper trading. Read this once; come back to the per-feature docs for depth.

Cross-references:

0. One-time setup

Build

cmake --preset=release
cmake --build --preset=release -j
open "build/release/bin/QE Dashboard.app"          # macOS
./build/release/bin/qe_dashboard                   # Linux

First launch writes a workspace at ~/Library/Application Support/qe_dashboard/workspace/ (macOS) or the XDG equivalent on Linux: six starter example_*.qe files plus a positions.json. F3 WKSP opens to that folder so you're never staring at an empty pane.

Pick a broker

Two paths, both safe to learn on. Configure once, change later via Cmd+,.

Broker Cred source Notes
alpaca-paper ALPACA_KEY_ID / ALPACA_SECRET_KEY env vars US equities only. No setup beyond the env vars.
ibkr-paper TWS or IB Gateway logged into a paper account Multi-asset, multi-currency. Need Gateway running first — see ibkr-connectivity.md.
ibkr-live TWS/Gateway logged into a live account Requires IBKR_LIVE_TRADING=I_KNOW_WHAT_I_AM_DOING env var and a typed-confirmation modal. Don't pick this until you've done the paper checklist end-to-end.

1. Cmd+, — Settings pass

Open the Settings modal, walk top-to-bottom:

Section Field What to set
General Refresh interval 5s default is fine
General Vim mode On if you want vim motions in F3
Data feeds Yahoo news On — drives F1 NEWS
Data feeds L2 streaming On — drives F2 DEPTH (needs Alpaca creds)
Trading Broker alpaca-paper or ibkr-paper
Trading IBKR host / port 127.0.0.1 / 4002 for Gateway paper
Trading IBKR client id 1 (any unused int)
Research Factor window / K Defaults are fine

Close Settings → top bar shows the broker badge (PAPER · alpaca-paper, PAPER · ibkr-paper, or LIVE in red). Edits auto-save on close and on app exit.

The watchlist is not edited from Settings — edit it in-place on F1 MAIN (Cmd+P style fuzzy add, ↑/↓ to focus).

2. The screens, in workflow order

Tab / Shift+Tab cycles through F1–F6 in display order. F-keys jump directly. F12 quits, Cmd+Q also quits.

F1 MAIN — see the market

Watchlist + ImPlot candles + positions/tape + Yahoo news.

  • / (or j / k in vim mode) — focus prev/next symbol
  • Click a watchlist row — focus that symbol (chart panel follows)
  • + ADD — async fuzzy search by ticker or company name
  • POSITIONS rows are LIVE from positions_json; TAPE shows the most recent fills your broker reported

F2 DEPTH — drill into microstructure

L2 book + Time & Sales + spread/imbalance/vol-burst widgets + ORDER TICKET.

  • Use this to time an entry — look at where the liquidity is, what's clearing, what the imbalance is doing.
  • ORDER TICKET is where new orders get submitted (qty, side, type, limit price → Submit). Read-only when broker = Disabled.
  • WORKING ORDERS at the bottom of this screen mirrors F6's blotter — convenient while you're staring at the book.

F3 WKSP — write / edit strategies

File tree (left) + multi-tab editor (right) + run log (bottom).

  • Click any .qe file in the tree to open as a tab.
  • Shift+H / Shift+L cycle tabs; Cmd+W closes the active tab.
  • Cmd+S is the bus stop:
  • .qe backtest → forks qe_run, stdout/stderr into the log, results.json lands → F4 BCKT auto-refreshes.
  • .qe sweep → loads spec into F4 BCKT's sweep panel, runs it.
  • positions.json → re-mounts as live positions, F1 / F5 auto-refresh.
  • Vim mode (toggle Cmd+Shift+V): i a I A o O insert, h j k l w b e 0 ^ $ gg G motions with counts, x X dd yy p P u Ctrl-R edits, D C v V line/visual operations, :w :bd :q ex.

Minimal .qe example (in backtests/example_ma_spy.qe):

let fast = 10
let slow = 50

backtest(
  data     = yahoo("SPY", "1d", "2024-01-01", "2024-12-31"),
  strategy = signal(
    entry  = cross_above(sma(close, fast), sma(close, slow)),
    exit   = cross_below(sma(close, fast), sma(close, slow)),
    symbol = "SPY",
    size   = 1.0,
  ),
  execution = execution(capital = 100_000, commission_bps = 1.0),
  output    = output(results = "out/ma_spy.json"),
)

Full grammar: docs/qe-language.md.

F4 BCKT — review results

Sweep matrix (top) + equity curve + KPIs + recent fills + monthly returns heatmap.

  • If F3 saved a single-config backtest: equity / KPIs / monthly matrix render off the produced results.json.
  • If F3 saved a sweep: sweep matrix on top (2D bucketed, ◆ on the best cell). Click any cell → re-runs that config with let-overrides, re-points results_json at the new file, rest of the screen swaps to that cell's results.
  • Monthly matrix uses a 3-tier diverging palette (red / neutral / green); NaN cells are dim gray.

F5 RISK — portfolio risk

Always-on meta strip (NAV / Gross / Net / Leverage / Long-Short / VaR95 / ES99) over four sub-tabs:

Tab What's live
Overview Concentration glance (per-symbol or per-sector if mapped)
Greeks Black-Scholes Δ/Γ/ν/Θ/ρ per leg + Σ; needs positions_json.options[]. Equity-only Δ$ if no options.
VaR & Stress VaR/ES via historical / parametric + 8 spot+vol scenarios
Factor PCA correlation matrix + portfolio exposures + per-PC stats + strategy IC

Each tab degrades to a "no data — set positions_json" hint when its inputs aren't available. Active tab is persisted across launches.

F6 TRADE — manage live orders

Five panels + safety footer:

WORKING ORDERS                          EXECUTIONS (last 50)
ID    SYM   SIDE QTY    PX     STATE    TIME      SYM  SIDE QTY  PX
o-17  AAPL  BUY  0/10   150.50 WORK     14:32:05  SPY  BUY  1    495.10
o-18  SPY   SELL 3/5    495.50 PART     14:31:48  AAPL SELL 5    149.80
[Cancel] inline per row                 …

ACCOUNT · CAD                           ORDER LOG
cash          1,000,000.00              14:30:01 submit_attempt  AAPL BUY 10 @ 150.50
buying power  4,000,000.00              14:30:02 submit_accepted AAPL
equity        1,000,000.00              14:31:48 fill            SPY 1 @ 495.10
day P&L       +231.12 (+0.40%)          14:32:05 fill            AAPL 5 @ 150.42
  account: DUQ526944                    … auto-stick to bottom
  refreshed: 3s ago

SAFETY  ·  kill: armed  ·  reconcile: clean  ·  broker: PAPER ibkr-paper
[Trip kill-switch]   [Reconnect broker]   [Re-reconcile now]
  • WORKING ORDERS is sortable; per-row Cancel button. Empty state shows "no working orders".
  • EXECUTIONS tails OrderLog fill events, newest first.
  • ACCOUNT header carries the currency code (USD / CAD / …) from the broker's account snapshot.
  • ORDER LOG color-codes by kind: rejects/failures red, accepts green, attempts dim. Auto-sticks to bottom unless you've scrolled up.
  • SAFETY footer: three live status badges + three buttons — same actions as the Broker menu, but visible without a click while you're trading.

By design F6 has no order ticket — new orders are submitted from F2 DEPTH so you're looking at the book while you size. F6 is for managing what's already live.

3. End-to-end paper-trade flow

0. Gateway / Alpaca creds OK     · top-bar badge shows PAPER
1. F1 MAIN  : add symbol         · ↑/↓ to focus the one you want
2. F2 DEPTH : eyeball the book   · pick a limit price
3. F2 ticket: Submit             · WORKING ORDERS row appears
4. F6 TRADE : watch the fill     · ORDER LOG / EXECUTIONS update
5. (repeat 2–4 as needed)
6. Cmd+Shift+X if anything looks wrong  → KILL ·  no new orders
7. Cmd+Q

Research-only session (no live broker):

1. F3 WKSP : edit a .qe          · vim or plain text
2. Cmd+S   : qe_run forks        · log streams into F3
3. F4 BCKT : equity / KPIs       · auto-refreshes on save
4. (iterate)
5. Cmd+Q

4. Safety net — what each guard does

Trigger Effect
Cmd+Shift+X Global kill-switch tripped. New submit_order is rejected. Cancel + read-only calls keep working so you can drain open orders. First-trip-wins: only the first chord captures a reason; later presses are no-ops. Persists until restart.
Actual positions ≠ broker positions Reconcile worker pops a read-only drift modal. No auto-fix. You decide whether to adjust manually in the broker UI. See live-trading-safety.md.
Broker socket drops Top-bar badge → BROKER OFFLINE. Reconnect via Broker menu or F6 SAFETY [Reconnect broker].
Day-loss limit exceeded SafeBroker rejects new orders once day_pl crosses the configured threshold. IBKR day_pl arrives via the account stream.
ibkr-live selection Requires IBKR_LIVE_TRADING=I_KNOW_WHAT_I_AM_DOING env var and typing the broker name into the confirmation modal. Triple gate; deliberately annoying.

5. Persistence — what survives a restart

State Persisted? Where
Watchlist / focused symbol config.json (auto-save on exit)
Broker selection + IBKR knobs config.json
Workspace path + active backtest/sweep file config.json
Active F5 RISK tab config.json
Layout splitter positions config.json (per-screen)
F3 editor open tabs Re-open from the tree next session
Working orders at the broker ✓ (broker side) TWS / Gateway / Alpaca keeps them; dashboard re-syncs on reconnect
Kill-switch state Always armed on launch — by design

6. Common surprises

  • F6 ACCOUNT shows zeros under IBKR. Older builds returned an empty AccountInfo stub. Update to a recent build with the account-stream wiring; cash / buying_power / equity / day_pl populate from REQ_ACCOUNT_DATA.
  • Historical Data Farm is Inactive: ushmds in Gateway. Informational, not an error. Means "no one's requesting historical bars; the connection is dormant". We don't use IBKR for historical data (Yahoo handles that). Ignore.
  • F4 BCKT empty after Cmd+S. The .qe's output(results = …) path is relative to the workspace root; check the path printed in F3's log pane resolves to a writable directory.
  • Vim cursor not highlighted on F3 tree. Already fixed in a recent build; if you see this, rebuild.
  • F6 TRADE blotter row says WORK but never moves. Check the order is within trading hours for the symbol's exchange. Outside hours, IBKR holds the order; Alpaca paper accepts but won't simulate fills.

7. Where to look next