# PHASES.md Complete roadmap for market-screener evolution from Phase 9 through Phase 16+. ## Phase 9 — Subdomain Restructure: Server Layer Organization **Goal:** Reorganize `server/` from flat layer-based structure to domain-driven structure. **Timeline:** 3 weeks. ### 9a — Create shared infrastructure layer Create `server/domains/shared/` hierarchy: ``` server/domains/shared/ ├── entities/ (models + their types together) │ ├── Asset.ts │ ├── Stock.ts │ ├── Etf.ts │ ├── Bond.ts │ └── index.ts ├── adapters/ (external API wrappers, renamed from "clients") │ ├── YahooFinanceAdapter.ts │ ├── AnthropicAdapter.ts │ ├── SimpleFINAdapter.ts │ └── index.ts ├── services/ (cross-domain services) │ ├── BenchmarkProvider.ts │ ├── CatalystAnalyst.ts │ ├── LLMAnalyst.ts │ └── index.ts ├── scoring/ (rules + regime management) │ ├── ScoringConfig.ts │ ├── GateValidator.ts │ ├── MarketRegime.ts │ └── index.ts ├── persistence/ (SQLite stores) │ ├── MarketCallStore.ts │ ├── PortfolioStore.ts │ └── index.ts ├── types/ (all domain types) │ ├── asset.model.ts │ ├── finance.model.ts │ ├── market.model.ts │ ├── [...other models] │ └── index.ts ├── config/ │ └── constants.ts ├── utils/ │ ├── logger.ts │ ├── Chunker.ts │ └── index.ts ├── db/ │ └── index.ts ├── schemas.ts └── index.ts ``` ### 9b — Extract screener domain ``` server/domains/screener/ ├── ScreenerController.ts ├── ScreenerEngine.ts ├── PersonalFinanceAnalyzer.ts ├── scorers/ │ ├── StockScorer.ts │ ├── EtfScorer.ts │ ├── BondScorer.ts │ └── index.ts ├── transform/ │ ├── DataMapper.ts │ ├── RuleMerger.ts │ └── index.ts └── index.ts ``` ### 9c — Extract portfolio domain ``` server/domains/portfolio/ ├── PortfolioController.ts ├── PortfolioAdvisor.ts ├── persistence/ │ └── PortfolioStore.ts └── index.ts ``` ### 9d — Extract calls domain ``` server/domains/calls/ ├── CallsController.ts ├── CalendarService.ts ├── persistence/ │ └── MarketCallStore.ts └── index.ts ``` ### 9e — Extract finance domain ``` server/domains/finance/ ├── FinanceController.ts └── index.ts ``` ### 9f — Clean up old directories Remove: `server/controllers/`, `server/services/`, `server/repositories/`, `server/clients/`, `server/models/`, `server/scorers/`, `server/config/`, `server/types/`, `server/utils/` ### 9g — Update documentation in CLAUDE.md Update "Server layer map" section with new domain structure. ### 9h — Smoke test all routes Create integration smoke test verifying all major routes work after restructure. --- ## Phase 10 — UI Component Restructure & Clarity **Goal:** Mirror Phase 9 server restructure at UI layer. Organize components by domain. **Timeline:** 1 week. ### 10a — Create component hierarchy ``` ui/src/lib/components/ ├── shared/ │ ├── Spinner.svelte │ ├── VerdictPill.svelte │ ├── SignalBadge.svelte │ └── index.ts ├── screener/ │ ├── AssetTable.svelte │ ├── AnalysisSidebar.svelte │ └── index.ts ├── portfolio/ │ ├── AddHoldingForm.svelte │ ├── AdviceTable.svelte │ └── index.ts └── calls/ ├── CallForm.svelte ├── CallCard.svelte └── index.ts ``` ### 10b — Split utils and types ``` lib/utils/ ├── formatting.ts ├── sorting.ts ├── verdicts.ts └── index.ts lib/types/ ├── ui.types.ts ├── portfolio.types.ts └── index.ts ``` ### 10c — Update all imports in routes + stores ### 10d — Extract reusable layout components ### 10e — UI Phase 10 complete --- ## Phase 10.5 — Professional-Grade Screener UI (Institutional Research Tool) **Goal:** Build professional screener interface showing complete investment research capabilities. **Timeline:** 4-6 weeks (after Phase 10). ### 10.5a — Three-Layer Layout ``` Sidebar (280px) | Main Table (flex) | Tearsheet Panel (420px) ────────────────┼──────────────────┼────────────────────── Advanced │ Compact table │ Forensic detail filters │ 10 columns only │ Full metrics (left) │ │ Peer comparison │ Scannable │ Decision framework Quick presets │ minimal │ Risk breakdown │ │ (right side-panel) ``` ### 10.5b — Sidebar: Advanced Filtering - Preset buttons: All, Strong Buy, Buy, Hold, Avoid - Custom filters: P/E Range, ROE Min, Dip %, D/E Max - Quick presets: "Value Trap Screen", "Growth at Fair Price", "Dip Opportunity" ### 10.5c — Main Table: Minimal, Scannable 10 columns: Ticker | Price | Verdict | Score | P/E | ROE | 52W | DCF | Flags | Menu - Sortable, sticky header - Monospace numbers (professional) - Color-coded metrics - Click row → opens tearsheet ### 10.5d — Tearsheet Panel: Professional Research Right-side slide-in (420px) with sections: 1. Core Metrics (4-grid, color-coded cards) 2. Valuation Context (comparison table) 3. Decision Framework (gate-by-gate breakdown) 4. Risk Breakdown (ranked, quantified) 5. Threshold Sensitivity (what-if scenarios) 6. Peer Comparison 7. CTA Row (Add to Watchlist, Decision Log) ### 10.5e — Decision Logging & Backtest - Save thesis + entry date/price - Track 30/60/90 day outcomes - Simple review modal ("did thesis play out?") - Backtest dashboard (win rate by signal type) ### 10.5f — Implementation (Phased) - Week 1-2: Core UI (sidebar, table, tearsheet basic) - Week 2-3: Tearsheet sections (all 7 sections) - Week 3-4: Interactivity (sorting, filters, animation) - Week 4-5: Decision logging - Week 5-6: Backtest dashboard (optional) --- ## Phase 10.6 — Portfolio Integration: Market Analysis → Action **Goal:** Connect screener signals + market context to portfolio decisions. ### 10.6a — Market-Aware Position Sizing Auto-calculate recommended position size based on: - Stock verdict - Market regime - Sector momentum - Portfolio allocation Display: "Recommended: 2-4% of portfolio" or "$2,000-$4,000" ### 10.6b — Portfolio Dashboard: Integrated View Single screen showing: 1. Holdings + P&L 2. Allocation vs Target 3. Market Context 4. Screener Signals 5. Recommended Action ### 10.6c — Screener-Portfolio Bridge Add "Your Holdings" column in screener showing: - "You own 2% | +$1,000 gain" - Verdict changes - Thesis change alerts ### 10.6d — Thesis Journal (Simplified) When adding position: 1. Why I'm buying (pick ONE reason) 2. What I'll watch (pick 1-2 metrics) 3. Review date (auto 30 days) ### 10.6e — Rebalancing Advisor Monitor allocation vs target. When screener verdict changes on existing holding, suggest action. --- ## Phase 10.7 — Newbie UX: Progressive Disclosure **Goal:** Professional tool with newbie-friendly interface. Same power, different experience. ### 10.7a — Screener Entry: Strategy-Based Instead of filters, ask: "What are you looking for?" Options: - ○ Solid companies at good prices (Balanced) - ○ Hot stocks with momentum (Momentum) - ○ Beaten-down bargains (Value) - ○ Let me customize filters (Advanced) ### 10.7b — Table View: Plain Language Explanations Minimal table: Ticker | Price | Verdict | Why? ℹ️ Clicking "ℹ️" shows plain-language explanation with reasons, scores, and what it means. ### 10.7c — Buy Decision Helper Calculate recommended position size automatically. Show: - Star rating (intuitive) - Concrete dollars (not abstract %) - Clear "safe" path highlighted ### 10.7d — Portfolio Status View (Not Analysis) Show status + guidance, not complex metrics: - Visual breakdown (bars) - What it means - Concrete actions (sell, buy, do nothing) ### 10.7e — Market Context: Status Light + Impact Use traffic light system: - 🟢 Good / ⚠️ Mixed / 🔴 Bad - Plain explanation of why - Impact on YOUR portfolio ### 10.7f — Thesis Logging: Simple Checklist Pick ONE reason + 1-2 metrics to watch. Built-in review schedule. ### 10.7g — After Buying: 30-Day Check-In Auto-reminder after 30 days showing: - How metrics moved vs prediction - Thesis status (working / shaken / broken) - Next action ### 10.7h — Newbie Mode vs Pro Mode (Toggle) **Newbie Mode:** Simplified screener, plain language, auto position sizing, status lights, guided workflows **Pro Mode:** Full filter control, all metrics, raw data, advanced analysis, complete transparency --- ## Phase 10.8 — Earnings Calendar: Context, Not Destination **Goal:** Integrate earnings data contextually, NOT as standalone tab. ### 10.8a — Earnings in Screener Tearsheet (Primary) ``` UPCOMING EVENTS: ├── Earnings: July 30, 2026 (18 days away) │ ├── EPS estimate: $6.50 │ ├── Historical beat rate: 65% │ ├── Avg price move on earnings: +3% (beat), -2% (miss) │ └── Timing decision: "Buy now before earnings?" or "Wait?" │ ├── Ex-dividend: June 15 (6 days away) │ └── Dividend: $0.24/share │ └── Analyst call: Post-earnings July 30 ``` ### 10.8b — Earnings in Portfolio (Secondary) Portfolio holdings view shows upcoming events for YOUR positions with thesis-specific tracking. ### 10.8c — Earnings Discovery Widget (Optional, Tertiary) Light calendar feature in screener header (NOT main nav): ``` 📅 25 earnings this week in your screened results └── [View by day] [View by verdict] ``` ### 10.8d — What NOT to Build ❌ **Standalone "Calendar" nav tab** — creates bloat, out-of-context data, redundant. ### 10.8e — Earnings in Thesis Journal Earnings become key tracking metric when user logs thesis. ### 10.8f — Design Note: Revisit Earnings Display Format **⚠️ DESIGN REVIEW NEEDED:** Consider consistency across three locations, visual hierarchy differences, and mobile responsiveness before finalizing visual design. --- ## Phase 10.9 — Strong Buys: Professional Dip Opportunity Monitor **Goal:** Flag quality stocks when they drop 5%+ from 52W high, with market analysis of why. ### 10.9a — Data Structure | Field | Source | Purpose | |-------|--------|---------| | Ticker | Yahoo Finance | Stock identifier | | Current Price | Yahoo Finance daily fetch | Entry price today | | 52W High | Yahoo Finance | Reference for dip % | | Dip % | Calculated | Triggers display if ≥5% | | Screener Verdict | ScreenerEngine | Quality ranking | | Dip Reason | Market Analysis | Macro vs company issue | | Market Context | Daily fetched | Why dropped? Temporary? | | Your Play | LLM analysis | Buy dip or wait? | | Recommended Action | Position sizing | "Add 2-4% to portfolio" | ### 10.9b — Fetching Mechanism (Daily) 1. Get "Too Big to Fail" universe (~150 stocks: mega-cap + large-cap + watchlist) 2. Fetch prices + 52W high (one Yahoo batch call) 3. Filter dips ≥5% from 52W high 4. Run screener on dipped stocks 5. Analyze why dipped (macro vs company) 6. Combine + cache (TTL 24 hours) 7. API serves from cache ### 10.9c — UI: Tabular Display of Dip Opportunities | Ticker | Price | Dip % | Verdict | Why It Dipped | Your Play | Action | |--------|-------|-------|---------|---------------|-----------|--------| | AAPL | $189.50 | -9.76% | Strong Buy (8.2) | Fed rates high (macro, not company) | Buy dip. iPhone intact. | [+2-4%] | | JPM | $215.30 | -7.2% | Strong Buy (7.8) | Sector rotation (capital away) | Defensive play. Undervalued. | [+3%] | - Sortable by: Dip %, Verdict, Your Play - Click row → full tearsheet - Daily refresh - Threshold configurable: 5% (default) → 10% → 15% ### 10.9d — Configuration (User Control) ``` Settings > Strong Buys Monitor: Stock Universe: ☑ Mega-cap (10) ☑ Large-cap (50) ☑ My Watchlist (custom) Dip Threshold: ○ 5% (Aggressive) ○ 10% (Balanced) ○ 15% (Conservative) Update Frequency: ○ Daily morning (9:30 AM) ● Daily EOD (4:00 PM) ``` ### 10.9e — Design Note: Revisit Tabular Format **⚠️ DESIGN REVIEW NEEDED:** Consider: 1. **Card-based alternative** (cleaner, easier scan) vs current **compact table** 2. **Hybrid approach** (desktop table + mobile cards) Recommendation: Implement Phase 10.9a, gather user feedback, adjust design. --- ## Phase 10.5j — Comprehensive Free Data Stack (Zero Cost, Zero Redundancy) **Philosophy:** Professional-grade screener using only FREE sources. No $99-$200/mo subscriptions. Each source has ONE clear job (no duplication). ### Data Sources | Source | Cost | Job | Why | |--------|------|-----|-----| | Yahoo Finance (YahooFinanceClient) | $0 | Core metrics (P/E, ROE, FCF, D/E, analyst ratings) | Already integrated. No alternatives needed. | | yfinance | $0 | Per-ticker enrichment (news, earnings dates, dividends) | Wraps Yahoo, optimized for news extraction. | | Finnhub FREE | $0 | Earnings calendar + estimates only | Reliable future events (3-month lookahead). | | Alpha Vantage FREE | $0 | Market context + sentiment (macro-focused) | Sector trends, Fed decisions, keyword search. | | API Ninjas FREE | $0 | Earnings backup only (redundancy layer) | Fallback if Finnhub hits rate limits. | | Your LLM (Claude) | ~$50/mo | Intelligence layer (turns data into insights) | Sentiment analysis, decision framework, thesis validation. | **Total:** ~$50/mo (just LLM), vs $300-400/mo for Bloomberg/FactSet. ### Data Flow in Tearsheet 1. User screens stocks → ScreenerEngine uses YahooFinanceClient 2. Metrics cached in memory/state (no extra calls) 3. User clicks row → Tearsheet opens 4. Fetch per-ticker enrichment on-demand (yfinance, Finnhub, Alpha Vantage — parallel) 5. Process with LLM (if enabled) for sentiment + decision framework 6. Display complete tearsheet ### Integration Timeline - **Week 1:** Add yfinance news enrichment - **Week 2:** Add Finnhub earnings calendar - **Week 3:** Add Alpha Vantage market context - **Week 4:** Add API Ninjas as backup - **Week 5:** Wire everything into tearsheet - **Week 6:** Add LLM enrichment (optional) ### Why This Approach ✅ **Zero Cost:** $0/month (all sources FREE) ✅ **Zero Redundancy:** Each source has ONE job, no overlap ✅ **Professional Grade:** Layered sources like institutional traders use ✅ **Reliability:** Redundancy where it matters (earnings calendar via Finnhub + API Ninjas backup) ✅ **Intelligent:** Your LLM adds 10x value without additional data cost ### Rate Limits & Sustainability - Yahoo Finance: No official limits (proven in production) - yfinance: No limits (wraps Yahoo) - Finnhub FREE: 60 calls/minute (sufficient for 250 stocks) - Alpha Vantage FREE: 5 calls/minute (one daily call, easily manageable) - API Ninjas: 100 calls/month (backup only, minimal usage) --- ## Phase 11 — Day Trading: Authentication & Authorization **Goal:** Add multi-user support with JWT auth, role-based access control, and portfolio isolation. **Timeline:** 2-3 weeks. ### Why Auth is First Can't test multi-user portfolios, public + private access, Discord notifications with user context, or trade journal attribution without auth. ### 11a — Create auth domain ``` server/domains/auth/ ├── AuthController.ts ├── AuthService.ts ├── JWTStrategy.ts ├── RBACGuard.ts ├── persistence/ │ └── UserStore.ts └── types/ └── auth.model.ts ``` ### 11b — Database schema changes ```sql CREATE TABLE users ( id TEXT PRIMARY KEY, email TEXT UNIQUE NOT NULL, password_hash TEXT NOT NULL, role TEXT DEFAULT 'viewer' CHECK (role IN ('trader', 'viewer', 'admin')), created_at DATETIME DEFAULT CURRENT_TIMESTAMP, last_login DATETIME ); ALTER TABLE holdings ADD COLUMN user_id TEXT NOT NULL REFERENCES users(id); ALTER TABLE market_calls ADD COLUMN created_by TEXT REFERENCES users(id); ``` ### 11c — Middleware + route protection Apply RBACGuard to protected routes. JWT secret from env var. ### 11d — UI auth layer Add `routes/auth/login/` and `routes/auth/register/`. Create `lib/stores/auth.store.svelte.ts` for currentUser, JWT, login/logout. --- ## Phase 12 — Day Trading: News Webhooks **Goal:** Ingest real-time market news via Polygon.io webhooks. **Timeline:** 2-3 weeks. ### Why Webhooks Come Second News feeds everything downstream: Safe Buys monitor, LLM analysis, price dips. ### 12a — Create news domain ``` server/domains/news/ ├── NewsController.ts ├── WebhookHandler.ts ├── NewsStore.ts ├── NewsQueue.ts (BullMQ worker) ├── persistence/ │ └── NewsArticleStore.ts └── types/ └── news.model.ts ``` ### 12b — Database schema ```sql CREATE TABLE news_articles ( id TEXT PRIMARY KEY, ticker TEXT NOT NULL, headline TEXT NOT NULL, body TEXT, source TEXT, url TEXT, sentiment TEXT, published_at DATETIME, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX idx_news_ticker_date ON news_articles(ticker, published_at DESC); ``` ### 12c — Set up Polygon.io webhook 1. Subscribe to Polygon news API (~$200/mo) 2. Register webhook: `https://yourapp.com/webhooks/news` 3. Validate signature (Polygon sends HMAC) 4. Queue article for async processing ### 12d — Async processing with BullMQ Queue processes articles: 1. Store in DB 2. Trigger LLM analysis if key tickers mentioned 3. Notify subscribers (Discord, etc) --- ## Phase 13 — Day Trading: Prompt Caching & LLM Optimization **Goal:** Reduce LLM costs by 90% using Anthropic prompt caching. **Timeline:** 2-3 weeks. ### 13a — Create llm domain ``` server/domains/llm/ ├── LLMRouter.ts ├── PromptCache.ts ├── LLMAnalyst.ts (refactored) ├── persistence/ │ ├── AnalysisStore.ts │ └── CacheStore.ts └── types/ └── llm.model.ts ``` ### 13b — Database schema ```sql CREATE TABLE llm_analysis ( id TEXT PRIMARY KEY, ticker TEXT NOT NULL, analysis_result TEXT NOT NULL, model_used TEXT DEFAULT 'claude-opus', tokens_used INTEGER, cache_hit BOOLEAN DEFAULT false, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); ``` ### 13c — Implement Anthropic prompt caching Add `cache_control: { type: 'ephemeral' }` to system prompt message block. Use `anthropic-beta: prompt-caching-2024-07-31` header. ### 13d — LLM Router for cost optimization Route to cheaper models (Sonnet) when cost-sensitive. Fallback to OpenAI if rate-limited. --- ## Phase 14 — Day Trading: Safe Buys Monitor with Discord Alerts **Goal:** Monitor safe-buy stocks in real-time, detect 5%+ dips, notify via Discord. **Timeline:** 3-4 weeks. ### 14a — Create trading domain ``` server/domains/trading/ ├── TradingController.ts ├── DipDetector.ts ├── PriceMonitor.ts ├── DiscordNotifier.ts ├── persistence/ │ ├── PriceSnapshotStore.ts │ └── TradeSignalStore.ts └── types/ └── trading.model.ts ``` ### 14b — Database schema ```sql CREATE TABLE price_snapshots ( id TEXT PRIMARY KEY, ticker TEXT NOT NULL, price REAL NOT NULL, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, source TEXT, dip_detected BOOLEAN DEFAULT false ); CREATE TABLE trading_signals ( id TEXT PRIMARY KEY, ticker TEXT NOT NULL, signal_type TEXT CHECK (signal_type IN ('strong_buy', 'dip', 'warning')), entry_price REAL, detected_at DATETIME DEFAULT CURRENT_TIMESTAMP, notified BOOLEAN DEFAULT false, outcome TEXT ); ``` ### 14c — Real-time price polling Check watched tickers every 5 seconds. Filter dips ≥5%. Process via DipDetector. ### 14d — Discord notifications Send rich embeds with: - 🔴 5% Dip Detected: TICKER - Price fell from $X to $Y (-%Z) - LLM sentiment + recommendation - Risks --- ## Phase 15 — Day Trading: Trade Journal & Performance Tracking **Goal:** Log every decision, track outcomes, measure strategy performance. **Timeline:** 1-2 weeks. ### 15a — Database schema ```sql CREATE TABLE trade_journal ( id TEXT PRIMARY KEY, user_id TEXT NOT NULL REFERENCES users(id), ticker TEXT NOT NULL, signal TEXT, entry_price REAL NOT NULL, entry_date DATETIME DEFAULT CURRENT_TIMESTAMP, exit_price REAL, exit_date DATETIME, outcome TEXT CHECK (outcome IN ('win', 'loss', 'pending')), pnl REAL, reason TEXT, notes TEXT ); CREATE INDEX idx_journal_user ON trade_journal(user_id, entry_date DESC); ``` ### 15b — Trade stats dashboard Compute daily aggregates: - Total trades, wins, losses - Win rate, total P&L - Average win/loss, best/worst signal ### 15c — UI: Trade Stats Dashboard Display stats + trade history with filtering. --- ## Phase 16 — Multi-LLM Support (Optional) **Goal:** Support Claude, OpenAI, optionally Llama for cost optimization. **Timeline:** 2-3 weeks (do after Phase 14). ### Minimal implementation ```typescript const MODELS = { 'claude-opus': { cost: 0.015, speed: 'slow', quality: 'best' }, 'claude-sonnet': { cost: 0.003, speed: 'fast', quality: 'good' }, 'gpt-4': { cost: 0.03, speed: 'medium', quality: 'excellent' }, }; async analyze(ticker: string, preferredModel?: string) { const model = preferredModel || 'claude-sonnet'; return await routers[model].analyze(ticker); } ``` --- ## Production Readiness Checklist **Before going live:** - [ ] Environment variables locked down (.env.production, no secrets in code) - [ ] Database: Migrate SQLite → Postgres if expect >10 concurrent users - [ ] Job Queue: Set up BullMQ with Redis - [ ] Logging: Add structured logging (Winston, Pino) to track LLM calls + costs - [ ] Rate Limiting: Enabled on all public endpoints (@fastify/rate-limit) - [ ] Discord Webhook: Test alerts with real market data - [ ] Auth: JWT secret rotated, session timeout 1h - [ ] SSL/TLS: HTTPS enforced - [ ] Monitoring: Alerts for job backlog, API latency, cache hit rate, webhook failures - [ ] Alpaca price feed staleness: Should be <5s **Cost estimation (steady state):** | Service | Cost | Notes | |---------|------|-------| | Polygon.io (real-time news + quotes) | $200 | Required for webhooks | | Anthropic Claude API (w/ prompt caching) | $50–100 | Most cached; 90% cost reduction | | OpenAI API (fallback, optional) | $50 | Only if GPT-4 fallback added | | Alpaca/Interactive Brokers | $30–100 | Depends on which feed | | BullMQ (Redis queue, if scaled) | $0–30 | Free if self-hosted | | **Total** | **~$330–450/month** | Scales well (no per-user seat cost) | --- ## Final Architecture Summary | Layer | Tech | Status | |-------|------|--------| | **Auth** | JWT + RBAC | Phase 11 (weeks 1-2) | | **Data** | SQLite → Postgres if 1000+ users | Phase 11 | | **News** | Polygon.io webhooks | Phase 12 (weeks 3-4) | | **LLM** | Anthropic + OpenAI w/ prompt caching | Phase 13-14 (weeks 5-6) | | **Trading** | Real-time price monitoring + Discord | Phase 14 (weeks 7-10) | | **Tracking** | Trade journal + stats | Phase 15 (weeks 11-12) | | **UI** | Svelte 5 + Phase 10 structure | Phase 10 (weeks 1-5 parallel) | **Total time to "trading ready":** 12-16 weeks solo, 8 weeks with 1-2 junior devs. **Go-live target:** Q3 2026 (July–September). --- ## Postgres Migration Path (When Needed) If you grow to 10+ active traders: 1. Create Postgres RDS instance (AWS: ~$15/mo, db.t3.micro) 2. Update connection string to point to Postgres 3. Run schema dump SQLite → Postgres 4. Test on staging first 5. Blue-green deploy: run both DBs in parallel for 1 day, switch, keep SQLite as backup **Time:** 2–4 hours. No code changes needed. --- ## Frequently Asked Questions **Q: How many traders can this system handle?** A: - **10–50 traders:** Single instance. Costs ~$450/mo. - **50–500 traders:** Add Postgres + Redis queue. Costs ~$1000/mo. - **500+ traders:** Add Kubernetes + load balancing. Costs ~$5000+/mo. **Q: What if Polygon.io goes down?** A: Have fallback plan: 1. Switch to Finnhub webhooks (similar API, different provider) 2. Or fall back to polling (5s instead of real-time, less expensive) 3. Add circuit breaker: if Polygon fails for >5 min, automatically switch **Q: Can I trade with real money?** A: Yes, but: 1. Start with **paper trading** (Alpaca's paper account, no real money) 2. Test for 2+ weeks on real market conditions 3. Once you hit 55%+ win rate on paper, go live with small position sizes 4. Scale up gradually (1% → 5% → 10%) 5. Always have manual kill-switch **Q: Should I use local LLM training?** A: Not yet. Only consider if: - You have 6+ months of clean trade data - Your LLM bill is >$1000/mo - You have $20K+ to spend on GPU infrastructure For now, optimize prompts instead. Good prompt beats fine-tuned model. --- ## Future Enhancements (Unscheduled) ### FE-1 — Pinned Stocks Watchlist **Concept:** User can pin any stock from the screener table. Pinned stocks appear in a persistent sidebar or dedicated panel showing: - Minimal summary: ticker, current price, signal badge, score - Price-since-pin sparkline — a small inline chart showing how price moved from the day the stock was pinned to today - Quick unpin button **Data requirements:** - Store `{ ticker, pinnedAt, pinnedPrice }` in SQLite (`pinned_stocks` table) - Fetch daily OHLC history from Yahoo Finance for the period `pinnedAt → now` to power the sparkline - API: `GET /api/pins` (list), `POST /api/pins` (add), `DELETE /api/pins/:ticker` (remove), `GET /api/pins/:ticker/history` (OHLC since pin) **UI notes:** - Pin button (📌) appears on hover of each summary row in the screener table - Pinned panel can live in a collapsible drawer at the bottom, or a fixed right sidebar - Sparkline: use a lightweight SVG path (no charting library needed); green if price above pin price, red if below - On click of the sparkline, open a larger chart modal (Phase FE-1b — can use TradingView widget or Chart.js) **Why deferred:** Requires persistent per-user state (needs Phase 11 auth to be meaningful across sessions). Build after Phase 11. --- ### FE-2 — Column Header Tooltips ("Why does this matter?") **Concept:** Clicking a column header in the screener summary row opens a small popover explaining: - What the metric measures - What a good vs bad value looks like - How the screener uses it in scoring This turns the table into a learning tool — users understand *why* P/E or ROE matters, not just what the number is. **Suggested content per column:** | Header | What to explain | |--------|----------------| | **Score** | Weighted sum of all factor scores. >6 = quality, <4 = weak. Gates must pass first — score only fires if gates are cleared. | | **Signal** | Compares two scoring lenses (Mkt-Adjusted vs Graham). Strong Buy = passes both. Momentum = passes inflated only. | | **P/E** | Price-to-earnings. Lower = cheaper relative to earnings. Gate: <15x (Graham) or 30x warrants scrutiny unless high growth. | | **PEG** | P/E ÷ growth rate. Normalises valuation for growth. <1.0 = paying less than growth justifies. Lynch's standard. | | **ROE%** | Return on equity — how efficiently the company uses shareholder money. >15% is healthy; >30% is exceptional. Weighted 3× in scoring. | | **OpMgn%** | Operating margin — profit per dollar of revenue before interest and tax. Measures business efficiency. | | **FCF%** | Free cash flow yield — cash the business actually generates relative to price. Negative = cash-burning; gate fails. | | **D/E** | Debt-to-equity. Measures leverage. Gate: <1.5× (general), <2.0× (tech). Higher than 2× raises distress risk. | | **52W Chg** | Total price return over last 52 weeks. Positive momentum is healthy; >+50% may signal overextension. | | **From High** | % below the 52-week high. -5% to -15% is a typical dip zone; ≤-30% triggers a risk flag. | | **Analyst** | Yahoo consensus (1=Strong Buy, 5=Strong Sell). Requires ≥3 analysts to fire. ≤2.0 adds points; >4.0 subtracts. | | **DCF Safety** | Margin of safety from a two-stage DCF model. Positive = stock appears undervalued vs intrinsic value. Only fires when FCF > 0. | | **Cap** | Market cap tier: Mega (>$200B), Large ($10B+), Mid ($2B+), Small ($300M+), Micro (<$300M). Smaller = higher risk + volatility. | | **Style** | Growth classification from revenue + earnings growth rate. High Growth = ≥15% revenue growth. Value = low growth + ≥3% yield. | **Implementation approach:** - Add `data-tip` attribute to each `` in `AssetTable.svelte` - On click, show a positioned `
` anchored to the header - Dismiss on outside click or Escape - No library needed — pure Svelte `$state` + CSS positioning - Mobile: tip opens as a bottom sheet modal **Why not `title` attribute?** `title` tooltips are unstyled, non-interactive, and don't work on touch. A custom popover lets you format the content properly and include a "Good range" callout. **Why deferred:** Nice-to-have educational feature. Build after the core screener UI (Phase 10.5) is stable.