Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FastAPI Trading Dashboard

A real-time trading dashboard built on FastAPI and WebSockets — the kind of interface you move to when a Jupyter/Voila + ipywidgets front-end has gone as far as it can.

Dashboard, live

Recorded from a running instance — prices ticking, chart appending, values flashing on update.

Dashboard, dark theme

Light theme

Dashboard, light theme

pip install -r requirements.txt
uvicorn app.main:app --reload
# http://127.0.0.1:8000

No API keys, no database, no build step. It runs immediately against a synthetic feed.

What's here

  • Live streaming over a WebSocket, ~2 updates/sec — equity, P&L, prices, positions and strategy state
  • Candlestick chart (Plotly) that appends bars in place rather than redrawing history on every tick
  • Instrument switching without reconnecting — the client sends {"symbol": "ETH-USD"} on the open socket
  • Dark and light themes, switched by one data-theme attribute
  • Positions table with per-position P&L and P&L %
  • Control panel — sliders, a toggle, an action button (UI-wired only)
  • Auto-reconnect with capped exponential backoff

Why it's built this way

The strategy layer only produces a Snapshot. Nothing in the transport or the templates knows where the numbers came from, so replacing app/feed.py with a live broker connection touches no other file. That boundary is the whole point of moving off a notebook — in Voila the UI and the strategy are the same process, and you cannot change one without risking the other.

Updates are surgical, not re-renders. At two pushes a second, re-rendering the table or redrawing the full chart drops frames on a laptop. New bars are appended via Plotly.react; KPI values are direct textContent writes.

Numbers use tabular figures. font-variant-numeric: tabular-nums keeps columns from jittering as digits change — with a price updating twice a second, proportional digits make the whole layout shiver.

The update flash is deliberately restrained. A brief tint that hugs the digits, not a full-card highlight. Something you can sit in front of for eight hours.

Theming is a token swap. Every colour is a CSS custom property; the light theme redefines the tokens and changes nothing else. Plotly is the exception — its colours aren't CSS-driven, so the chart is redrawn on theme change.

Layout

app/
  main.py               FastAPI app — routes, WebSocket, lifecycle
  feed.py               synthetic market data (swap this for a real feed)
  templates/
    base.html           shell, top bar, theme toggle
    dashboard.html      KPIs, chart, rail, positions table
  static/
    css/style.css       design tokens + components
    js/dashboard.js     WebSocket client, chart, DOM updates

API

Method Path Purpose
GET / dashboard
GET /api/candles/{symbol} OHLC history for first paint
GET /api/snapshot/{symbol} single snapshot (polling fallback)
WS /ws/{symbol} live stream; accepts {"symbol": "..."} to switch
GET /healthz liveness
GET /api/docs generated OpenAPI docs

Connecting a real feed

Replace Feed.next_snapshot() in app/feed.py so it returns a Snapshot built from your own data. The dataclass is the contract:

Snapshot(
    ts, symbol, price, change_pct,
    equity, day_pnl, win_rate, open_positions, exposure,
    positions=[...],   # dicts: symbol, side, qty, entry, mark, pnl, pnl_pct
    signals=[...],     # dicts: name, value, tone ∈ {pos, neg, flat}
)

Nothing else needs to change.

Notes

Controls are wired to the interface only — no orders are placed and no strategy runs. This is a front-end and transport demonstration, not a trading system.

License

MIT

About

Real-time dashboard in FastAPI — WebSocket streaming, live candlestick charts, dark and light themes. What you move to when a Jupyter/Voila front-end runs out of road.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages