Can an AI read the news and call the stock? We're testing it — live.
Twice every trading day a machine collects US-stock headlines, has three language models judge each one — YES, NO, or UNKNOWN — and records everything raw. A forward, out-of-sample replication of Lopez-Lira & Tang (2023).
The paper: “Can ChatGPT Forecast Stock Price Movements?”, arXiv 2304.07619 · paper ledger only, no real trades.
Morning round completed 2026-06-17 at 8:00 AM ET (on time) · 722 articles · 673 judged · database committed 9:11 AM ET.
Rounds fire 8:00 AM & 2:30 PM ET, every trading day
How a round works
Live numbers from the latest round — morning round · Jun 17, fired Jun 17, 8:00 AM ET. Every step expands.
01 The clock fires Two rounds every trading day — morning for overnight and pre-market news, afternoon for trading-day news. Never early; late is allowed and recorded; never twice. fired 8:00 AM ETon time
Morning round — fires 8:00 AM ET, judges P3 (published after 4pm yesterday) + P1 (published before 6am today). Decisions feed today's 9:30 OPEN (orders by 9:28); collection window: since yesterday 14:30 ET.
Afternoon round — fires 2:30 PM ET, judges P2 (published 6am–4pm today). Decisions feed today's 16:00 CLOSE (orders by 15:58); collection window: since today 06:00 ET.
An early round would truncate its window and silently miss news, so the gate forbids it. A late round still collects everything published before its target — the slip is recorded in the run ledger, and the analysis judges each day's fidelity. Schedule and gate: src/chatpredict/schedule.py
02 Collect the news Market-wide feeds plus hot-list look-ups, pulled in parallel. The publish time is the law. 899articles fetched
Market-wide feeds deliver ticker-tagged articles for the whole US market at once:
“What's hot” lists name stocks that should have news today — 73 stocks were flagged this round (every one recorded, including those where we then found nothing):
Targeted look-ups then query flagged stocks the feeds didn't cover:
Pipeline declared once in src/chatpredict/flow.py — the runner builds from it and this page renders it, so the diagram cannot drift from what runs.
03 Keep what qualifies Exact ticker matches against 5,842 US common stocks; everything else is dropped and the reason logged. 722articles kept722 = 682 + 40
An article is kept only if it maps to exactly one US common stock — via the source's own ticker tag, an official SEC identifier, or an explicit ticker in the text. We never fuzzy-match company names; that is how news ends up filed under the wrong company. Every rejected article is stored in the drop log with its reason — “no record” never means “quietly discarded”.
| dropped | reason | meaning |
|---|---|---|
| 153 | out of universe | not a US common stock in our universe |
| 24 | no ticker | no exact stock could be identified |
Resolution: src/chatpredict/resolver.py
04 Three models judge every headline The paper's exact question, word for word, at temperature 0 — YES, NO, or UNKNOWN. 673headlines judged
Each (stock × headline) is judged once per model, ever — at temperature 0 a re-ask returns the same answer. A rate-capped or failed model is retried next round; one that answered is never re-asked. The free models are paced to their providers' limits, which is why a round takes about 80 minutes — the panel runs in parallel, so the wall-clock is the slowest model. Tallies below are this round's.
Clients and pacing: src/chatpredict/model_clients.py
05 Everything stored raw Verdicts, drops, no-news checks — all of it. The strategy is computed later, as an analysis over a complete record. 2,019verdict rows
A verdict row keeps the model's raw reply verbatim alongside the parsed answer, the relevance tag, and a status (ok / failed / rate-capped) — so every gap is explainable. Articles keep their raw source payloads; flagged-but-newsless stocks are recorded too. UNKNOWN and not-relevant answers are kept like everything else: no-signal is also a result. Nothing is filtered live.
06 Committed to the record The database is committed to a git repository — append-only history, every change timestamped. 9:11 AM ETcommitted
After every round the SQLite file is committed back to the repository — simultaneously the store, the backup, and the audit trail. If new code lands mid-round, the save step rebases and retries; if saving still fails, the data is parked as a downloadable artifact. This site is regenerated from that file on every commit and has no write access to anything. See the run ledger.
What the models said today
Where at least two models agreed on a relevant headline — 185 stocks:
from the verdicts × articles of Jun 17's 1 round — full table on News & Verdicts