## 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 security, and return a normalized profile that includes an **instrument type** discriminant (`equity` or `etf`) plus name, exchange, currency, and — for equities — sector/industry and shares outstanding. v1 fully supports the `equity` type; ETF-specific data is a later change, but resolution SHALL still classify ETFs so an unsupported-type path is explicit rather than silently wrong. #### Scenario: Valid listed equity resolves - **WHEN** a user submits an equity ticker listed on NYSE or Nasdaq (e.g. `DE`) - **THEN** the system returns a profile with instrument type `equity`, name, exchange, and sector #### Scenario: ETF is classified, not misread as an equity - **WHEN** a user submits an ETF ticker (e.g. `SPY`) - **THEN** the system returns a profile with instrument type `etf` - **AND** the app reports ETF evaluation as not yet supported rather than running the equity branch against it #### Scenario: Unknown or unlisted ticker is rejected - **WHEN** a user submits a symbol that does not resolve to an NYSE/Nasdaq security - **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