SentimentFX

org.sentimentfxPublished by sentimentfx.orgOfficial publisherv1.0.0Updated Oct 24, 2026

FinBERT news sentiment and price history for 42 crypto, FX, stock, ETF and commodity tickers.

VerifiedStreamable HTTPWeb executableWeb Search & ScrapingFinanceData & Analytics

Overview

AI-generated overview

SentimentFX exposes FinBERT-scored news sentiment, daily prices and sentiment-price correlation for 42 crypto, FX, stock, ETF and commodity tickers over a…

What you can do
  • List tracked tickers and inspect API key allowance, remaining credits and refill timing
  • Retrieve recent scored headlines per ticker, with sentiment score, label and source kind
  • Get daily aggregated sentiment averages and daily close prices over a chosen number of days
  • Get 180-day Pearson correlation between sentiment shifts and next-day returns, with p-value, confidence interval and strength label
When to use it
Useful when an assistant needs quick, structured market news sentiment or price history for the covered tickers, for example to compare sentiment with price moves or to summarize recent coverage. It is a data source, not a forecast, so it suits research and monitoring rather than trading decisions.
Requirements
Remote streamable HTTP endpoint; no local install. Requires a SentimentFX API key sent in the X-API-Key header (or a bearer token for clients that cannot set custom headers). A free key is available with 1,000 calls per 30 days; paid plans raise the allowance. Network access to the provider's API is needed.
Before you install
Calls are metered: get_sentiment, get_summary, get_prices and get_correlation consume API credits based on rows or days returned, and a key that exhausts its allowance returns an insufficient-quota error until it refills. Paid plans and the bulk archive cost money. The API key is a secret and should be kept out of shared configs. Sentiment is derived from news headlines only and the provider states it is not a price forecast.

Installation

In SourceWeft

  1. Open SentimentFX in the dashboard and add it to a workspace.
  2. Connect X-API-Key credentials. They are stored privately and never shown on public pages.
  3. Enable the server for the chats that should use its tools.

Web executable via Streamable HTTP. Remote servers run from the web runtime once configured in a workspace.

Use with an agent

Paste this prompt into Claude Code, Codex, Cursor or another agent — or into SourceWeft chat. The agent reads this server's install guide, shows you its publisher, endpoint and sign-in, and adds it to your client once you agree. Keys never go into a command.

Read https://sourceweft.com/mcp/org.sentimentfx%2Fmarket-sentiment/install.md and connect the MCP server it describes to my client. Before changing any config, show me its publisher, endpoint and sign-in method and wait for my OK. Never put an API key in a command or in a file I would commit; ask me where it should come from.

Read the install guide the agent follows

Other MCP clients

Add this to your client's mcpServers config.

{
  "mcpServers": {
    "sentimentfx": {
      "type": "http",
      "url": "https://api.sentimentfx.org/mcp",
      "headers": {
        "X-API-Key": "<YOUR_API_KEY>"
      }
    }
  }
}

README

SentimentFX

A news-sentiment dataset for 42 markets across crypto, FX, stocks, ETFs and commodities. SentimentFX scrapes financial headlines, scores each one with FinBERT (a finance-tuned transformer model), and stores the scores next to daily and intraday prices. You can read the data on a dashboard, through a metered REST API, or as tools over MCP for Claude and other AI clients.

The product is the scored archive and live feed. It is not a price forecast: the dashboard shows correlation and backtest results so you can judge the signal yourself, and it makes no claim that sentiment predicts returns.

Live: sentimentfx.org · app.sentimentfx.org · developers.sentimentfx.org · status.sentimentfx.org


What it does

  • Pulls headlines from RSS feeds every 15 minutes (CoinDesk, CoinTelegraph, Yahoo Finance, r/CryptoCurrency and others), plus RSS-less news sites through saved ScraperAI configs
  • Scores each new headline once with FinBERT: positive_prob - negative_prob, giving -1 to +1, shown as 0–100 in the UI
  • Refreshes prices for all 42 tickers every hour through yfinance (daily OHLC and intraday candles)
  • Correlates daily sentiment shifts with next-day returns over 180 days, with a 95% confidence interval and a strength label
  • Publishes a free cross-asset Sentiment Index (0–100, Fear → Greed) built from scored news text, not trader positioning
  • Sells access through Stripe: a Pro dashboard plan, a Data plan for the API, and the full archive on request

