Skip to content
Skip to content
← all research
STUDY

"FinBERT vs alternatives — backtest on Financial PhraseBank v1.0 (50agree)"

2026-08-29

·

Source: Ankur Sinha, Hugging Face financial_phrasebank (50agree subset), 4,846 sentences labeled {positive, neutral, negative} by ≥50% annotator agreement. Downloaded free from https://huggingface.co/datasets/financial_phrasebank/.../FinancialPhraseBank-v1.0.zip into data/finphrase/ (gitignored).

Sample: n=4846 (full set, or --n-rows N to subsample). Caveat: this is the training data ProsusAI/finbert was fine-tuned on, so it's an IN-SAMPLE check — overstates accuracy. A truly out-of-sample test would use FiQA-2018, SemEval-2017 task 5 fine-grained, or Twitter financial sentiment.

#Models compared

ModelSourceTraining data3-classNotes
keyword proxyPOS/NEG listsnone (heuristic)yesused as production fallback
ProsusAI/finbertProsusAI/finbertFinancial PhraseBankyes (3-class)currently wired in production (production/correlation_tracker.py:62)
cardiffnlp/twitter-roberta-base-sentiment-latestCardiff NLPTwitter (general)yes (3-class)general-domain, may generalize beyond finance
finiteautomata/bertweet-base-sentiment-analysisUTAustin CSETwitter (financial-relevant)yes (3-class)Twitter-trained, maps to finance-style headlines
yiyanghkust/finbert-tonebroken on HF (Unrecognized model_type)n/an/askipped (config error)

#Headline (3-class accuracy)

ScorerAccuracyMacro-F1
all-neutral baseline0.5940.248
keyword proxy (POS/NEG lists)0.6310.425
ProsusAI/finbert (3-class)0.8900.883
cardiffnlp/twitter-roberta (3-class)0.6750.575
finiteautomata/bertweet (3-class)0.7070.657

#Direction-only accuracy (positive vs negative, both gold and pred directional)

ScorerDirection accuracyn (both directional)
keyword0.689547
ProsusAI/finbert0.9841870
cardiffnlp0.990701
bertweet0.9921035

Direction matters more than 3-class for the bot (we skip neutrals in the daily panel anyway), so this is the most decision-relevant number.

#Inter-scorer agreement (Cohen's κ; 1.0 = perfect, 0 = chance)

Pairκ
keyword vs ProsusAI/finbert0.176
keyword vs cardiffnlp0.105
keyword vs bertweet0.121
ProsusAI/finbert vs cardiffnlp0.317
ProsusAI/finbert vs bertweet0.450
cardiffnlp vs bertweet0.615

#Confusion matrices (rows = true, cols = predicted)

#Keyword proxy

true \ predpositiveneutralnegative
positive300101251
neutral144268154
negative11940877

#ProsusAI/finbert

true \ predpositiveneutralnegative
positive12558622
neutral2872470122
negative711586

#cardiffnlp/twitter-roberta

true \ predpositiveneutralnegative
positive4688896
neutral248257853
negative1377226

#finiteautomata/bertweet

true \ predpositiveneutralnegative
positive7196377
neutral413239769
negative1295308

#Verdict

  • Best on this set: ProsusAI/finbert (0.890 acc).
  • All transformer models beat the keyword proxy by a wide margin (0.890 / 0.675 / 0.707 vs 0.631). Keep the FinBERT wiring; the keyword proxy is a useful fallback only if transformers/HF Hub is unreachable.

#Limitations

  • In-sample: this dataset trained FinBERT, so the headline accuracy is upward-biased. Real out-of-sample needs FiQA-2018 / SemEval-2017 task 5 / Twitter financial sentiment (also free on HF).
  • Domain: Financial PhraseBank is short earnings-press-release style. Our live input (yfinance headlines) is shorter, noisier, and broader (M&A, macro, CEO changes). The lift on this set may overstate the lift on live data.
  • Inference speed: full 4,846 takes ~3-5 min on CPU with batch 32. Live bot batches 50-name pilot in one pipeline call; on the order of 1-2s per day once the model is loaded (lazy-load, ~440MB cache after first run).

Per-row CSV (label, keyword, finbert, cardiffnlp, bertweet, correct_*): reports/finbert_per_row.csv

All trading described is paper (simulated). Not investment advice.

← all research