Market Deck is a local dashboard for ranking financial assets by momentum and viewing trailing monthly returns in a heatmap. It supports multiple watchlists, server-side Yahoo Finance price loading, historical FX conversion into a shared base currency, and inline editing backed by SQLite.
- Momentum rankings for 1M, 3M, 6M, and 12M lookbacks
- Monthly heatmap with a trailing 12M return column
- Multiple editable watchlists with per-ticker tags and currencies
- Global base currency conversion using historical FX series from Yahoo Finance
- Built-in CRUD UI for watchlists, tickers, and tag colors
- Server-side price fetching with caching and safer request handling
- Client-side reuse of fetched ticker and FX histories across list visits
- Watchlist categories are stored and edited in uppercase
- Tag color names are stored and edited in uppercase
- Frontend: vanilla HTML, CSS, and JavaScript
- Backend: FastAPI + Uvicorn
- Database: SQLite (
data.db) - Market data: Yahoo Finance via
yfinance
.
|-- index.html
|-- server.py
|-- static/
| |-- app.js
| `-- styles.css
|-- scripts/
| |-- get_volumes.py
| `-- migrate.py
`-- data/
|-- colors.json
|-- lists.json
`-- volumes.json
data.db is generated locally and is ignored by git.
- Install Python 3.10+.
- Install dependencies:
pip install fastapi uvicorn pydantic yfinance pandas- If you do not already have
data.db, create it from the legacy JSON files:
python scripts/migrate.py- Start the server:
python server.py- Open http://localhost:8000.
python scripts/migrate.pyThis recreates data.db from data/lists.json and data/colors.json.
Warning: running it again destroys existing UI edits stored in the database.
python scripts/get_volumes.pyThis reads data/lists.json and writes data/volumes.json.
GET /api/initreturns settings, tag colors, watchlists, and tickersGET /api/settingsreturns all settingsPUT /api/settings/{key}updates a setting such asGLOBAL_BASE_CURRENCYPOST /api/listscreates a watchlistPUT /api/lists/{slug}updates watchlist metadataDELETE /api/lists/{slug}deletes a watchlist and its tickersPOST /api/lists/{slug}/tickersadds a ticker to a watchlistPUT /api/tickers/{id}updates a tickerDELETE /api/tickers/{id}deletes a tickerPUT /api/tag-colors/{tag}upserts a tag colorDELETE /api/tag-colors/{tag}deletes a tag colorPOST /api/pricesfetches historical price dataDELETE /api/prices/cacheclears the server-side price cache
- The app serves local files through a guarded catch-all route and rejects path traversal attempts.
- The frontend now keeps list loads alive in the background when you switch views quickly, so returning to a still-loading list reuses the existing request instead of restarting it.
- The server retries tickers that come back missing from a batch Yahoo Finance response, which helps reduce partial list loads.
- Price and CRUD requests now surface HTTP errors instead of silently acting like they succeeded.