Coverage

CategoryTickers
Crypto (5)BTC, ETH, SOL, XRP, DOGE
FX (7)EURUSD, GBPUSD, USDJPY, AUDUSD, USDCAD, USDCHF, NZDUSD
Stocks (20)AAPL, MSFT, GOOGL, AMZN, META, NVDA, TSLA, JPM, BAC, GS, V, MA, XOM, JNJ, AMD, NFLX, WMT, UBER, CRM, PLTR
ETFs (6)SPY, QQQ, GLD, SLV, USO, ARKK
Commodities (4)GC=F (gold), SI=F (silver), CL=F (crude), NG=F (natural gas)

Price currency depends on category. Crypto is quoted in GBP (BTC-GBP on Yahoo). FX pairs are raw exchange rates. Stocks, ETFs and commodity futures are in native USD, and no GBP conversion is applied.

Products

Dashboard (app.sentimentfx.org)

  • Sentiment vs price chart, candlestick chart with a sentiment pane, and a 0–100 sentiment gauge
  • Correlation signal, divergence card, interactive backtest simulator and headline-impact panel
  • Headline feed with a per-article score. Editorial news is the default, and social sources are badged.
  • Leaderboard, track record and morning-brief pages
  • CSV export, email sentiment alerts and the morning brief email (Pro)

Alerts only fire for tickers whose backtest passes a quality gate: positive out-of-sample net return, and at least 70% of walk-forward folds positive. The gate is refreshed daily.

Plans

PlanPriceIncludes
Free£015 top tickers (3 per category), 30-day history, candlesticks, backtests, correlation
Pro£11.99/mo or £99.99/yrAll 42 tickers, full history, CSV export, alerts, morning brief, 15,000 API calls/mo
Data£49.99/mo or £499.99/yrEverything in Pro, 200,000 API calls/mo
Free API key£01,000 calls per 30 days, no card, hard stop at the limit

The bulk archive (every scored headline and price row, as CSV or JSONL) is sold separately. Ask through the dataset form on the developer portal.

Developer API (api.sentimentfx.org/v1/)

Authenticate with an X-API-Key header. Full docs are at developers.sentimentfx.org.

EndpointReturnsCost
GET /v1/sentiment/{ticker}?limit=1-100&sources=news|social|allLatest scored headlines, each with a source_kind1 credit per 25 rows returned
GET /v1/summary/{ticker}?days=1-365&sources=news|socialDaily average sentiment1 credit per day returned
GET /v1/prices/{ticker}?days=1-365Daily closes, with a currency field1 credit per day returned
GET /v1/correlation/{ticker}180-day Pearson r, p-value, 95% CI, strength1 credit
GET /v1/usagePlan, usage, allowance, reset date, rate limitsFree

Social posts (Reddit, StockTwits, X) are collected but kept separate. Every sentiment number is news only by default, and sources=social returns the social posts on their own. Calls are counted after the query, on rows actually returned. Nothing is billed per call: a key that uses up its allowance gets a 402 insufficient_quota until it refills, and a higher allowance can be requested. A 404 costs nothing, and out-of-range parameters are rejected with a 422 before any work is done. Every response carries X-Quota-* and X-RateLimit-* headers. Errors use one envelope: {"error": {"type": "...", "message": "..."}}.

bash
# Get a free key (1,000 calls every 30 days, no card)curl -X POST https://api.sentimentfx.org/api/keys/generate \  -H "Content-Type: application/json" \  -d '{"email": "[email protected]"}'
# Use itcurl https://api.sentimentfx.org/v1/summary/BTC?days=7 \  -H "X-API-Key: sfx_your_key_here"

The Sentiment Index is public and needs no key: GET https://api.sentimentfx.org/sentiment-index. Like every other sentiment number, it's built from news only.

MCP server (api.sentimentfx.org/mcp)

The same data is exposed as six Model Context Protocol tools: list_tickers and get_usage (both free), plus get_sentiment, get_summary, get_prices and get_correlation, which bill exactly like their /v1 equivalents. It uses streamable HTTP with the same X-API-Key header, or Authorization: Bearer <key> for clients that can't set custom headers (the Claude API's MCP connector is one). The registry manifest is server.json, and publishing steps are in docs/publishing-mcp-registry.md.

