# Requirements Document

## Introduction

This specification covers four dashboard enhancements for the stock signal platform: sentiment drill-down with OpenAI response details, fundamentals drill-down with missing-data transparency, TradingView-style chart improvements (zoom, crosshair), and S/R level clustering into filterable shaded zones. All changes target the existing TickerDetailPage and its child components, preserving the glassmorphism UI style.

## Glossary

- **Dashboard**: The TickerDetailPage in the React frontend that displays ticker data, charts, scores, sentiment, and fundamentals.
- **Sentiment_Panel**: The SentimentPanel component that displays classification, confidence, dimension score, and source count for a ticker.
- **Fundamentals_Panel**: The FundamentalsPanel component that displays P/E Ratio, Revenue Growth, Earnings Surprise, and Market Cap for a ticker.
- **Chart_Component**: The CandlestickChart canvas-based component that renders OHLCV candlesticks and S/R level overlays.
- **SR_Service**: The backend service (sr_service.py) that detects, scores, merges, and tags support/resistance levels from OHLCV data.
- **Sentiment_Provider**: The OpenAISentimentProvider that calls the OpenAI Responses API with web_search_preview to produce sentiment classifications.
- **FMP_Provider**: The FMPFundamentalProvider that fetches fundamental data from Financial Modeling Prep stable endpoints.
- **SR_Zone**: A price range representing a cluster of nearby S/R levels, displayed as a shaded area on the chart instead of individual lines.
- **Detail_Section**: A collapsible/expandable UI region within a panel that reveals additional information on user interaction.
- **Data_Availability_Indicator**: A visual element within the Fundamentals_Panel that communicates which data fields are unavailable and the reason.
- **Crosshair**: A vertical and horizontal line overlay on the Chart_Component that tracks the cursor position and displays corresponding price and date values.

## Requirements

### Requirement 1: Sentiment Detail Storage

**User Story:** As a developer, I want the backend to store the full OpenAI response details (reasoning text, web search citations, and annotations) alongside the sentiment classification, so that the frontend can display drill-down information.

#### Acceptance Criteria

1. WHEN the Sentiment_Provider receives a response from the OpenAI Responses API, THE Sentiment_Provider SHALL extract and return the reasoning text from the parsed JSON response.
2. WHEN the Sentiment_Provider receives a response containing web_search_preview output items, THE Sentiment_Provider SHALL extract and return the list of source URLs and titles from the search result annotations.
3. THE sentiment API endpoint SHALL include the reasoning text and citations list in the response payload for each sentiment score.
4. IF the OpenAI response contains no annotations or citations, THEN THE Sentiment_Provider SHALL return an empty citations list without raising an error.

### Requirement 2: Sentiment Drill-Down UI

**User Story:** As a user, I want to drill into the sentiment analysis to see the AI reasoning and source citations, so that I can evaluate the quality of the sentiment classification.

#### Acceptance Criteria

1. THE Sentiment_Panel SHALL display a clickable expand/collapse toggle below the summary metrics.
2. WHEN the user expands the Detail_Section, THE Sentiment_Panel SHALL display the reasoning text from the latest sentiment score.
3. WHEN the user expands the Detail_Section and citations are available, THE Sentiment_Panel SHALL display each citation as a clickable link showing the source title and URL.
4. WHEN the user collapses the Detail_Section, THE Sentiment_Panel SHALL hide the reasoning and citations without removing the summary metrics.
5. THE Detail_Section SHALL default to the collapsed state on initial render.

### Requirement 3: Fundamentals Data Availability Transparency

**User Story:** As a user, I want to understand why certain fundamental metrics are missing for a ticker, so that I can distinguish between "data not available from provider" and "data not fetched."

#### Acceptance Criteria

1. WHEN the FMP_Provider receives an HTTP 402 response for a supplementary endpoint, THE FMP_Provider SHALL record the endpoint name and the reason "requires paid plan" in the response metadata.
2. THE fundamentals API endpoint SHALL include a field listing which data fields are unavailable and the corresponding reason for each.
3. WHEN a fundamental metric value is null and a corresponding unavailability reason exists, THE Fundamentals_Panel SHALL display the reason text (e.g., "Requires paid plan") instead of a dash character.
4. WHEN a fundamental metric value is null and no unavailability reason exists, THE Fundamentals_Panel SHALL display a dash character as the placeholder.

### Requirement 4: Fundamentals Drill-Down UI

**User Story:** As a user, I want to drill into the fundamentals data to see additional detail and data source information, so that I can better assess the fundamental metrics.

