suryaarajan/earnings-lens-project
π EarningsLens
AI-powered, explainable analysis of earnings-call language.
EarningsLens takes a pasted earnings-call paragraph, management-commentary snippet, or transcript excerpt and returns a structured, beginner-readable analysis: financial sentiment, operational and financial themes, an explainable operational-risk score, management outlook, likely financial impacts, supporting evidence, and a concise executive summary.
It sits at the intersection of business analytics, supply-chain and operations management, finance and investment analysis, and natural-language processing β implemented with Hugging Face transformers and a small, transparent Python application.
β οΈ Educational decision-support tool β not financial advice. EarningsLens analyzes language. It does not predict stock returns and is not an investment-recommendation system.
1. Project overview
EarningsLens is a portfolio-quality MVP that demonstrates how pretrained NLP models plus transparent, hand-written heuristics can turn dense earnings-call prose into structured, explainable signals a business student can read and reason about.
2. Business problem
Earnings calls are long and full of hedged, qualitative language. Analysts, students, and operators want a fast way to gauge tone, surface operational and financial themes (freight, inventory, demand, margins, capacity, and so on), and frame likely business effects β without over-claiming precision. EarningsLens provides that first-pass lens while being explicit about its limits.
3. Main features
- Financial sentiment (positive / negative / neutral) with a signed score.
- Operational & financial themes via configurable zero-shot classification.
- Explainable operational-risk score (0β100) with a documented formula.
- Management outlook (Optimistic / Balanced / Cautious).
- Likely financial impacts from a transparent themeβeffect mapping.
- Evidence excerpts drawn directly from your input.
- Deterministic executive summary in hedged, decision-support language.
- Sentence-aware chunking so long passages are handled without truncation.
- Runs fully local on CPU β no API keys, database, or external data feeds.
4. Architecture
app.py Gradio Blocks UI (module-level `demo` for HF Spaces)
src/earnings_lens/
βββ config.py Model names, thresholds, theme lists, label maps
βββ schemas.py Typed dataclasses for internal results
βββ chunking.py Sentence splitting + token-bounded chunking
βββ models.py Lazy, lru_cache-d Hugging Face pipelines
βββ scoring.py Aggregation + explainable heuristics
βββ analyzer.py Orchestration + input validation (DI-friendly)
βββ formatting.py Executive summary + display tablesThe analysis logic is decoupled from the models: analyzer.analyze() accepts injectable sentiment_fn, zeroshot_fn, and tokenizer callables, so the whole pipeline is testable with fakes and no downloads.
5. Models used
Both run on CPU by default (device=-1); CUDA is never assumed. Pipelines are lazily built and cached with functools.lru_cache, so models load only on the first analysis β importing a module (or a test) never downloads them.
6. How the pipeline works
- Input & validation β text is stripped and checked for length (about 40β15,000 characters). The upper limit keeps the free CPU demo responsive; input is never silently truncated.
- Sentence-aware chunking β text is split into sentences with a lightweight regex (no extra NLP model) and greedily packed into ~380-token chunks using the FinBERT tokenizer, leaving room for special tokens. A single oversized sentence is split safely on tokens and decoded back to text. Order is preserved and each chunk records its token count.
- Sentiment β FinBERT scores every chunk; positive/negative/neutral are combined with token-count weights. The signed score is
positive β negative. - Themes β the zero-shot model scores every chunk against the theme vocabulary; strengths are token-weighted across chunks and the top themes are displayed. Zero-shot values are reported as model confidence / theme strength, not calibrated probabilities.
- Heuristics β risk score, outlook, impacts, evidence, and the executive summary are computed with deterministic, documented Python.
7. Explainable risk-score formula
risk_score = 100 Γ ( 0.45 Β· negative_probability
+ 0.45 Β· risk_theme_strength
+ 0.10 Β· caution_score )negative_probabilityβ token-weighted FinBERT negative probability.risk_theme_strengthβ average of up to the top three aggregated risk-oriented theme scores (0 if none detected).caution_scoreβ share of a transparent caution-word list present in the text, counted by distinct terms so repeated words cannot exceed 1.0.
The result is rounded and clamped to 0β100:
This is a transparent, project-specific heuristic decision-support score β not a prediction of stock performance or financial distress.
8. Local installation and run
# 1) Create and activate a virtual environment
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# 2) Install runtime dependencies
pip install -r requirements.txt
# 3) (optional) install dev dependencies for tests
pip install -r requirements-dev.txt
# 4) Launch the app locally
python app.py # serves at http://127.0.0.1:7860The first analysis downloads the two models (a few hundred MB) and can take a little longer; subsequent runs use the local cache. Public sharing is disabled by default.
9. Testing
python -m pytest -q
python -m compileall app.py src testsTests run offline β they use fake model callables and a whitespace tokenizer, so no network access or model download is required.
10. Example inputs and outputs
Input (negative operational passage):
"Freight costs remained elevated during the quarter, and component shortages continued to affect production. We expect inventory levels to remain above historical averages through the end of the yearβ¦"
Illustrative output:
- Sentiment: Strongly negative (signed score β β0.93)
- Top themes: freight and logistics costs Β· labor and workforce costs Β· production capacity constraints
- Operational risk: ~61 / 100 (Moderate)
- Outlook: Cautious
- Likely impacts: gross-margin pressure; operating-expense pressure
- Summary: "The model identifies an overall financial sentiment that is strongly negativeβ¦ The estimated operational risk level is moderateβ¦ the passage suggests a cautious management outlookβ¦"
More examples ship in `examples/sample_passages.txt` and are clickable in the UI.
11. Project structure
EarningsLens/
βββ app.py
βββ requirements.txt
βββ requirements-dev.txt
βββ README.md
βββ LICENSE
βββ .gitignore
βββ conftest.py
βββ src/earnings_lens/
β βββ __init__.py
β βββ config.py
β βββ models.py
β βββ chunking.py
β βββ analyzer.py
β βββ scoring.py
β βββ formatting.py
β βββ schemas.py
βββ tests/
β βββ __init__.py
β βββ test_chunking.py
β βββ test_scoring.py
β βββ test_analyzer.py
β βββ test_formatting.py
βββ examples/
βββ sample_passages.txt12. Limitations
- Pretrained models are used as-is (no fine-tuning yet); they can misread sarcasm, hedging, or unusual phrasing.
- Zero-shot "confidence" is a relative strength, not a calibrated probability.
- The operational-risk score is a heuristic for study and discussion β it does not predict stock returns or financial distress.
- The analysis reflects only the pasted text; it has no access to filings, guidance history, or market data.
- English-language earnings commentary works best.
13. Ethical and financial disclaimer
EarningsLens is an educational decision-support tool, not an investment-recommendation system. It does not provide personalized financial advice and does not predict stock performance. Always verify findings against primary sources and consult a licensed professional for investment decisions.
14. Potential future improvements
- Fine-tuned, calibrated theme and sentiment models on labeled earnings data.
- Confidence calibration and uncertainty display.
- Speaker/segment attribution (prepared remarks vs. Q&A).
- Multi-passage and full-transcript comparison over time.
- Exportable reports and optional retrieval over prior calls.
15. Model attribution and licensing
- FinBERT β Β© ProsusAI, distributed on the Hugging Face Hub under its own terms.
cross-encoder/nli-deberta-v3-smallβ Β© its authors, under its own terms.
The MIT license in `LICENSE` covers the original EarningsLens application code only. It does not extend to third-party model weights, which are governed by their respective licenses. Verify each model's license and usage terms before any commercial use.
A note on the MVP
This MVP deliberately uses pretrained models rather than a newly trained model: FinBERT analyzes financial sentiment, and the zero-shot model identifies a configurable set of business themes. Model confidence scores are not guaranteed to be calibrated probabilities, and the risk score is a project-specific heuristic. The project does not predict stock returns.