json
{  "mcpServers": {    "sentimentfx": {      "type": "http",      "url": "https://api.sentimentfx.org/mcp",      "headers": { "X-API-Key": "sfx_your_key_here" }    }  }}

Architecture

RSS feeds (15 min) ─┐ScraperAI replay ───┼→ scraper.py / ai_sources.py → dedup by URL → FinBERT → headlinesHN Algolia (admin) ─┘
yfinance (hourly) → prices.py / candles.py → prices, candles
headlines + prices → /dashboard, /candles, /correlation, /backtest …  → React dashboard                   → /v1/*  and  /mcp                                → API and MCP clients                   → /sentiment-index                                → public index page

Scheduled jobs (APScheduler, inside the API process):

JobWhenWhat
scrape_rss_onlyEvery 15 minRSS + ScraperAI headlines for all 42 tickers
scrape_allHourly, :00Daily price refresh for all tickers, sentiment alert checks (GNews only if enabled)
scrape_intraday_pricesHourly, :05Intraday candles
Signal-quality refreshDaily, 05:00 UTCRe-runs the backtest that gates alerts
Alert outcome settlementDaily, 06:15 UTCScores past alerts for the track record
Morning briefDaily, 07:00 LondonEmails the Claude-written brief to subscribers
API usage reset1st of monthResets monthly call counts. Free keys are measured on lifetime calls, so this doesn't refill them.

FinBERT only runs on headlines it hasn't seen. The model (~400 MB) downloads and loads on the first scoring call, not at import.

Dormant sources. GNews, StockTwits and X/Twitter fetchers are still in the code but switched off. Set GNEWS_ENABLED, STOCKTWITS_ENABLED or X_ENABLED to true to turn one back on. StockTwits was turned off because Cloudflare blocks the server's IP and retail chat scores poorly with a news-tuned model.

Repo layout

PathWhat
backend/app/main.pyEvery FastAPI route, the scheduler, Stripe webhook and billing
backend/app/scraper.py, ai_sources.pyHeadline fetchers. ScraperAI configs live in app/scraperai_configs/.
backend/app/sentiment.pyFinBERT pipeline
backend/app/prices.py, candles.pyyfinance daily and intraday prices
backend/app/sentiment_index.pyThe cross-asset index (equal-weighted across the 5 categories)
backend/app/mcp_server.pyMCP tools, mounted at /mcp
backend/app/brief.pyClaude-written morning brief
backend/app/trend_signal.py, funding_monitor.pyPersonal-use tooling, not product features
backend/build_scraper_config.pyOffline tool that generates ScraperAI configs. Needs its own venv; not used at runtime.
frontend/React + Vite dashboard
landing/Marketing site, leaderboard, index page and per-ticker SEO pages
developers/Developer portal and API docs
status/Status page

Getting started

Backend

bash
cd backendpython -m venv venvsource venv/Scripts/activate        # Windows (Git Bash); venv/bin/activate on macOS/Linuxpip install -r requirements.txtpython -m uvicorn app.main:app --reload   # http://localhost:8000

There is no .env.example. Create backend/.env with the variables below.

VariableNeeded for
DATABASE_URLPostgreSQL. Required: tables are created at import, so the app won't start without a reachable database.
ANTHROPIC_API_KEYMorning brief. Read at import, so any value lets the app boot.
SUPABASE_URL, SUPABASE_SERVICE_KEYUser accounts and tiers
STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRETCheckout and webhook
RESEND_API_KEYWaitlist, alert and API-key emails
ADMIN_SECRET?token= for admin, backfill and cleanup endpoints
MCP_ALLOWED_HOSTSOptional. Hosts the MCP endpoint accepts. Defaults cover localhost and 127.0.0.1 on port 8000; other ports get a 421.
GNEWS_ENABLED, GNEWS_API_KEY, STOCKTWITS_ENABLED, X_ENABLED, X_NITTER_BASEOptional. Dormant sources.

Frontend

bash
cd frontendnpm installnpm run dev      # http://localhost:5173

Set VITE_SUPABASE_ANON_KEY in frontend/.env to enable login (VITE_GA_ID is optional). The API base URL is hard-coded to https://api.sentimentfx.org in src/lib/constants.js, so a local frontend talks to production unless you change it.

Tests

bash
cd backendpip install -r requirements-dev.txtpython -m pytest tests/ -v

Use python -m pytest, not bare pytest: tests/ has no __init__.py, so bare pytest can't import app. The tests are smoke-level only. They check that the app boots and the core routes answer, and they need a reachable DATABASE_URL. CI runs them against a throwaway Postgres on every push to main and every PR. There is no frontend test suite.

Sentiment scoring

score = positive_probability - negative_probability

The range is -1 (most negative) to +1 (most positive), and the UI shows it as 0–100. Neutral headlines land near 0 instead of being forced to exactly 0, which was the problem with the old label × confidence method. FinBERT scores the title only, even when the full article body is stored.

Deployment

  • Backend: Railway via Procfile + nixpacks.toml at api.sentimentfx.org. Starts with uvicorn app.main:app --host 0.0.0.0 --port $PORT. Runs on CPU only.
  • Dashboard, landing, developer portal: separate Vercel projects (frontend/, landing/, developers/), each auto-deploying from main.

Source: README.md at commit 0357f97

Tools

6

list_tickers

List every asset SentimentFX tracks. Cheap (free — doesn't hit the billing meter). Returns two groups: `primary` (5 crypto + 7 FX pairs — the ones with full sentiment coverage across the primary RSS feeds), and `background` (US equities, ETFs, commodity futures — coverage is thinner but real). Use the exact ticker string from either group as the `ticker` arg to the other tools.

Takes no parameters.

get_usage

Introspect your API key: included allowance, remaining credits, and when they refill. Free keys get 1,000 calls per 30-day window starting at their first billable call (`resets_at` is null when no window is running); paid plans refill on the 1st of each month. Free — doesn't hit the billing meter. Useful before a large batch of `get_sentiment`/`get_summary` calls to check you have credit headroom.

Takes no parameters.

get_sentiment

Return the most recent FinBERT-scored news headlines for `ticker`. Each headline has a `sentiment_score` in [-1, +1] (positive_prob - negative_prob), a categorical `sentiment_label`, and a `source_kind` (news / reddit / stocktwits / x / youtube). Costs 1 API credit per 25 headlines actually returned — same billing as GET /v1/sentiment/{ticker}. An empty result costs nothing. `limit` is capped at 100. Social posts are kept separate from news: the default `sources="news"` returns editorial news, `"social"` returns only Reddit, StockTwits and X posts, and `"all"` returns both, labelled by `source_kind`. Titles come back reverse-chronological so the first item is the freshest.

Parameterslimittickerrequiredsources

get_summary

Return daily aggregated news sentiment for `ticker` over the last `days`. Each entry has `avg_sentiment` (unweighted mean of that day's scores), `article_count`, and a directional `label` (positive / negative / neutral, thresholded at ±0.1). `sources="social"` returns a separate daily average of Reddit, StockTwits and X posts; news and social are never averaged together. Costs 1 API credit per day actually returned — same as GET /v1/summary/{ticker}. A window with no coverage costs nothing.

Parametersdaystickerrequiredsources

get_prices

Return daily close prices for `ticker` over the last `days`, in the ticker's native currency -- see the `currency` field on the response. Costs 1 API credit per day actually returned — same as GET /v1/prices/{ticker}. Prices come back reverse-chronological. Crypto is GBP (yfinance BTC-GBP etc.), FX pairs are a raw exchange rate in the pair's native convention (e.g. USDJPY is yen per dollar), and everything else (stocks/ETFs/commodity futures) is native USD -- there is no currency conversion.

Parametersdaystickerrequired

get_correlation

180-day Pearson correlation between daily sentiment shifts and next-day price returns for `ticker`. Returns Pearson `r`, `p_value`, `n_days` overlapping, a 95% confidence interval (Fisher z), and a categorical `strength` (strong / weak / inconclusive). Costs 1 API credit — same as GET /v1/correlation/{ticker}. Requires ≥30 overlapping day-pairs. Under that, returns a `note` field explaining what's missing so a caller can suggest waiting or switching to a higher-coverage ticker.

Parameterstickerrequired

Version history

1
  1. v1.0.0LatestSep 16, 2026

Score

90% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 daysRequired25 pts
  • Auth declaredRequired10 pts
  • Tools listedRequired15 pts
  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts

    Declare a license in the repository or the registry entry.