---
title: "Sentiment Analysis"
description: "This page explains how to use Hugging Face sentiment analysis models in LEAN trading algorithms."
canonical: https://www.quantconnect.com/docs/v2/writing-algorithms/machine-learning/hugging-face/popular-models/sentiment-analysis
markdown: https://www.quantconnect.com/docs/v2/writing-algorithms/machine-learning/hugging-face/popular-models/sentiment-analysis.md
language: python
source: https://github.com/QuantConnect/Documentation/tree/master/03%20Writing%20Algorithms/31%20Machine%20Learning/04%20Hugging%20Face/02%20Popular%20Models/06%20Sentiment%20Analysis
modified: 2026-10-31
index: https://www.quantconnect.com/llms.txt
---

# Sentiment Analysis

[Documentation](https://www.quantconnect.com/docs/v2.md) > [Writing Algorithms](https://www.quantconnect.com/docs/v2/writing-algorithms.md) > Machine Learning > Hugging Face > [Popular Models](https://www.quantconnect.com/docs/v2/writing-algorithms/machine-learning/hugging-face/popular-models.md) > Sentiment Analysis

> Code examples are shown in Python. Append `?lang=csharp` to this URL for the C# version of this page.

## Introduction

This page explains how to use Hugging Face sentiment analysis models in LEAN trading algorithms. These models classify financial text into sentiment categories like positive, negative, and neutral. The following models are available:

- [ahmedrachid/FinancialBERT-Sentiment-Analysis](https://huggingface.co/ahmedrachid/FinancialBERT-Sentiment-Analysis) — A BERT model fine-tuned on financial data for sentiment analysis, classifying text as positive, negative, or neutral.
- [bardsai/finance-sentiment-fr-base](https://huggingface.co/bardsai/finance-sentiment-fr-base) — A French-language financial sentiment classification model.
- [cardiffnlp/twitter-roberta-base-sentiment-latest](https://huggingface.co/cardiffnlp/twitter-roberta-base-sentiment-latest) — A RoBERTa model fine-tuned on tweets for sentiment analysis.
- [mrm8488/distilroberta-finetuned-financial-news-sentiment-analysis](https://huggingface.co/mrm8488/distilroberta-finetuned-financial-news-sentiment-analysis) — A DistilRoBERTa model fine-tuned on financial news for sentiment classification.
- [nickmuchi/deberta-v3-base-finetuned-finance-text-classification](https://huggingface.co/nickmuchi/deberta-v3-base-finetuned-finance-text-classification) — A DeBERTa model fine-tuned for financial text classification.
- [nickmuchi/distilroberta-finetuned-financial-text-classification](https://huggingface.co/nickmuchi/distilroberta-finetuned-financial-text-classification) — A DistilRoBERTa model fine-tuned for financial text classification.
- [nickmuchi/sec-bert-finetuned-finance-classification](https://huggingface.co/nickmuchi/sec-bert-finetuned-finance-classification) — A SEC-BERT model fine-tuned for financial document classification.
- [StephanAkkerman/FinTwitBERT-sentiment](https://huggingface.co/StephanAkkerman/FinTwitBERT-sentiment) — A BERT model fine-tuned on financial tweets for sentiment classification.

All of these models accept text input and return classification labels with confidence scores. You can use them with the Hugging Face `transformers` library to analyze the sentiment of financial news and social media posts, then use the results to inform trading decisions.

## Examples

The following examples demonstrate usage of Hugging Face sentiment analysis models.

### Example 1: News Sentiment Trading

The following algorithm selects the most volatile asset at the beginning of each month. It gets the [Tiingo News](https://www.quantconnect.com/datasets/tiingo-news-feed) articles that were released for the asset over the previous 10 days and then feeds them into a sentiment analysis model. It aggregates the sentiment scores of all the news releases. If the aggregated sentiment is positive, it enters a long position for the month. If it's negative, it enters a short position. You can replace the model name with any of the sentiment analysis models listed on the introduction page.

```python
from transformers import pipeline, set_seed

class SentimentAnalysisModelAlgorithm(QCAlgorithm):

    def initialize(self):
        self.set_start_date(2024, 9, 1)
        self.set_end_date(2024, 12, 31)
        self.set_cash(100_000)

        self.universe_settings.resolution = Resolution.DAILY
        self.universe_settings.schedule.on(self.date_rules.month_start("SPY"))
        self._universe = self.add_universe(
            lambda fundamental: [
                self.history(
                    [f.symbol for f in sorted(
                        fundamental, key=lambda f: f.dollar_volume
                    )[-10:]],
                    timedelta(365), Resolution.DAILY
                )['close'].unstack(0).pct_change().iloc[1:].std().idxmax()
            ]
        )

        set_seed(1, True)

        # Load the sentiment analysis pipeline.
        # Replace the model name with any supported sentiment model.
        self._sentiment_pipeline = pipeline(
            "text-classification",
            model="mrm8488/distilroberta-finetuned-financial-news-sentiment-analysis"
        )

        self._last_rebalance_time = datetime.min
        self.set_warm_up(30, Resolution.DAILY)

    def on_warmup_finished(self):
        self._trade()
        self.schedule.on(
            self.date_rules.month_start("SPY", 1),
            self.time_rules.midnight,
            self._trade
        )

    def on_securities_changed(self, changes):
        for security in changes.removed_securities:
            self.remove_security(security.dataset_symbol)
        for security in changes.added_securities:
            security.dataset_symbol = self.add_data(
                TiingoNews, security.symbol
            ).symbol

    def _trade(self):
        if (self.is_warming_up or
            self.time - self._last_rebalance_time < timedelta(14)):
            return

        # Get the target security.
        security = self.securities[list(self._universe.selected)[0]]

        # Get the latest news articles.
        articles = self.history[TiingoNews](
            security.dataset_symbol, 10, Resolution.DAILY
        )
        article_text = [
            article.description for article in articles
            if article.description
        ]
        if not article_text:
            return

        # Run sentiment analysis on each article.
        # Truncate long articles to the model's max length.
        results = self._sentiment_pipeline(
            article_text, truncation=True, max_length=512
        )

        # Aggregate sentiment scores.
        positive_score = 0
        negative_score = 0
        for result in results:
            label = result['label'].lower()
            score = result['score']
            if 'pos' in label:
                positive_score += score
            elif 'neg' in label:
                negative_score += score

        self.plot("Sentiment", "Positive", positive_score)
        self.plot("Sentiment", "Negative", negative_score)

        # Rebalance based on sentiment.
        weight = 1 if positive_score > negative_score else -0.25
        self.set_holdings(
            security.symbol, weight,
            liquidate_existing_holdings=True
        )
        self._last_rebalance_time = self.time
```
