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:
@@ -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.
|
||||
Reference in New Issue
Block a user