feat(market): surface an LLM news-sentiment sub-score on stock analysis - #5656
feat(market): surface an LLM news-sentiment sub-score on stock analysis#5656dyrach1o wants to merge 2 commits into
Conversation
The analyze-stock overlay model already reads the pulled headlines but only emits prose. Ask it for one extra key — a signed newsSentiment in [-1, 1] — in the same strict-JSON call, so there is no extra LLM request, no new dependency, and no external quota. Normalize (clamp + round) and surface it as optional AnalyzeStockResponse field 69, plus a "News" tile in the panel. Omitted when the analysis falls back to the deterministic rules overlay (no LLM). Field 69 avoids a collision with the in-flight rating-blend (61-62) and risk-analytics (66-68) PRs.
|
@dyrach1o is attempting to deploy a commit to the World Monitor Team on Vercel. A member of the Team first needs to authorize it. |
Greptile SummaryAdds an optional LLM-derived news-sentiment score to stock analysis.
Confidence Score: 3/5The PR should not merge until analyses without headlines stop surfacing a synthetic neutral News reading. The LLM is invoked with an empty headline list when news is disabled or unavailable, and the new prompt, normalization, response mapping, and UI collectively turn that absence into a visible neutral score. Files Needing Attention: server/worldmonitor/market/v1/analyze-stock.ts
|
| Filename | Overview |
|---|---|
| server/worldmonitor/market/v1/analyze-stock.ts | Adds prompt, normalization, and response mapping, but emits a synthetic neutral score when no headlines exist. |
| src/components/StockAnalysisPanel.ts | Conditionally formats and renders the optional sentiment value with escaped output. |
| proto/worldmonitor/market/v1/analyze_stock.proto | Adds the optional field 69 while preserving backward-compatible response semantics. |
| tests/stock-analysis.test.mts | Covers normalization and field mapping but does not cover the empty-headline LLM path. |
| src/generated/client/worldmonitor/market/v1/service_client.ts | Regenerates the client response interface with the optional numeric field. |
| src/generated/server/worldmonitor/market/v1/service_server.ts | Regenerates the server response interface with the optional numeric field. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart LR
A[Analyze stock request] --> B[Fetch market data]
A --> C{includeNews}
C -->|true| D[Fetch headlines]
C -->|false| E[Empty headline list]
D --> F[LLM overlay]
E --> F
F --> G[Normalize newsSentiment]
G --> H[AnalyzeStockResponse]
H --> I[Conditional News tile]
Reviews (1): Last reviewed commit: "feat(market): surface an LLM news-sentim..." | Re-trigger Greptile
| { | ||
| role: 'system', | ||
| content: 'You are a disciplined stock analyst. Weigh the fundamentals alongside the technicals and news — do not judge on price action alone. All margin, return, growth, and debtToEquity values are decimal ratios (0.25 means 25%; debtToEquity 1.5 means debt is 1.5x equity). totalCash, totalDebt, freeCashflow, and ebitda are denominated in fundamentals.financialCurrency. Treat missing values as unknown. Return strict JSON only with keys: summary, action, confidence, whyNow, technicalSummary, newsSummary, bullishFactors, riskFactors. Keep it concise, factual, and free of disclaimers.', | ||
| content: 'You are a disciplined stock analyst. Weigh the fundamentals alongside the technicals and news — do not judge on price action alone. All margin, return, growth, and debtToEquity values are decimal ratios (0.25 means 25%; debtToEquity 1.5 means debt is 1.5x equity). totalCash, totalDebt, freeCashflow, and ebitda are denominated in fundamentals.financialCurrency. Treat missing values as unknown. Return strict JSON only with keys: summary, action, confidence, whyNow, technicalSummary, newsSummary, bullishFactors, riskFactors, newsSentiment. newsSentiment is a signed number from -1 to 1 scoring how bullish the supplied news headlines are for the stock (-1 very bearish, 0 neutral or no material news, 1 very bullish); use 0 when no headlines are provided. Keep it concise, factual, and free of disclaimers.', |
There was a problem hiding this comment.
Synthetic sentiment without headlines
When news is disabled or headline retrieval returns an empty list, this instruction makes the LLM return zero, which is preserved by the response mapping and causes the panel to display “News — Neutral (+0.00)” even though no news was requested or available. Omit the sentiment unless at least one headline was supplied.
A news-disabled or empty-headline run still surfaced newsSentiment: 0, showing a misleading "News — Neutral (+0.00)" tile for an analysis that never looked at any news. Gate the response field on headlines.length > 0 so the score only appears when headlines were actually scored, and drop the prompt's "use 0 when no headlines" instruction.
Summary
The
analyze-stockoverlay model already reads the pulled news headlines butonly emits prose. This asks it for one extra JSON key — a signed
newsSentimentin[-1, 1]— in the same strict-JSON overlay call:comes from the headlines the overlay already receives.
[-1, 1], round to 2dp) via an exportedpure
normalizeNewsSentimenthelper, then surfaced as optionalAnalyzeStockResponsefield 69.(no LLM), so the field only appears when a real sentiment reading exists.
grid (only when present).
Deliberately scoped: the score is not blended into the rating/composite
score (that is the concurrent fundamentals-blend PR's surface), and no news
corpus index is built — this is a self-contained additive signal.
Field 69 avoids a field-number collision with the in-flight rating-blend
PR (claims 61-62) and risk-analytics PR (claims 66-68); 63-65 are the merged
earnings join.
Type of change
Affected areas
/api/*)Checklist
api/rss-proxy.jsallowlist (if adding feeds)npm run typecheck)Also verified:
npm run typecheck:api,npx biome linton changed files, andthe stock-analysis test suite (24/24, including 7 new cases: the mocked-LLM
flow, prompt-instruction assertion, response present/omit mapping, and the
normalizeNewsSentimentround/clamp/undefined cases).Documentation Alignment Checklist
make generate— OpenAPI + client/server stubs)make generate)