115 lines
3.6 KiB
Markdown
115 lines
3.6 KiB
Markdown
# Market Screener UI
|
||
|
||
SvelteKit 5 dashboard for the [Market Screener](../market_screener) API. Provides an interactive interface for screening stocks, ETFs, and bonds — and tracking your portfolio with live hold/sell/add advice.
|
||
|
||
---
|
||
|
||
## Quick Start
|
||
|
||
This UI requires the Market Screener API running on port 3000.
|
||
|
||
```bash
|
||
# Recommended: start both from the API repo
|
||
cd ../market_screener
|
||
npm run dev # starts API (:3000) + this UI (:5173) together
|
||
|
||
# Or start the UI independently
|
||
npm install
|
||
npm run dev # http://localhost:5173
|
||
```
|
||
|
||
---
|
||
|
||
## Pages
|
||
|
||
### Screener (`/`)
|
||
|
||
- Enter any tickers (comma or space separated) and click **Screen**
|
||
- Click **📰 Catalysts** to load today's news-driven tickers and screen them automatically (one click)
|
||
- Market context strip shows live benchmarks: 10Y yield, VIX, S&P 500, P/E ratios, rate regime
|
||
- Signal Summary table ranks all assets by signal strength
|
||
- Drill-down tables for Stocks, ETFs, and Bonds with **Mkt-Adjusted** / **Graham** tab toggle
|
||
- Ticker column stays pinned while scrolling wide tables
|
||
|
||
### Portfolio (`/portfolio`)
|
||
|
||
- Reads `portfolio.json` from the API server
|
||
- Shows total value, cost basis, and unrealised G/L
|
||
- Per-holding advice: ✅ Hold & Add, 🟡 Reduce, 🔴 Sell
|
||
- If SimpleFIN is configured: net worth, account balances, 30-day spending breakdown
|
||
|
||
---
|
||
|
||
## Signals Explained
|
||
|
||
| Signal | Meaning |
|
||
|---|---|
|
||
| ✅ Strong Buy | Passes both Market-Adjusted AND Fundamental gates |
|
||
| ⚡ Momentum | Passes market-adjusted, holds fundamentally |
|
||
| ⚠️ Speculation | Passes market-adjusted, fails fundamental — priced for perfection |
|
||
| 🔄 Neutral | Hold territory in one or both lenses |
|
||
| ❌ Avoid | Fails both gates |
|
||
|
||
The **Mkt-Adjusted** tab uses gates derived from live market data (e.g. S&P P/E × 1.5 for the P/E gate). The **Graham** tab uses strict historical value-investing gates (P/E < 15×, PEG < 1.0).
|
||
|
||
---
|
||
|
||
## Tech Stack
|
||
|
||
| Layer | Choice |
|
||
|---|---|
|
||
| Framework | SvelteKit 2 + Svelte 5 |
|
||
| Build tool | Vite 6 |
|
||
| Adapter | `@sveltejs/adapter-auto` |
|
||
| Rendering | Client-side only (SSR disabled) |
|
||
| API | Proxied via Vite dev server → Fastify on :3000 |
|
||
|
||
---
|
||
|
||
## Project Structure
|
||
|
||
```
|
||
src/
|
||
app.html HTML shell
|
||
app.css Global reset + dark theme base
|
||
routes/
|
||
+layout.js ssr = false
|
||
+layout.svelte Nav bar
|
||
+page.svelte Screener page
|
||
portfolio/
|
||
+page.js load() → fetches /api/finance/portfolio
|
||
+page.svelte Portfolio + SimpleFIN page
|
||
lib/
|
||
api.js All API fetch functions
|
||
SignalBadge.svelte Signal pill component
|
||
MarketContext.svelte Benchmark strip component
|
||
|
||
vite.config.js /api proxy → localhost:3000
|
||
svelte.config.js SvelteKit config
|
||
```
|
||
|
||
---
|
||
|
||
## Configuration
|
||
|
||
### API URL
|
||
In `vite.config.js`, the Vite dev server proxies `/api/*` to `http://localhost:3000`. To point at a different API host, update the `proxy` target there.
|
||
|
||
For production, configure your reverse proxy (nginx, Caddy, etc.) to route `/api/*` to the Fastify server.
|
||
|
||
### CORS
|
||
The Fastify API allows `http://localhost:5173` by default. If you deploy the UI to a different origin, set `CLIENT_ORIGIN` in the API's `.env`:
|
||
```
|
||
CLIENT_ORIGIN=https://your-deployed-ui.example.com
|
||
```
|
||
|
||
---
|
||
|
||
## Development Notes
|
||
|
||
- Uses Svelte 5 runes: `$state`, `$derived`, `$derived.by`, `$props`
|
||
- `onclick={handler}` not `on:click` — Svelte 5 syntax
|
||
- Page data loaded via `+page.js` `load()` function, not `onMount`
|
||
- Global CSS lives in `src/app.css` — no `:global()` in component `<style>` blocks
|
||
- `asset.displayMetrics` (plain object from API) — never call `getDisplayMetrics()` in the browser
|