Build stock-deep-evaluation v1: single-stock equity evaluation app

Next.js 15 + TypeScript app implementing the fully-specced first change.
Pipeline: resolve -> market data -> pure evaluation engine -> budget guard
-> analysis agent -> report.

- market-data: DataProvider interface, offline FixtureProvider (DE/SPY seeded
  from the reference example), FmpProvider (FMP free tier), TTL cache + retry.
- technicals: pure MA/volatility/swing/52-week math.
- evaluation: instrument-aware pure engine; equity branch built, ETF gated to
  "not yet supported". Reproduces the DE example (P/E 34.5, fwd 29.3, $167.6B).
- agent: AnalysisAgent interface; default Claude Code CLI transport (headless,
  subscription-backed, web-grounded), Anthropic API alternate via config.
- cost-controls: price table, spend store, monthly budget guard.
- UI: ticker search + deep-dive toggle, report view, price chart with marked
  entry/exit/stop levels, cost/budget display, ETF/not-found states.

31 vitest tests, typecheck, production build, and lint all pass. Verified
end-to-end via the API for DE, SPY, and an unknown ticker. Live Claude CLI
agent test is the documented pick-up point (see README).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-21 17:03:04 -04:00
co-authored by Claude Opus 4.8
parent 73e93e7cb4
commit 902758ce67
44 changed files with 12425 additions and 91 deletions
+96
View File
@@ -0,0 +1,96 @@
# equitysearch
Thorough, agent-written evaluation of individual NYSE / Nasdaq equities:
valuation and over/undervalued reasoning, macro factors, entry/exit points, and
stop-loss levels — grounded in structured fundamentals plus live web search.
Built spec-first with [OpenSpec](https://github.com/Fission-AI/OpenSpec); the
change that produced v1 lives in `openspec/changes/stock-deep-evaluation/`.
## ▶ Pick up here next time — live agent test
v1 is fully built and verified except for **one thing left to do live**: exercise
the real Claude Code CLI agent writing the thesis with web grounding. Everything
else (data → evaluation → API → structured report → charts → cost/budget) is
tested and confirmed end-to-end; the analysis *narrative* has only been checked
with a stubbed agent.
**To resume:**
1. Ensure the `claude` CLI is authenticated (`claude` → log in).
2. `npm run dev`, open http://localhost:3000, search **DE**.
3. Confirm the written thesis renders (Thesis / Valuation / Macro / Timing /
Entry-exit-stop / Bull-vs-bear / Plan sections) and that **Sources** are cited.
4. Toggle **Deep dive** to run Fable 5 and compare depth.
5. If the narrative needs shaping, tune the prompt in
`src/lib/agent/agent.ts` (`systemInstructions` / `userPrompt`).
The OpenSpec change `stock-deep-evaluation` is complete but **not yet archived**
archive it (`openspec archive stock-deep-evaluation`) once the live test looks good.
## Quick start
```bash
npm install
cp .env.example .env.local # optional — the app runs with zero config
npm run dev # http://localhost:3000
```
Search a ticker (try **DE**). With no configuration the app uses an offline
fixture provider (DE + SPY) and the Claude Code CLI agent.
## How it works
```
ticker → resolve → market data → evaluation engine (pure) → budget guard → analysis agent → report
```
- **Market data** (`src/lib/market-data`) — a provider-agnostic `DataProvider`
interface. Default is an offline **fixture** (DE seeded from the reference
example); set `MARKET_DATA_PROVIDER=fmp` + `MARKET_DATA_API_KEY` for real
Financial Modeling Prep data.
- **Evaluation engine** (`src/lib/evaluation`) — a pure function that computes the
quantitative sections (standing, earnings recap, quality-of-earnings flags,
segments, valuation, entry/exit/stop levels, bull/bear, plan). Instrument-aware:
v1 runs the **equity** branch; ETFs resolve but return "not yet supported".
- **Analysis agent** (`src/lib/agent`) — turns the structured evaluation into the
written thesis, grounded with live web search.
- **Cost controls** (`src/lib/cost`) — captures per-report usage/cost and enforces
a monthly budget (soft warning, hard cap, deep-dive pre-emption).
## Configuration (`.env.local`)
| Var | Default | Purpose |
|---|---|---|
| `AGENT_TRANSPORT` | `claude-cli` | `claude-cli` (runs the local Claude Code CLI on your subscription — no API key, ~$0 marginal) or `api` (metered Anthropic API for serving external users) |
| `ANTHROPIC_API_KEY` | — | Only for `AGENT_TRANSPORT=api`. Server-side only |
| `MARKET_DATA_PROVIDER` | `fixture` | `fixture` (offline DE/SPY) or `fmp` |
| `MARKET_DATA_API_KEY` | — | FMP free-tier key |
| `MONTHLY_BUDGET_USD` | `0` | Monthly spend cap; `0` disables the guard |
**Agent transports.** The default runs `claude -p --output-format json --model
opus|fable --allowedTools "WebSearch WebFetch"` on your existing Claude auth, so an
internal tool incurs near-zero marginal cost and web grounding is built in. Deep
dive escalates the model to Fable 5. Requires the `claude` CLI installed and
authenticated. Switch to `api` if the app is ever served to external users
(subscription-backed serving is not appropriate then).
## Scripts
```bash
npm run dev # dev server
npm run build # production build
npm run start # run the production build
npm run typecheck # tsc --noEmit
npm test # vitest (31 tests)
```
## Not investment advice
Every report ends with a disclaimer. This is analysis, not investment advice.
## Roadmap (deferred changes, compose on v1)
- **ETF evaluation branch** — holdings, expense ratio, NAV premium/discount,
weighted fundamentals (the seams are already in place).
- **Screening / candidate-finder** — criteria → grounded ranked shortlist that
feeds this evaluator.