Back to Projects

Investment News Sentiment Analysis Dashboard

A Streamlit dashboard that pairs price charts and fundamentals with AI-powered news sentiment analysis—combining FinBERT scoring and BART summarization to compress scattered headlines into a decision-ready market narrative.

StreamlitNLPSentiment AnalysisFinBERTSummarizationQuant + QualFinancial Modeling Prep API (FMP)

Investment News Sentiment Analysis Dashboard

Markets move on numbers and narratives. This project is an attempt to make both legible in one place: a single Streamlit dashboard that pairs price + fundamentals with a summarized “news tone” signal—fast enough to be useful, structured enough to be explainable.

If you want to explore it live, the demo is here:

  • Dashboard: https://stock-sentiment-dashboard.streamlit.app/
  • Repository: https://github.com/m-turnergane/stock-sentiment-dashboard

What I wanted the dashboard to do (and what I explicitly didn’t)

Most retail workflows look like this:

  1. Open a price chart
  2. Skim a few headlines
  3. Bounce between sources
  4. Leave with a vague feeling, not a decision-ready snapshot

The goal here was to compress steps 2–4 into a single, reviewable artifact:

  • Show the “inputs” (headlines) and the “logic” (sentiment labels/scores) so the output isn’t a black box.
  • Generate a short, readable market narrative so you don’t have to synthesize ten articles manually.
  • Anchor everything next to the price chart and fundamentals to keep sentiment in its proper role: context, not a standalone trading signal.

This is not a price-prediction model. It's a decision-support surface.


Dashboard Screenshots

Dashboard overview showing chart, fundamentals, and sentiment panel

Full dashboard view: price chart, fundamentals, top headlines with sentiment labels, and AI-generated summary in one unified interface.

Top headlines section with sentiment labels

Explainability in action: per-headline sentiment labels (Positive/Negative/Neutral) with confidence scores, so you can audit the overall tone.

AI-generated market narrative summary

The narrative synthesis layer: BART-generated summary that compresses scattered headlines into a readable market context snapshot.


System design at a glance

Pipeline Architecture

Input normalization → Data retrieval → NLP inference → Presentation

Input

Ticker or company name

Market Data

1Y prices + fundamentals

yfinance

News Retrieval

Recent article headlines

NewsAPI

Sentiment

Per-headline scoring

FinBERT

Summary

Narrative synthesis

BART

Dashboard

Unified presentation

Combines quantitative (price, fundamentals) and qualitative (news, sentiment) signals in a single view

The pipeline follows a structured flow:

  1. Input normalization — Accept a ticker or common company name, normalize into a ticker symbol.
  2. Market data layer — Pull 1Y historical prices + key fundamentals (fast, familiar baseline).
  3. News retrieval layer — Fetch a small, recent set of relevant articles (bounded by time window + page size) via NewsAPI's "everything" search.
  4. Sentiment inference — Score each headline using FinBERT (financial-domain sentiment model), producing per-headline label + confidence score.
  5. Narrative synthesis — Summarize the "bundle" of headlines using a BART summarization model, producing a short digest that matches the dashboard's scanning workflow.
  6. Presentation layer — Render: chart, fundamentals, top headlines + sentiment, and an AI-generated summary.

The choices that matter (tradeoffs, not just tooling)

LayerWhy it's thereTradeoff I accepted
News pull (bounded window)Keeps the narrative "fresh" and reduces noiseFewer articles means missing some context; more articles means latency + cost + dilution
FinBERT on headlinesHeadlines are short, high-signal, and faster to scoreHeadline-only sentiment can miss nuance present in article bodies
Summarizer on structured inputConverts "10 links" into a digest you can actually readSummaries can hallucinate if the input is messy; strict input formatting matters
Streamlit caching patternsKeeps the app responsive even with heavyweight modelsCache invalidation becomes a product decision (freshness vs speed)
Explainability via per-headline outputsLets you audit why the dashboard "feels" positive/negativeMore UI surface area; you need to keep it clean and scannable

If you were productizing this, you'd treat freshness, latency, and explainability as first-class metrics, not afterthoughts.


What “good” looks like when you’re using it

A practical workflow is:

  • Enter a ticker (or name)
  • Scan the 1Y chart + fundamentals to set baseline context
  • Read the top 5 headlines with sentiment labels to sanity-check the tone
  • Use the AI summary as your “market narrative” snapshot
  • Optionally: compare to sector sentiment if you’re deciding between peers

If you leave the page knowing what the market is talking about and why the tone reads the way it does, the dashboard did its job.


Operational considerations (the unsexy part that makes it real)

A sentiment dashboard lives and dies by reliability:

  • API key handling: News retrieval depends on external services (rate limits, downtime, quota management).
  • Model cold-start: Transformer models can be slow on first load; caching is not optional if you want a usable UX.
  • Failure modes: A resilient dashboard should degrade gracefully:
    • no news returned → still show chart/fundamentals
    • API error → show a helpful message + retry path
    • model load failure → skip summary, preserve the rest

What I’d add in a v2

If I were extending this beyond an MVP:

  • Sentiment trendline (headline sentiment over time) rather than a single average
  • Source weighting (credibility, recency, relevance scoring)
  • Article-body sentiment (not just headlines) for higher fidelity
  • Watchlist mode (batch analysis for a set of tickers)
  • Exportable report (PDF/markdown snapshot for journaling or review)

Build notes (for builders, not just readers)

  • Choose a default “demo ticker” that reliably has news coverage.
  • Keep the news window configurable (7–14 days) so you can balance freshness vs stability.
  • Treat “average sentiment” as a context signal, not a recommendation engine.

The point of this project isn’t to tell you what to buy.
It’s to reduce time-to-context—without hiding the inputs.

Back to Projects