From 1482422f2f5b236cdcdff4429ae06bb55dca4083 Mon Sep 17 00:00:00 2001 From: Tyler Hoang Date: Sun, 17 May 2026 12:46:13 -0700 Subject: Add stack start and stop scripts --- CLAUDE.md | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 CLAUDE.md (limited to 'CLAUDE.md') diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..9e7c256 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,74 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## What This Is + +Prism v2 is a financial overview app: FastAPI backend (Python) + Next.js frontend (TypeScript). The backend pulls market data from yfinance with TTL caching and stores a watchlist in SQLite. The frontend renders a single Overview page with ticker search, price chart (Plotly), market bar, and watchlist. + +## Commands + +**Backend — run from repo root or `backend/`:** +```bash +# Start API (ports 8001 to avoid conflicts) +backend/.venv/bin/uvicorn app.main:app --reload --host 127.0.0.1 --port 8001 + +# Run all tests (pytest.ini sets pythonpath=backend) +pytest + +# Run a single test file +pytest backend/tests/test_api.py + +# Compile-check without running +backend/.venv/bin/python -m py_compile backend/app/main.py backend/app/schemas.py +``` + +**Frontend — run from `frontend/`:** +```bash +NEXT_PUBLIC_API_BASE_URL=http://127.0.0.1:8001 npm run dev -- --hostname 127.0.0.1 --port 3001 +npm run lint # ESLint +npm run build # Production build (validates TypeScript + Next.js) +``` + +## Architecture + +### Backend data flow +`main.py` routes → `services/data_service.py` → yfinance (primary source). +`data_service.py` has three data-fetching helpers that `get_ticker_overview()` calls in priority order: `get_company_info()` (full yfinance `.info`), `get_fast_info()` (lightweight), then search + price history as last resort. `OverviewMeta.sources` records which source each field came from. + +### Key backend files +- `app/main.py` — FastAPI routes, CORS config, lifespan (DB init) +- `app/schemas.py` — all Pydantic response models +- `app/services/data_service.py` — yfinance wrapper, TTL cache (`HISTORY_CACHE`), signal/stat computation +- `app/db/watchlist.py` — SQLite CRUD; watchlist capped at 10 symbols, normalized to uppercase + +### Frontend data flow +`app/page.tsx` (Overview shell) → `lib/api.ts` (typed fetch client) → backend. +Selected ticker lives in the URL query param `?ticker=SYMBOL`. Types are shared in `frontend/types/api.ts` — keep these in sync with `backend/app/schemas.py`. + +### Testing approach +Backend tests use `monkeypatch` to stub `data_service` functions — never make live yfinance calls in tests. Use a `tmp_path` fixture for any test that touches SQLite. There is no frontend test runner; use `npm run lint` and `npm run build` for frontend validation. + +## Reference: Prism v1 (`../prism`) + +The old Streamlit-based app at `../prism` is the canonical reference for finance logic being ported into v2. Do not import from it at runtime, but read it when implementing new financial features. + +Key source files to consult: + +- **`services/data_service.py`** — yfinance wrappers for price history, financials (income/balance/cash flow), options chain, insider transactions, SEC filings, market indices, and analyst targets. Contains `compute_ttm_ratios()` which self-computes P/E, P/B, P/S, EV/EBITDA, margins, ROE/ROA/ROIC, leverage ratios, and dividend metrics from raw quarterly statements (avoiding FMP quota). Includes outlier safeguards (e.g. P/B and EV/Sales capped at 100). +- **`services/valuation_service.py`** — DCF engine (`run_dcf()`) using Gordon Growth Model: projects FCF with median historical growth (capped ±50%, skips sign flips), computes terminal value, bridges enterprise value to equity per share via net debt/preferred equity/minority interest. Also has `run_ev_ebitda()`, `run_ev_revenue()`, `run_price_to_book()`. +- **`services/fmp_service.py`** — FMP REST calls for peers, forward analyst estimates, historical ratios, and news. Falls back to yfinance when FMP is unavailable. +- **`services/news_service.py`** — Finnhub sentiment wrapper. +- **`components/overview.py`** — signal badge logic (6 signals), 52-week range bar, short interest rendering. +- **`utils/formatters.py`** — number formatting helpers (market cap abbreviations, percent display, etc.). + +**Caching strategy in v1:** `@st.cache_data` with staggered TTLs — financials at 1 h, indices at 5 min, search at 60 s. Mirror these TTLs when adding new cached endpoints in v2's `data_service.py`. + +**Data source hierarchy in v1:** yfinance primary → FMP fallback → Finnhub for news/sentiment. FMP free tier is 250 req/day; `FMP_API_KEY` and `FINNHUB_API_KEY` are set via `.env`. + +## Environment Variables + +Copy `.env.example` → `.env`. The current feature set works without API keys; yfinance is the active data source. + +- `NEXT_PUBLIC_API_BASE_URL` — frontend points to backend (default `http://localhost:8000`) +- `FMP_API_KEY`, `FINNHUB_API_KEY` — reserved for future enrichment endpoints (see v1 `fmp_service.py` / `news_service.py`) -- cgit v1.3-2-g0d8e