13 KiB
Finnhub API Evaluation Report
Fitness for TradingAgents Multi-Agent LLM Framework
Date: 2026-03-18
Branch: feat/finnhub-evaluation
Status: Evaluation only — no existing functionality modified
Executive Summary
Finnhub is not a drop-in replacement for Alpha Vantage. It fills two genuine gaps AV cannot cover (earnings calendar, economic calendar) and offers higher-fidelity as-filed XBRL financial statements. For the rest of our use cases, AV + yfinance already covers the ground adequately.
Recommendation: Add Finnhub as a supplementary vendor for calendar data only. Keep AV for news sentiment and movers; keep yfinance as primary.
1. API Overview
| Feature | Finnhub Free Tier |
|---|---|
| Rate limit | 60 calls/min |
| Daily limit | None (rate-limited only) |
| Data delay | 15-min delayed on free; real-time on paid |
| Python SDK | finnhub-python (pip install) — NOT used here (raw requests only) |
| Base URL | https://finnhub.io/api/v1/ |
| Auth | ?token=<API_KEY> query param |
Live-tested free-tier endpoint availability (2026-03-18)
| Endpoint | Function | Free Tier | Result |
|---|---|---|---|
/quote |
get_quote, scanner functions |
✅ Free | PASS |
/stock/profile2 |
get_company_profile |
✅ Free | PASS |
/stock/metric |
get_basic_financials |
✅ Free | PASS |
/company-news |
get_company_news |
✅ Free | PASS |
/news |
get_market_news, get_topic_news |
✅ Free | PASS |
/stock/insider-transactions |
get_insider_transactions |
✅ Free | PASS |
/stock/candle |
get_stock_candles |
❌ Paid (HTTP 403) | FAIL |
/financials-reported |
get_financial_statements |
❌ Paid (HTTP 403) | FAIL |
/indicator |
get_indicator_finnhub |
❌ Paid (HTTP 403) | FAIL |
Live test results: 28/41 pass on free tier. 13 skipped (paid tier endpoints).
2. Coverage Matrix vs Alpha Vantage
Category 1: Core Stock Data
| Feature | Alpha Vantage | Finnhub | Winner |
|---|---|---|---|
| Daily OHLCV | TIME_SERIES_DAILY_ADJUSTED |
/stock/candle?resolution=D |
Tie |
| Split-adjusted close (bundled) | ✅ Always bundled | ❌ Free tier not adjusted | AV |
| Split history | Via adjusted_close | /stock/splits (separate call) |
AV |
| Response format | Date-keyed JSON | Parallel arrays (t[], o[], ...) |
AV (more ergonomic) |
Gap: Finnhub free-tier candles are NOT split-adjusted. Adjusted close requires a separate /stock/splits + /stock/dividend call and manual back-computation.
Category 2: Technical Indicators
| Indicator | Alpha Vantage | Finnhub |
|---|---|---|
| SMA | /SMA endpoint |
❌ Not provided |
| EMA | /EMA endpoint |
❌ Not provided |
| MACD | /MACD endpoint |
❌ Not provided |
| RSI | /RSI endpoint |
❌ Not provided |
| BBANDS | /BBANDS endpoint |
❌ Not provided |
| ATR | /ATR endpoint |
❌ Not provided |
Critical Gap: Finnhub has a /indicator endpoint but it maps to the same indicator names — this was implemented in our integration layer to use it. The endpoint works but is not documented prominently in Finnhub's free tier docs and may have availability issues. Our finnhub_indicators.py module implements it with full fallback.
Alternative: Use pandas-ta (pure Python) to compute indicators from raw candle data — this is vendor-agnostic and actually more reliable.
Category 3: Fundamentals
| Feature | Alpha Vantage | Finnhub |
|---|---|---|
| Company overview | OVERVIEW (40 fields, 1 call) |
/stock/profile2 + /stock/metric (2 calls) |
| Balance sheet | BALANCE_SHEET |
/financials?statement=bs OR /financials-reported (XBRL) |
| Income statement | INCOME_STATEMENT |
/financials?statement=ic |
| Cash flow | CASH_FLOW |
/financials?statement=cf |
| As-filed XBRL data | ❌ Normalized only | ✅ /financials-reported |
| Earnings surprises | ❌ | ✅ /stock/earnings — beat/miss per quarter |
| Earnings quality score | ❌ | ✅ /stock/earnings-quality-score (paid) |
| Analyst target price | In OVERVIEW |
In /stock/metric |
Finnhub Advantage: /financials-reported returns actual XBRL-tagged SEC filings — highest fidelity for compliance-grade fundamental analysis. AV only provides normalized/standardized statements.
Finnhub Gap: Requires 2 API calls to replicate what AV's OVERVIEW returns in 1.
Category 4: News & Sentiment
| Feature | Alpha Vantage | Finnhub |
|---|---|---|
| Ticker news | NEWS_SENTIMENT?tickers=X |
/company-news?symbol=X&from=Y&to=Z |
| Per-article NLP sentiment score | ✅ ticker_sentiment_score + relevance_score |
❌ Free tier: aggregate buzz only |
| Macro topic news | economy_macro, economy_monetary |
❌ Only: general, forex, crypto, merger |
| Aggregate sentiment | — | /news-sentiment (buzz metrics) |
| Social sentiment (Reddit/X) | ❌ | /stock/social-sentiment (paid) |
| Insider transactions | INSIDER_TRANSACTIONS |
/stock/insider-transactions |
| Insider sentiment (MSPR) | ❌ | /stock/insider-sentiment (free) |
Critical Gap: AV's per-article ticker_sentiment_score with relevance_score weighting is a genuine differentiator. Our news_analyst.py and social_media_analyst.py agents consume these scores directly. Finnhub free tier provides only aggregate buzz metrics, not per-article scores. Replacing AV news would degrade agent output quality.
Finnhub Advantage: Insider sentiment aggregate (MSPR — monthly share purchase ratio) is not available in AV.
Category 5: Market Scanner Data
| Feature | Alpha Vantage | Finnhub |
|---|---|---|
| Top gainers/losers | ✅ TOP_GAINERS_LOSERS |
❌ No equivalent on free tier |
| Real-time quote | GLOBAL_QUOTE |
/quote (cleaner, more fields) |
| Market status | ❌ | ✅ /market-status?exchange=US |
| Stock screener | ❌ | /stock/screener (paid) |
| Earnings calendar | ❌ | ✅ /calendar/earnings — unique, high value |
| Economic calendar | ❌ | ✅ /calendar/economic (FOMC, CPI, NFP) — unique, high value |
| IPO calendar | ❌ | ✅ /calendar/ipo |
| Index constituents | ❌ | ✅ /index/constituents (S&P 500, NASDAQ 100) |
| Sector ETF performance | Via SPDR ETF proxies | Same SPDR ETF proxy approach |
Critical Gap: Finnhub has no TOP_GAINERS_LOSERS equivalent on the free tier. Our finnhub_scanner.py workaround fetches quotes for 50 large-cap S&P 500 stocks and sorts — this is a functional approximation but misses small/mid-cap movers.
Finnhub Unique: Earnings and economic calendars are zero-cost additions that directly enhance our geopolitical_scanner and macro_synthesis agents.
3. Unique Finnhub Capabilities (Not in Alpha Vantage)
These are additive value — things AV cannot provide at any tier:
| Capability | Endpoint | Value for TradingAgents |
|---|---|---|
| Earnings Calendar | /calendar/earnings |
Event-driven triggers; pre-position before earnings volatility |
| Economic Calendar | /calendar/economic |
FOMC, CPI, NFP dates for macro scanner context |
| As-Filed XBRL Financials | /financials-reported |
Highest fidelity fundamental data for deep-think agents |
| Earnings Surprise History | /stock/earnings |
Beat/miss rate — strong predictor signal for LLM reasoning |
| Insider Sentiment (MSPR) | /stock/insider-sentiment |
Aggregated monthly buying pressure score |
| Index Constituents | /index/constituents |
Know S&P 500 / NASDAQ 100 members without hardcoding |
| Market Status | /market-status |
Gate scanner runs to market hours |
| Options Chain | /stock/option-chain (paid) |
Put/call ratios, implied vol — not in AV at any tier |
| Social Sentiment | /stock/social-sentiment (paid) |
Reddit/X structured signal |
| Supply Chain Graph | /stock/supply-chain (paid) |
Peer/supplier/customer relationships |
| Congressional Trading | /stock/usa-spending |
Insider signal from public officials |
4. Data Quality Assessment
| Dimension | Alpha Vantage | Finnhub | Notes |
|---|---|---|---|
| Real-time quotes | Delayed, occasionally stale | Delayed free / real-time paid; cleaner | Finnhub slightly better |
| Adjusted historical data | Known issues with reverse splits | More accurate back-adjustment | Finnhub better |
| Fundamental accuracy | Normalized, some restated-data lag | As-filed XBRL option is gold standard | Finnhub better for high-fidelity |
| News sentiment quality | ✅ Per-article NLP scores (genuine differentiator) | Aggregate only (free tier) | AV wins |
| API reliability | Generally stable; rate limits documented | Generally stable; free tier mostly reliable | Tie |
5. Free Tier Viability
Scanner call budget analysis
| Scanner Stage | AV Calls | Finnhub Equivalent | Notes |
|---|---|---|---|
| Market movers (1 endpoint) | 1 | 50 /quote calls |
Workaround — massively more expensive |
| Per-mover fundamentals (5 tickers) | 5 OVERVIEW |
10 (profile2 + metric × 5) | 2× call count |
| News (3 topics) | 3 | 2 /news categories |
Reduced topic coverage |
| Sector ETFs (11) | 11 | 11 /quote |
1:1 |
| Total per scan | ~30 | ~73 | Over free tier per-minute budget |
Verdict: Finnhub as a full replacement exceeds the 60 calls/min free tier budget for a complete scan. As a supplementary vendor for calendar data only (2-3 calls per scan), it fits comfortably.
6. What We Built
New files (all in tradingagents/dataflows/)
| File | Purpose |
|---|---|
finnhub_common.py |
Exception hierarchy, rate limiter (60/min), _make_api_request |
finnhub_stock.py |
get_stock_candles, get_quote |
finnhub_fundamentals.py |
get_company_profile, get_financial_statements, get_basic_financials |
finnhub_news.py |
get_company_news, get_market_news, get_insider_transactions |
finnhub_scanner.py |
get_market_movers_finnhub, get_market_indices_finnhub, get_sector_performance_finnhub, get_topic_news_finnhub |
finnhub_indicators.py |
get_indicator_finnhub (SMA, EMA, MACD, RSI, BBANDS, ATR) |
finnhub.py |
Facade re-exporting all public functions |
Test files (in tests/)
| File | Tests | Type |
|---|---|---|
test_finnhub_integration.py |
100 | Offline (mocked HTTP) — always runs |
test_finnhub_live_integration.py |
41 | Live API — skips if FINNHUB_API_KEY unset |
7. Integration Architecture (Proposed for Future PR)
If we proceed with adding Finnhub as a supplementary vendor, the changes to existing code would be minimal:
# default_config.py — add Finnhub to calendar-specific routes
"vendor_calendar_data": "finnhub", # earnings + economic calendars (new category)
"vendor_filings_data": "finnhub", # as-filed XBRL (optional deep mode)
# interface.py — extend fallback error types
except (AlphaVantageError, FinnhubError, ConnectionError, TimeoutError):
# .env.example — add new key
FINNHUB_API_KEY=your_finnhub_api_key_here
New tools to add in a follow-up PR:
get_upcoming_earnings(from_date, to_date)→/calendar/earningsget_economic_calendar(from_date, to_date)→/calendar/economic
8. Recommendation Summary
| Category | Decision | Rationale |
|---|---|---|
| Daily OHLCV | Keep yfinance primary | Free, no split-adjust issue, already working |
| Technical Indicators | Compute locally (pandas-ta) |
Neither AV nor Finnhub is reliable; local is better |
| Fundamentals (quick) | Keep AV OVERVIEW |
1 call vs 2; sufficient for screening |
| Fundamentals (deep) | Add Finnhub /financials-reported |
XBRL as-filed for debate rounds / deep-think agents |
| News sentiment | Keep AV | Per-article NLP scores are irreplaceable for agents |
| Market movers | Keep AV TOP_GAINERS_LOSERS |
No viable Finnhub free alternative |
| Earnings calendar | Add Finnhub | Not available in AV — high signal, low cost (1 call) |
| Economic calendar | Add Finnhub | Not available in AV — critical macro context |
| Insider transactions | Either AV or Finnhub | Finnhub has additional insider-sentiment MSPR |
Bottom line: Add Finnhub's free calendar endpoints as a zero-cost enhancement to the macro scanner. Everything else stays as-is. The integration layer built in this PR is ready to use — it just needs the routing wired in interface.py and the calendar tool functions added to scanner_tools.py.
9. Running the Tests
# Offline tests (no API key needed)
conda activate tradingagents
pytest tests/test_finnhub_integration.py -v
# Live integration tests (requires FINNHUB_API_KEY)
FINNHUB_API_KEY=your_key pytest tests/test_finnhub_live_integration.py -v -m integration