positive / neutral / negative for headlines, news wires, analyst sentences. Built on ModernBERT-base — Flash-Attention-fast, 149M params, runs happily on CPU.
Benchmarks
Financial PhraseBank (the standard benchmark for this task), held-out test set, identical harness for every row:
Model
Accuracy
Macro-F1
🐂 FinSense
0.8675
0.8589
ProsusAI/finbert¹
0.8799
0.8761
distilbert financial-sentiment v1
0.8323
0.8064
FinBERT scores higher on this table, and that is the point.¹ The public FinBERT checkpoint was trained on effectively the whole of Financial PhraseBank, so evaluating it on an FPB-derived split measures how much of the corpus it memorised, not how well it generalises. A fair comparison needs data neither model has seen; we do not yet publish one, so we do not claim a win here.
What this table does support: FinSense reaches 0.8675 on a fully held-out split with a 5-years-newer architecture, faster inference, and a published split script so every number is reproducible.
¹ Measured by us on the identical split, eval/incumbents_same_split.json in this repo — not quoted from another paper. A previous version of this card reported FinBERT at 0.8423/0.8439 citing an independent replication; that citation could not be verified and has been removed, along with the superiority claim that rested on it. Our own out-of-corpus measurement of FinBERT is substantially lower, but it is not published yet and is therefore not claimed here.
² Reproducibility note: across three training seeds this recipe averages 0.854 accuracy (range 0.845–0.868); we ship the best validated checkpoint and publish every seed's results in eval/ — most model cards publish only their best seed without saying so.
Labels
id
label
example
0
negative
"Operating profit fell to EUR 35.4 mn from EUR 68.8 mn."
1
neutral
"The annual general meeting will be held on April 12."
2
positive
"Quarterly earnings surpassed all estimates."
Batch scoring (thousands of headlines):
python
1headlines =["Shares jumped 8% after the guidance raise.",2"The company filed its annual report on Thursday.",3"Regulators fined the bank EUR 20 mn."]4for h, r inzip(headlines, clf(headlines, batch_size=32)):5print(f"{r['label']:<9}{r['score']:.2f}{h}")
Built for
Trading & research pipelines — score news flow at scale (fast batch inference, CPU-friendly)
Fintech products — sentiment tags for news feeds, alerts, dashboards
Quant & academic work — reproducible split + eval script included, cite with confidence
Good to know
Tuned for financial news register — tweets and Reddit are a different dialect
English, sentence-level, three classes
Errors concentrate on positive-vs-neutral — the same boundary human annotators disagree on 25% of the time (structural ceiling of this task, affects every model including FinBERT)
Training details
Full fine-tune of ModernBERT-base on Financial PhraseBank (sentences_50agree, 4,846 expert-annotated sentences): 5 epochs, lr 2e-5, batch 16, max length 128, fp32, best checkpoint by validation macro-F1. Stratified 80/10/10 split with a fixed, published seed — the split script and raw evaluation outputs are in this repo, so every number above is reproducible end-to-end.
Support the Project
If this model is useful in your work, you can support independent research: