Initial commit: OpenSpec setup and stock-deep-evaluation change
Set up OpenSpec spec-driven workflow and fully specify the first change, stock-deep-evaluation: a Next.js/TS app for thorough single-stock evaluation (valuation reasoning, macro factors, entry/exit points, stop-loss) with a pluggable data layer and Claude analysis agent. Includes proposal, design, specs (market-data, equity-evaluation, analysis-agent, evaluation-app), tasks, and the DE gold-standard example. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Provider-agnostic analysis-agent interface
|
||||
|
||||
The system SHALL define an `AnalysisAgent` interface that accepts a structured
|
||||
evaluation object and returns a written analysis. Consumers MUST depend only on
|
||||
this interface so the underlying model provider can change without affecting the
|
||||
evaluation engine or UI.
|
||||
|
||||
#### Scenario: Agent invoked through the interface
|
||||
- **WHEN** an evaluation object is passed to the configured analysis agent
|
||||
- **THEN** the agent returns a written analysis produced through the interface
|
||||
|
||||
#### Scenario: Alternate implementation can be registered
|
||||
- **WHEN** a different agent implementation is configured
|
||||
- **THEN** the system uses it without changes to evaluation or UI code
|
||||
|
||||
### Requirement: Claude default implementation via Anthropic SDK
|
||||
|
||||
The system SHALL ship a default `AnalysisAgent` backed by Claude through the
|
||||
`@anthropic-ai/sdk`, targeting a current Claude model. The API key SHALL be
|
||||
supplied by the user (bring-your-own-key) via configuration and never hard-coded
|
||||
or committed.
|
||||
|
||||
#### Scenario: Claude produces the written thesis
|
||||
- **WHEN** a valid Anthropic API key is configured and an evaluation is submitted
|
||||
- **THEN** the default agent calls Claude and returns the written thesis
|
||||
|
||||
#### Scenario: Key sourced from configuration
|
||||
- **WHEN** the app reads its configuration
|
||||
- **THEN** the Anthropic API key is loaded from environment/config, not source code
|
||||
|
||||
### Requirement: Grounded, structured written analysis
|
||||
|
||||
The agent SHALL base its narrative only on the supplied evaluation data and
|
||||
SHALL NOT invent figures. It SHALL produce the narrative sections reflected in the
|
||||
example evaluation: current standing, earnings recap and quality-of-earnings
|
||||
caveats, valuation with explicit over/undervalued reasoning, macro factors, timing,
|
||||
entry/exit/stop-loss rationale, bull-versus-bear, and an actionable plan. When a
|
||||
data caveat or discrepancy is present in the input, the agent SHALL preserve it.
|
||||
|
||||
#### Scenario: Narrative grounded in provided data
|
||||
- **WHEN** the agent writes the analysis
|
||||
- **THEN** every figure it cites is present in the supplied evaluation object
|
||||
|
||||
#### Scenario: Data caveats preserved
|
||||
- **WHEN** the evaluation object flags a discrepancy or one-time item
|
||||
- **THEN** the written analysis surfaces that caveat rather than omitting it
|
||||
|
||||
#### Scenario: Disclaimer preserved in narrative
|
||||
- **WHEN** the agent returns its analysis
|
||||
- **THEN** the analysis-not-advice disclaimer is present
|
||||
|
||||
### Requirement: Graceful degradation without an API key
|
||||
|
||||
When no analysis-agent key is configured, the system SHALL still return the full
|
||||
structured evaluation and SHALL clearly indicate that the written narrative is
|
||||
unavailable until a key is provided.
|
||||
|
||||
#### Scenario: No key configured
|
||||
- **WHEN** an evaluation is requested and no agent API key is configured
|
||||
- **THEN** the structured evaluation is returned
|
||||
- **AND** the response indicates the written analysis is unavailable pending a key
|
||||
|
||||
### Requirement: Agent error handling
|
||||
|
||||
The system SHALL handle agent failures (auth errors, rate limits, timeouts) by
|
||||
returning a typed error and the underlying structured evaluation, without losing
|
||||
the data already computed.
|
||||
|
||||
#### Scenario: Agent call fails
|
||||
- **WHEN** the agent call errors after retries
|
||||
- **THEN** the system returns the structured evaluation plus a typed agent error
|
||||
- **AND** the computed data is not discarded
|
||||
@@ -0,0 +1,189 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Current standing summary
|
||||
|
||||
The system SHALL produce a current-standing summary for the ticker containing:
|
||||
last price, absolute and percent change on the day, today's volume as a multiple
|
||||
of average, percent distance from the 52-week high and low, market capitalization,
|
||||
and trailing P/E.
|
||||
|
||||
#### Scenario: Standing summary is produced
|
||||
- **WHEN** an evaluation is run for a resolved ticker with price and fundamentals
|
||||
- **THEN** the output includes price, day change (abs and %), volume multiple,
|
||||
distance from 52-week high and low, market cap, and trailing P/E
|
||||
|
||||
### Requirement: Earnings recap when a recent report exists
|
||||
|
||||
The system SHALL, when the most recent quarterly report falls within a
|
||||
configurable recency window, produce an earnings recap comparing reported EPS to consensus
|
||||
(beat/miss and magnitude), net income and its year-over-year change, and any
|
||||
changes to management guidance.
|
||||
|
||||
#### Scenario: Recent earnings summarized
|
||||
- **WHEN** the latest earnings report falls within the recency window
|
||||
- **THEN** the output includes EPS actual vs consensus, the beat/miss magnitude,
|
||||
net income with YoY change, and guidance changes when available
|
||||
|
||||
#### Scenario: No recent earnings
|
||||
- **WHEN** no report falls within the recency window
|
||||
- **THEN** the earnings recap is omitted and the evaluation proceeds
|
||||
|
||||
### Requirement: Quality-of-earnings caveats
|
||||
|
||||
The system SHALL surface quality-of-earnings caveats when the data supports them,
|
||||
including one-time items (e.g. tax or tariff refunds), price-driven versus
|
||||
volume-driven revenue changes, and headline metrics that compare against the
|
||||
wrong baseline (e.g. an equipment-sales figure presented as total revenue).
|
||||
|
||||
#### Scenario: One-time item flagged
|
||||
- **WHEN** a reported result includes a disclosed one-time benefit or charge
|
||||
- **THEN** the evaluation notes the item and its approximate EPS impact when known
|
||||
|
||||
#### Scenario: Price-vs-volume distinction made
|
||||
- **WHEN** segment or company data separates price realization from volume change
|
||||
- **THEN** the evaluation states how much of a revenue or profit move came from
|
||||
price versus units
|
||||
|
||||
### Requirement: Financial and segment breakdown
|
||||
|
||||
The system SHALL present a financial summary comparing the current period to the
|
||||
prior-year period (revenue, operating profit, margins, diluted EPS, operating
|
||||
and free cash flow) and, where segment data exists, a per-segment breakdown of
|
||||
revenue, year-over-year change, operating profit, and operating margin versus the
|
||||
prior-year margin.
|
||||
|
||||
#### Scenario: Current-vs-prior financials presented
|
||||
- **WHEN** current and prior-year period data are available
|
||||
- **THEN** the output includes a side-by-side comparison of the listed metrics
|
||||
|
||||
#### Scenario: Segment breakdown presented when available
|
||||
- **WHEN** the provider supplies segment data
|
||||
- **THEN** the output includes per-segment revenue, YoY, operating profit, and
|
||||
margin versus the prior-year margin
|
||||
|
||||
### Requirement: Valuation analysis with over/undervalued reasoning
|
||||
|
||||
The system SHALL compute a valuation view (TTM diluted EPS, trailing P/E, forward
|
||||
EPS and forward P/E from consensus, net-income and revenue growth, FCF yield,
|
||||
dividend yield) and compare current multiples against the company's own history.
|
||||
It SHALL state explicit, data-grounded reasons the company appears overvalued or
|
||||
undervalued, distinguishing multiple expansion from earnings growth and noting
|
||||
whether a high multiple sits on trough or peak earnings.
|
||||
|
||||
#### Scenario: Valuation metrics computed
|
||||
- **WHEN** fundamentals and consensus estimates are available
|
||||
- **THEN** the output includes trailing P/E, forward P/E, growth rates, FCF yield,
|
||||
and dividend yield, plus a comparison to prior fiscal-year multiples
|
||||
|
||||
#### Scenario: Explicit valuation reasoning produced
|
||||
- **WHEN** the valuation view is produced
|
||||
- **THEN** the output states specific reasons for the over/undervalued conclusion
|
||||
(e.g. "paying 29x a forecast recovery year before units confirm it")
|
||||
|
||||
#### Scenario: Conflicting estimate feeds are reconciled
|
||||
- **WHEN** two estimate sources disagree on a forward figure
|
||||
- **THEN** the evaluation discloses the discrepancy and states which figure it used
|
||||
|
||||
### Requirement: Macro and sector factor analysis
|
||||
|
||||
The system SHALL identify macro and sector factors affecting the stock, such as
|
||||
tariffs and their year-over-year trajectory, interest-rate sensitivity, commodity
|
||||
or input-cost pressure on customers, and read-throughs from peer companies.
|
||||
|
||||
#### Scenario: Macro factors surfaced
|
||||
- **WHEN** an evaluation is run
|
||||
- **THEN** the output lists the material macro/sector factors and their direction
|
||||
of impact on the stock
|
||||
|
||||
### Requirement: Timing and volatility context
|
||||
|
||||
The system SHALL provide timing context: how the stock has historically behaved
|
||||
after earnings prints, today's move versus the options-implied expected move,
|
||||
recent monthly trading ranges, and whether a post-earnings gap has been filled.
|
||||
|
||||
#### Scenario: Post-earnings behavior characterized
|
||||
- **WHEN** historical prices around prior earnings dates are available
|
||||
- **THEN** the output summarizes the typical post-earnings move and how the current
|
||||
move compares to the implied expectation
|
||||
|
||||
#### Scenario: Gap-fill status reported
|
||||
- **WHEN** the latest session gapped from the prior close
|
||||
- **THEN** the output states whether the gap was filled intraday
|
||||
|
||||
### Requirement: Entry points
|
||||
|
||||
The system SHALL produce a ranked set of candidate entry levels derived from
|
||||
technical structure (moving averages, swing lows, pre-earnings shelves), each
|
||||
annotated with what the level represents, its percent distance below the current
|
||||
price, and the valuation multiple implied at that price. It SHALL group nearby
|
||||
levels into practical entry bands.
|
||||
|
||||
#### Scenario: Entry levels table produced
|
||||
- **WHEN** technical context and valuation are available
|
||||
- **THEN** the output includes candidate entry levels with their meaning, distance
|
||||
below current price, and implied multiple at that price
|
||||
|
||||
#### Scenario: Entry bands recommended
|
||||
- **WHEN** multiple levels cluster within a narrow range
|
||||
- **THEN** the output groups them into a band and identifies a starter versus a
|
||||
high-conviction tranche
|
||||
|
||||
### Requirement: Exit points and price targets
|
||||
|
||||
The system SHALL produce candidate exit levels and price targets, incorporating
|
||||
analyst target average/median/range and technical resistance such as prior highs.
|
||||
|
||||
#### Scenario: Exit targets produced
|
||||
- **WHEN** analyst targets and price history are available
|
||||
- **THEN** the output includes exit/target levels with their basis and upside from
|
||||
the current price
|
||||
|
||||
### Requirement: Stop-loss levels
|
||||
|
||||
The system SHALL recommend stop-loss levels grounded in technical structure and
|
||||
realized volatility (e.g. below a key moving average or swing low, or a
|
||||
volatility-based distance), stated as concrete prices with rationale.
|
||||
|
||||
#### Scenario: Stop-loss recommended
|
||||
- **WHEN** an entry band is identified
|
||||
- **THEN** the output states a concrete stop-loss price for that entry and the
|
||||
technical/volatility basis for it
|
||||
|
||||
### Requirement: Bull-versus-bear synthesis and actionable plan
|
||||
|
||||
The system SHALL synthesize a bull case and a bear case as explicit lists, and
|
||||
produce an actionable plan: tranche sizing across entry bands, the next dated
|
||||
catalyst, conditional logic tying action to observable levels/dates, and the
|
||||
single most important metric to watch.
|
||||
|
||||
#### Scenario: Bull and bear cases produced
|
||||
- **WHEN** an evaluation is run
|
||||
- **THEN** the output includes distinct bull and bear point lists grounded in the data
|
||||
|
||||
#### Scenario: Actionable plan produced
|
||||
- **WHEN** entry, exit, and stop levels are available
|
||||
- **THEN** the output includes tranche guidance, the next dated catalyst, at least
|
||||
one conditional rule, and the key metric to monitor
|
||||
|
||||
### Requirement: Not-advice disclaimer
|
||||
|
||||
Every evaluation SHALL include a clear disclaimer that the output is analysis and
|
||||
not investment advice.
|
||||
|
||||
#### Scenario: Disclaimer present
|
||||
- **WHEN** any evaluation is produced
|
||||
- **THEN** the output includes an analysis-not-advice disclaimer
|
||||
|
||||
### Requirement: Structured evaluation object
|
||||
|
||||
The system SHALL emit the evaluation as a typed, structured object (not only prose)
|
||||
so the UI and the analysis agent can consume individual sections. Missing inputs
|
||||
SHALL be represented explicitly rather than fabricated.
|
||||
|
||||
#### Scenario: Structured object emitted
|
||||
- **WHEN** an evaluation completes
|
||||
- **THEN** a typed object containing each section is available to consumers
|
||||
|
||||
#### Scenario: Missing data is not fabricated
|
||||
- **WHEN** a required input for a section is unavailable
|
||||
- **THEN** that section marks the value unavailable rather than inventing one
|
||||
@@ -0,0 +1,85 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Ticker search entry point
|
||||
|
||||
The web app SHALL present a search input where a user enters an NYSE/Nasdaq ticker
|
||||
to request an evaluation. Invalid or unresolvable symbols SHALL produce an inline
|
||||
error without navigating away.
|
||||
|
||||
#### Scenario: User searches a valid ticker
|
||||
- **WHEN** a user enters a resolvable ticker and submits
|
||||
- **THEN** the app initiates an evaluation for that ticker
|
||||
|
||||
#### Scenario: User searches an invalid ticker
|
||||
- **WHEN** a user submits a symbol that does not resolve
|
||||
- **THEN** the app shows an inline not-found message and stays on the search view
|
||||
|
||||
### Requirement: Evaluation request orchestration
|
||||
|
||||
The app SHALL orchestrate the pipeline for a request: fetch market data, run the
|
||||
equity-evaluation engine, then invoke the analysis agent, returning both the
|
||||
structured evaluation and the written analysis to the client.
|
||||
|
||||
#### Scenario: Full pipeline succeeds
|
||||
- **WHEN** a valid ticker is evaluated with data and an agent key available
|
||||
- **THEN** the app returns the structured evaluation and the written analysis
|
||||
|
||||
#### Scenario: Partial pipeline (agent unavailable)
|
||||
- **WHEN** market data succeeds but the agent is unavailable
|
||||
- **THEN** the app returns the structured evaluation and indicates the narrative is
|
||||
pending
|
||||
|
||||
### Requirement: Evaluation report view
|
||||
|
||||
The app SHALL render the evaluation as a report with clearly delineated sections:
|
||||
current standing, earnings recap and quality-of-earnings caveats, financials and
|
||||
segments, valuation and over/undervalued reasoning, macro factors, timing, entry
|
||||
levels, exit/targets, stop-loss, bull-versus-bear, the actionable plan, and the
|
||||
disclaimer. Tabular data SHALL render as tables and unavailable values SHALL be
|
||||
shown as such rather than as zero.
|
||||
|
||||
#### Scenario: Report sections rendered
|
||||
- **WHEN** an evaluation result is available
|
||||
- **THEN** the report view displays each populated section in order
|
||||
|
||||
#### Scenario: Unavailable values shown honestly
|
||||
- **WHEN** a section contains an unavailable value
|
||||
- **THEN** the view displays it as unavailable rather than as a zero or blank number
|
||||
|
||||
### Requirement: Price chart with marked levels
|
||||
|
||||
The app SHALL render a price chart with the computed moving averages and overlay
|
||||
markers for the recommended entry bands, exit/target levels, and stop-loss levels
|
||||
so the user can see them against price history.
|
||||
|
||||
#### Scenario: Levels overlaid on chart
|
||||
- **WHEN** the report renders with computed levels
|
||||
- **THEN** the chart shows price history with entry, exit, and stop-loss markers
|
||||
|
||||
### Requirement: Loading and error states
|
||||
|
||||
The app SHALL show progress while an evaluation runs and SHALL present typed
|
||||
errors (data unavailable, rate-limited, agent failed) as user-readable messages
|
||||
without blank screens.
|
||||
|
||||
#### Scenario: Loading indicator during evaluation
|
||||
- **WHEN** an evaluation is in progress
|
||||
- **THEN** the app shows a loading state until results or an error return
|
||||
|
||||
#### Scenario: Error surfaced to user
|
||||
- **WHEN** the pipeline returns a typed error
|
||||
- **THEN** the app displays a readable message describing what failed
|
||||
|
||||
### Requirement: API key configuration in the app
|
||||
|
||||
The app SHALL provide a way to configure the market-data and Anthropic API keys
|
||||
via environment/config, SHALL NOT expose secret keys to the browser, and SHALL
|
||||
indicate when a required key is missing.
|
||||
|
||||
#### Scenario: Keys read server-side only
|
||||
- **WHEN** the app calls external providers
|
||||
- **THEN** secret keys are used only in server-side code and never sent to the client
|
||||
|
||||
#### Scenario: Missing key indicated
|
||||
- **WHEN** a required key is absent
|
||||
- **THEN** the app indicates which capability is unavailable until the key is set
|
||||
@@ -0,0 +1,99 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Provider-agnostic data interface
|
||||
|
||||
The system SHALL define a `DataProvider` interface that all market-data access
|
||||
goes through. Evaluation and UI code MUST depend only on this interface and its
|
||||
normalized data models, never on a concrete provider SDK or response shape. The
|
||||
active provider SHALL be selectable via configuration without code changes in
|
||||
consumers.
|
||||
|
||||
#### Scenario: Default free provider is used when none configured
|
||||
- **WHEN** the app starts with no market-data provider explicitly configured
|
||||
- **THEN** a default free-tier provider implementation is selected
|
||||
- **AND** all normalized data models are populated from that provider
|
||||
|
||||
#### Scenario: Provider can be swapped via configuration
|
||||
- **WHEN** an operator sets the provider configuration to a different implementation
|
||||
- **THEN** the system routes all data requests through the new provider
|
||||
- **AND** no changes to evaluation or UI code are required
|
||||
|
||||
### Requirement: Ticker resolution for NYSE and Nasdaq
|
||||
|
||||
The system SHALL accept a ticker symbol, validate that it resolves to an
|
||||
NYSE- or Nasdaq-listed equity, and return a normalized company profile
|
||||
(name, exchange, sector/industry, currency, shares outstanding).
|
||||
|
||||
#### Scenario: Valid listed ticker resolves
|
||||
- **WHEN** a user submits a ticker listed on NYSE or Nasdaq (e.g. `DE`)
|
||||
- **THEN** the system returns a company profile with name, exchange, and sector
|
||||
|
||||
#### Scenario: Unknown or unlisted ticker is rejected
|
||||
- **WHEN** a user submits a symbol that does not resolve to an NYSE/Nasdaq equity
|
||||
- **THEN** the system returns a not-found result with a clear message
|
||||
- **AND** no evaluation is attempted
|
||||
|
||||
### Requirement: Company fundamentals and financial statements
|
||||
|
||||
The system SHALL provide normalized fundamentals sufficient for valuation and
|
||||
earnings analysis: TTM and per-fiscal-year revenue, operating profit, margins,
|
||||
net income, diluted EPS, operating cash flow, free cash flow, dividend per share,
|
||||
and total/net debt. Where the provider exposes it, per-segment revenue and
|
||||
operating profit SHALL be included.
|
||||
|
||||
#### Scenario: Fundamentals returned for a resolved ticker
|
||||
- **WHEN** fundamentals are requested for a resolved ticker
|
||||
- **THEN** the system returns TTM and at least the last three fiscal years of the
|
||||
listed metrics
|
||||
- **AND** each metric carries the fiscal period it belongs to
|
||||
|
||||
#### Scenario: Missing metric is represented explicitly
|
||||
- **WHEN** the provider does not supply a given metric
|
||||
- **THEN** the normalized model marks that metric as unavailable rather than zero
|
||||
|
||||
### Requirement: Price history and computed technical indicators
|
||||
|
||||
The system SHALL provide daily OHLCV price history and compute technical context
|
||||
used for timing: 20/50/200-day moving averages, recent swing highs and lows,
|
||||
distance from 52-week high and low, average daily volume and today's volume as a
|
||||
multiple of it, and realized volatility (e.g. 60-day annualized).
|
||||
|
||||
#### Scenario: Technical context computed from price history
|
||||
- **WHEN** price history is requested for a resolved ticker
|
||||
- **THEN** the system returns the moving averages, 52-week high/low, volume ratio,
|
||||
and realized volatility computed from that history
|
||||
|
||||
#### Scenario: Insufficient history degrades gracefully
|
||||
- **WHEN** fewer than 200 trading days of history are available
|
||||
- **THEN** longer-window indicators (e.g. 200-day average) are marked unavailable
|
||||
- **AND** shorter-window indicators are still returned
|
||||
|
||||
### Requirement: Analyst coverage and consensus estimates
|
||||
|
||||
The system SHALL provide, where available, analyst rating counts (bullish /
|
||||
neutral / bearish), average and median price targets, target range, and forward
|
||||
consensus estimates (next fiscal-year EPS and revenue).
|
||||
|
||||
#### Scenario: Analyst data returned when available
|
||||
- **WHEN** analyst coverage exists for a ticker
|
||||
- **THEN** the system returns rating counts, average/median/target range, and
|
||||
forward EPS/revenue estimates
|
||||
|
||||
#### Scenario: No coverage is handled
|
||||
- **WHEN** no analyst coverage exists for a ticker
|
||||
- **THEN** the system returns an empty coverage result the evaluation can note
|
||||
|
||||
### Requirement: Rate limiting, caching, and data-freshness disclosure
|
||||
|
||||
The system SHALL respect provider rate limits, cache responses to reduce calls,
|
||||
and expose each dataset's freshness (as-of timestamp and whether it is delayed
|
||||
or real-time) so downstream output can disclose it.
|
||||
|
||||
#### Scenario: Rate-limit and transient errors are handled
|
||||
- **WHEN** the provider returns a rate-limit or transient error
|
||||
- **THEN** the system retries within limits and, if still failing, returns a typed
|
||||
error rather than throwing an unhandled exception
|
||||
|
||||
#### Scenario: Data freshness is surfaced
|
||||
- **WHEN** any dataset is returned
|
||||
- **THEN** it includes an as-of timestamp and a delayed/real-time flag
|
||||
Reference in New Issue
Block a user