#### Acceptance Criteria

1. THE Fundamentals_Panel SHALL display a clickable expand/collapse toggle below the summary metrics.
2. WHEN the user expands the Detail_Section, THE Fundamentals_Panel SHALL display the data source name, the fetch timestamp, and any unavailability reasons for missing fields.
3. WHEN the user collapses the Detail_Section, THE Fundamentals_Panel SHALL hide the detail information without removing the summary metrics.
4. THE Detail_Section SHALL default to the collapsed state on initial render.

### Requirement 5: Chart Zoom Capability

**User Story:** As a user, I want to zoom in and out on the candlestick chart, so that I can examine specific time periods in detail or see the full price history.

#### Acceptance Criteria

1. WHEN the user scrolls the mouse wheel over the Chart_Component, THE Chart_Component SHALL zoom in or out by adjusting the visible date range.
2. WHEN the user zooms in, THE Chart_Component SHALL increase the candle width and reduce the number of visible bars proportionally.
3. WHEN the user zooms out, THE Chart_Component SHALL decrease the candle width and increase the number of visible bars proportionally.
4. WHEN the chart is zoomed in, THE Chart_Component SHALL allow the user to pan left and right by clicking and dragging horizontally.
5. THE Chart_Component SHALL constrain zoom limits so that the minimum visible range is 10 bars and the maximum visible range is the full dataset length.
6. THE Chart_Component SHALL re-render S/R overlays correctly at every zoom level.

### Requirement 6: Chart Crosshair

**User Story:** As a user, I want a crosshair overlay on the chart that tracks my cursor, so that I can precisely read price and date values at any point.

#### Acceptance Criteria

1. WHEN the user moves the cursor over the Chart_Component, THE Chart_Component SHALL draw a vertical line at the cursor x-position spanning the full chart height.
2. WHEN the user moves the cursor over the Chart_Component, THE Chart_Component SHALL draw a horizontal line at the cursor y-position spanning the full chart width.
3. THE Chart_Component SHALL display the corresponding price value as a label on the y-axis at the horizontal crosshair position.
4. THE Chart_Component SHALL display the corresponding date value as a label on the x-axis at the vertical crosshair position.
5. WHEN the cursor leaves the Chart_Component, THE Chart_Component SHALL remove the crosshair lines and labels.

### Requirement 7: S/R Level Clustering

**User Story:** As a user, I want nearby S/R levels to be clustered into zones, so that the chart is less cluttered and I can focus on the most significant price areas.

#### Acceptance Criteria

1. THE SR_Service SHALL accept a configurable clustering tolerance parameter that defines the maximum price distance (as a percentage) for grouping levels into a single SR_Zone.
2. WHEN two or more S/R levels fall within the clustering tolerance of each other, THE SR_Service SHALL merge those levels into a single SR_Zone with a price range (low bound, high bound) and an aggregated strength score.
3. THE SR_Service SHALL compute the aggregated strength of an SR_Zone as the sum of constituent level strengths, capped at 100.
4. THE SR_Service SHALL tag each SR_Zone as "support" or "resistance" based on the zone midpoint relative to the current price.

### Requirement 8: S/R Zone Filtering

**User Story:** As a user, I want to see only the strongest S/R zones on the chart, so that I can focus on the most significant price areas.

#### Acceptance Criteria

1. THE S/R API endpoint SHALL accept an optional parameter to limit the number of returned zones.
2. WHEN a zone limit is specified, THE SR_Service SHALL return only the zones with the highest aggregated strength scores, up to the specified limit.
3. THE Dashboard SHALL default to displaying a maximum of 6 SR_Zones on the chart.

### Requirement 9: S/R Zone Chart Rendering

**User Story:** As a user, I want S/R zones displayed as shaded areas on the chart instead of individual lines, so that I can visually identify price ranges of significance.

#### Acceptance Criteria

1. THE Chart_Component SHALL render each SR_Zone as a semi-transparent shaded rectangle spanning the zone price range (low bound to high bound) across the full chart width.
2. THE Chart_Component SHALL use green shading for support zones and red shading for resistance zones.
3. THE Chart_Component SHALL display a label for each SR_Zone showing the zone midpoint price and strength score.
4. THE Chart_Component SHALL render SR_Zones behind the candlestick bodies so that candles remain fully visible.
5. WHEN the chart is zoomed, THE Chart_Component SHALL re-render SR_Zones at the correct vertical positions for the current price scale.
