Project 01 · Finance · AI
Market Sentiment Terminal
A desktop app that reads more than 100 sources in real time, scores every news item with AI and shows what is happening in the market, why, and whether the mood actually moves ahead of the price.
- 100+sources: media, regulators, social networks, market data
- 3000+stories a day, ranked by importance
- 570labelled records for checking accuracy
- 22files of automated tests
The problem
Thousands of news items a day, and most of it is noise
Market news comes in by the thousands every day. The same story appears in dozens of outlets, and a large share is ads, price predictions and “3 stocks to buy”.
I wanted one screen that says what matters, what the mood is, and whether it has anything to do with the price at all. And I wanted to be able to check every number instead of trusting it.
What it does
Three screens from the app
The interface is in Bulgarian. The app reads the news in English and translates and summarises it on its own.
The logic
From a raw headline to one gauge
Seven steps. Every number, weight and time window below comes from the app’s own settings.
-
01 · Collection
Every source that matters
48 news feeds, SEC filings (8-K, 6-K, 13D) for every listed company, press releases, the Fed, the ECB and US statistics, StockTwits and Bluesky, Yahoo and CoinGecko, an economic calendar and FRED data. Requests go out slowly and politely: a site that blocks three times is skipped for 6 hours.
- 48 RSS
- SEC EDGAR
- Fed · ECB · BLS
- StockTwits · Bluesky
- CoinGecko top 500
-
02 · Recognition
Which company is the news about
Every headline is matched against all US stocks and ETFs plus the leading cryptocurrencies. A name that is also an ordinary word needs context: “Attorney General” is not General Motors, and “Washington Post” is not the stock POST.
-
03 · Cleaning
One story, one vote
Ads, price predictions and bots are dropped. Headlines are compared by their rare words and the numbers in them. If 8 outlets run the same story, it counts once, with more weight for the wide coverage.
story weight × (1 + 0.5 × log₂ outlets) → 8 outlets = ×2.5
-
04 · Scoring
An AI model trained on financial text
News is scored with FinBERT from −100 to +100, plus rules for the clear cases: earnings, ratings, “the stock fell X%”. Social posts also go through VADER with about 250 words of finance and crypto slang. SEC filings and macro data are scored by rules: the surprise against the estimate.
score = P(positive) − P(negative) · confidence = 1 − P(neutral)
-
05 · Weight
Who says it and how fresh it is
Major agencies and regulators weigh 1.0, established media 0.65, small sites 0.25. Companies’ own press releases weigh 0.3, because by nature they are upbeat. A news item loses half its weight in 3 hours, a post in 1 hour and an event in 6.
-
06 · The gauge
Four parts, one value
News, social media, events and prices. A part with little data weighs less, so a single headline cannot push the gauge into a strong zone. Finally the sum goes through tanh to stay between −100 and +100. Try it below.
gauge = 100 × tanh(1.8 × Σ weight × confidence × tone ÷ Σ weight)
-
07 · Self-check
Does the mood move ahead of the price?
Every 10 minutes the app takes the last 30 days in non-overlapping 4-hour windows. It counts the cases where the words were at least ±10 and compares how often the price moved that way with chance. A verdict is given only with at least 30 cases, with a 95% interval.
Try it yourself
How the gauge moves
The formula and the weights are the same as in the app. Change the tone and the number of items and see why one headline is not enough and why prices weigh the most.
Freshness
How fast information gets old
Weight of a news item, post or event by hours since publication
Accuracy
Version 0.7 vs 0.8
Tested on 570 real records from 5 to 7 October 2026, labelled by two independent AI raters
version 0.7version 0.8
Technology
What it is built on
- AI models
- FinBERT (ProsusAI) in ONNX, quantised to int8 so it runs fast on an ordinary CPU. VADER with an added finance and emoji lexicon for social posts. An offline translation model for when there is no internet.
- Rules
- SEC filings by type: bankruptcy −90, delisting −60, activist investor +25. Macro data as a surprise against consensus, with direction: a higher CPI is a bad sign, stronger jobs data a good one. Earnings as EPS against the estimate.
- Data
- An SQLite database with the full history. On restart the last 12 hours are loaded back without double counting. Each source’s normal tone tunes itself slowly, and the gauge shows the deviation from it.
- Interface
- A desktop app with PySide6 (Qt), fully in Bulgarian, with a command console and keyboard shortcuts. Packaged as an .exe with PyInstaller, about 300 to 400 MB.
- Network
- Asynchronous requests, a separate polite pace for each site, fallback addresses for every feed and a special client for sites with bot protection.
- Tests
- pytest, 22 files. A separate test on the 570 labelled records blocks any change that makes the scores worse than version 0.8.
Lessons
What I learned
Clean data matters more than the AI model
The first readings were artificially high: +54 instead of +41 for crypto. Duplicate stories and ads were counted as news. The fix was in the cleaning, not in the model.
AI mistakes only show up when you check
FinBERT scored “Why Pagaya Stock Dropped 20%” as good news (+68). So I added rules for the clear cases and a test that catches them.
One story is not ten news items
Strategy’s purchase of 334 BTC was counted in 12 separate groups. After better headline matching there were 3.
Beyond finance
The same system works for your company
Media monitoring for a brand or company, customer opinion, competitor tracking, PR and communications. Anywhere there is a lot of text and you need to see quickly what matters.
An educational project, not investment advice. The app is personal and is not distributed.


