PT-BR Financial Sentiment Analysis

A BERT model fine-tuned for financial sentiment classification of Brazilian Portuguese news. The model is built upon FinBERT-PT-BR and predicts the sentiment conveyed by financial news headlines or short articles related to the Brazilian economy and capital markets.

Given a financial news text, the model assigns one of three sentiment labels:

  • POSITIVE โ€“ news suggesting a favorable impact or outlook for the financial market.
  • NEGATIVE โ€“ news suggesting an unfavorable impact or outlook for the financial market.
  • NEUTRAL โ€“ factual or informational news without a clear positive or negative financial sentiment.

The model was developed as part of an undergraduate thesis investigating whether sentiment indicators extracted from Brazilian financial news can improve quantitative asset allocation strategies for the Brazilian stock market.


Resources

Base model

This model is fine-tuned from FinBERT-PT-BR, developed by Lucas Leme.


Project repository

The complete training pipeline, manually annotated dataset, preprocessing scripts, and experiments used to produce this model are available at:


Dataset

The model was fine-tuned on a manually annotated subset of 624 Brazilian financial news articles sampled from a larger corpus containing approximately 56,000 financial news articles collected between 2016 and 2025.

Split Examples
Training 399
Validation 100
Test 125
Total 624

The train/validation/test split was stratified by sentiment class.

The complete news corpus used as the source for manual annotation is publicly available as the PT-BR Financial News Dataset:


Evaluation

The final ensemble was evaluated once on an independent test set containing 125 manually annotated news articles.

Model Accuracy Macro F1
Base FinBERT-PT-BR 0.336 0.325
Fine-tuned Ensemble 0.784 0.783

Compared to the original model, the fine-tuned ensemble achieved:

  • +44.8 percentage points in Accuracy
  • +45.8 percentage points in Macro-F1

Usage

The repository stores each seed checkpoint in a subfolder. Load one seed with subfolder:

from transformers import AutoTokenizer, BertForSequenceClassification
import torch

model_id = "lucasalmda/pt-br-financial-sentimental-analysis"
seed = "seed-789"  # also available: "seed-123" and "seed-456"

tokenizer = AutoTokenizer.from_pretrained(model_id, subfolder=seed)
model = BertForSequenceClassification.from_pretrained(model_id, subfolder=seed)
model.eval()

id2label = {
    0: "POSITIVE",
    1: "NEGATIVE",
    2: "NEUTRAL",
}

text = "Ibovespa fecha em alta com expectativa de corte na taxa Selic"

inputs = tokenizer(
    text,
    return_tensors="pt",
    truncation=True,
    max_length=512,
)

with torch.no_grad():
    logits = model(**inputs).logits
    prediction = logits.argmax(dim=-1).item()

print(id2label[prediction])

To reproduce the project ensemble, load the three seed subfolders, average the raw logits, and then apply argmax:

from transformers import AutoTokenizer, BertForSequenceClassification
import torch

model_id = "lucasalmda/pt-br-financial-sentimental-analysis"
seeds = ["seed-789", "seed-123", "seed-456"]
text = "Ibovespa fecha em alta com expectativa de corte na taxa Selic"

all_logits = []
for seed in seeds:
    tokenizer = AutoTokenizer.from_pretrained(model_id, subfolder=seed)
    model = BertForSequenceClassification.from_pretrained(model_id, subfolder=seed)
    model.eval()

    inputs = tokenizer(text, return_tensors="pt", truncation=True, max_length=512)
    with torch.no_grad():
        all_logits.append(model(**inputs).logits)

ensemble_logits = torch.stack(all_logits).mean(dim=0)
prediction = ensemble_logits.argmax(dim=-1).item()

print({0: "POSITIVE", 1: "NEGATIVE", 2: "NEUTRAL"}[prediction])
Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. ๐Ÿ™‹ Ask for provider support

Model tree for lucasalmda/pt-br-financial-sentiment-analysis

Finetuned
(8)
this model