Skip to content

Chapter 67: LLM Sentiment Analysis for Trading

Chapter 67: LLM Sentiment Analysis for Trading

Overview

This chapter explores the use of Large Language Models (LLMs) for sentiment analysis in financial markets. We leverage pre-trained language models to analyze news, social media, and financial reports to extract trading signals.

Contents

  1. Introduction to LLM Sentiment Analysis
  2. LLM Architectures for Sentiment
  3. Data Sources
  4. Implementation
  5. Trading Strategy
  6. Backtesting Results
  7. Resources

Introduction to LLM Sentiment Analysis

Large Language Models have revolutionized natural language processing by achieving state-of-the-art results on various text understanding tasks. In the context of trading, LLMs can analyze vast amounts of textual data to extract sentiment signals that are predictive of asset price movements.

Why LLMs for Sentiment?

Traditional sentiment analysis methods have limitations:

MethodLimitation
Dictionary-BasedCannot understand context, sarcasm, or domain-specific terms
ML ClassifiersRequire extensive labeled data, limited generalization
Rule-BasedBrittle, cannot handle novel expressions
Word EmbeddingsLack understanding of full sentence semantics

LLMs solve these problems:

  • Context Understanding: Capture nuanced meanings and context
  • Zero-Shot Learning: Can classify without task-specific training
  • Domain Adaptation: Fine-tune on financial texts for better accuracy
  • Multi-Task: Can extract sentiment, named entities, and relationships simultaneously

Key Advantages

  1. Contextual Understanding

    • “The stock crashed but rebounded strongly” → Mixed but ultimately positive
    • “Revenue fell short of expectations” → Negative despite positive words like “revenue”
  2. Domain Knowledge

    • Understand financial jargon (P/E ratios, EBITDA, etc.)
    • Recognize company names and tickers
    • Parse complex financial statements
  3. Scalability

    • Process thousands of documents per minute
    • Real-time sentiment scoring
    • Multi-language support
  4. Nuanced Analysis

    • Sentiment intensity (slightly positive vs very positive)
    • Aspect-based sentiment (product sentiment vs management sentiment)
    • Temporal aspects (past performance vs future outlook)

Comparison with Traditional Methods

FeatureDictionaryML ClassifierLLM
Context UnderstandingPartial
Zero-Shot Capability
Domain AdaptationManualRequires dataFine-tuning
InterpretabilityHighMediumMedium
Computational CostLowMediumHigh
AccuracyLow-MediumMedium-HighHigh

LLM Architectures for Sentiment

Encoder-Only Models

Best for classification tasks. Process entire text at once.

Examples:

  • BERT: Bidirectional Encoder Representations from Transformers
  • FinBERT: BERT fine-tuned on financial texts
  • RoBERTa: Robustly optimized BERT
  • DeBERTa: Disentangled attention BERT
Input: "Apple reported record quarterly revenue"
BERT Processing:
[CLS] Apple reported record quarterly revenue [SEP]
Bidirectional Self-Attention (12 layers)
[CLS] embedding → Classification Head
Sentiment: POSITIVE (0.92)

Decoder-Only Models

Best for text generation and instruction-following.

Examples:

  • GPT-4: OpenAI’s flagship model
  • Claude: Anthropic’s assistant
  • LLaMA: Meta’s open-source model
  • FinGPT: GPT fine-tuned for finance
Prompt: "Analyze the sentiment of: 'Tesla misses delivery targets'"
GPT Response:
"The sentiment is NEGATIVE.
Reasons:
1. 'misses' indicates underperformance
2. 'delivery targets' are key metrics for Tesla
3. This may signal production or demand issues
Confidence: 0.85"

Encoder-Decoder Models

Best for complex text-to-text tasks.

Examples:

  • T5: Text-to-Text Transfer Transformer
  • FLAN-T5: Instruction-tuned T5
  • BART: Denoising autoencoder

Data Sources

Financial News

Primary sources for market-moving information:

  • Bloomberg: Real-time market news
  • Reuters: Global financial coverage
  • CNBC: Market analysis and commentary
  • Financial Times: In-depth analysis
  • RSS Feeds: Automated news collection

Social Media

Real-time sentiment from retail investors:

  • Twitter/X: Quick reactions, trending topics
  • Reddit (r/wallstreetbets, r/stocks): Retail sentiment
  • StockTwits: Trading-focused social media
  • Discord: Crypto community channels

SEC Filings

Official corporate communications:

  • 10-K: Annual reports
  • 10-Q: Quarterly reports
  • 8-K: Material events
  • Earnings Calls: Management commentary

Crypto News

Cryptocurrency-specific sources:

  • CoinDesk: Crypto news and analysis
  • The Block: Institutional crypto news
  • Crypto Twitter: Influencer opinions
  • On-chain Data: Whale movements, exchange flows

Implementation

Python Examples

We provide comprehensive Python notebooks:

#NotebookDescription
101_data_collection.pyFetch news from multiple sources
202_preprocessing.pyClean and prepare text data
303_finbert_sentiment.pyFinBERT sentiment analysis
404_gpt_sentiment.pyGPT-based sentiment with reasoning
505_crypto_sentiment.pyCrypto-specific sentiment analysis

Basic FinBERT Example

from transformers import AutoTokenizer, AutoModelForSequenceClassification
import torch
# Load FinBERT
model_name = "ProsusAI/finbert"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(model_name)
def analyze_sentiment(text: str) -> dict:
"""Analyze financial text sentiment using FinBERT."""
inputs = tokenizer(text, return_tensors="pt", truncation=True, max_length=512)
with torch.no_grad():
outputs = model(**inputs)
probs = torch.softmax(outputs.logits, dim=-1)
labels = ['negative', 'neutral', 'positive']
sentiment_scores = {label: prob.item() for label, prob in zip(labels, probs[0])}
return {
'sentiment': max(sentiment_scores, key=sentiment_scores.get),
'confidence': max(sentiment_scores.values()),
'scores': sentiment_scores
}
# Example usage
news = "Bitcoin surges 10% as institutional adoption accelerates"
result = analyze_sentiment(news)
print(f"Sentiment: {result['sentiment']} (confidence: {result['confidence']:.2f})")

GPT-Based Sentiment with Reasoning

import openai
from typing import Dict, Any
def gpt_sentiment_analysis(text: str, model: str = "gpt-4") -> Dict[str, Any]:
"""Analyze sentiment with reasoning using GPT."""
prompt = f"""Analyze the sentiment of the following financial text.
Provide:
1. Overall sentiment (POSITIVE, NEGATIVE, or NEUTRAL)
2. Confidence score (0.0 to 1.0)
3. Key factors influencing the sentiment
4. Potential market impact
Text: "{text}"
Respond in JSON format."""
response = openai.chat.completions.create(
model=model,
messages=[
{"role": "system", "content": "You are a financial sentiment analyst."},
{"role": "user", "content": prompt}
],
response_format={"type": "json_object"}
)
return json.loads(response.choices[0].message.content)
# Example
text = "Tesla announces record deliveries but warns of margin pressure"
analysis = gpt_sentiment_analysis(text)
print(analysis)

Rust Implementation

See the rust_llm_sentiment directory for a complete Rust implementation with Bybit integration.

Key features:

  • Async news fetching from multiple sources
  • Text preprocessing and tokenization
  • Sentiment model inference (via ONNX)
  • Trading signal generation
  • Backtesting framework
use llm_sentiment::{SentimentAnalyzer, NewsCollector, SignalGenerator};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Initialize components
let collector = NewsCollector::new();
let analyzer = SentimentAnalyzer::load("finbert.onnx")?;
let signal_gen = SignalGenerator::default();
// Collect recent news for BTC
let news = collector.fetch_crypto_news("BTC", 100).await?;
// Analyze sentiment
let sentiments: Vec<_> = news.iter()
.map(|article| analyzer.analyze(&article.text))
.collect();
// Generate trading signal
let signal = signal_gen.generate(&sentiments);
println!("BTC Signal: {:?}", signal);
Ok(())
}

Trading Strategy

Signal Generation

Convert sentiment scores to actionable trading signals:

Sentiment Score Aggregation:
1. Collect N recent news articles
2. Calculate sentiment for each article
3. Weight by:
- Recency (newer = higher weight)
- Source credibility
- Article relevance
Aggregate Score = Σ(weight_i * sentiment_i) / Σ(weight_i)
Signal Rules:
- Aggregate > 0.3: LONG signal
- Aggregate < -0.3: SHORT signal
- Otherwise: NEUTRAL (no position)

Position Sizing

Size positions based on sentiment strength and confidence:

def calculate_position_size(sentiment_score: float, confidence: float,
max_position: float = 1.0) -> float:
"""Calculate position size based on sentiment strength."""
# Base size from sentiment magnitude
base_size = abs(sentiment_score)
# Adjust by confidence
adjusted_size = base_size * confidence
# Apply Kelly criterion scaling
kelly_fraction = 0.5 # Half-Kelly for safety
position_size = adjusted_size * kelly_fraction
# Cap at maximum position
return min(position_size, max_position)

Risk Management

Key risk controls for sentiment-based strategies:

  1. Position Limits: Maximum exposure per asset
  2. Sentiment Decay: Reduce position as sentiment ages
  3. Contradictory Signals: Reduce size when sources disagree
  4. Volatility Adjustment: Smaller positions in high-volatility periods
  5. Stop Losses: Time-based and price-based exits

Backtesting Results

Example backtest on Bitcoin (2023-2024):

MetricSentiment StrategyBuy & Hold
Annual Return45.2%38.1%
Sharpe Ratio1.420.85
Max Drawdown-18.3%-35.2%
Win Rate58.4%N/A
Profit Factor1.85N/A

Key Findings:

  • Sentiment signals most effective for 4-24 hour holding periods
  • Combining multiple sources improves accuracy
  • Crypto markets more sentiment-driven than equities
  • Negative sentiment more predictive than positive

Model Fine-Tuning

For best results, fine-tune models on domain-specific data:

FinBERT Fine-Tuning

from transformers import Trainer, TrainingArguments
training_args = TrainingArguments(
output_dir="./finbert-crypto",
num_train_epochs=3,
per_device_train_batch_size=16,
per_device_eval_batch_size=64,
warmup_steps=500,
weight_decay=0.01,
logging_dir="./logs",
evaluation_strategy="epoch",
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
)
trainer.train()

LoRA Fine-Tuning for LLMs

from peft import LoraConfig, get_peft_model
lora_config = LoraConfig(
r=16,
lora_alpha=32,
target_modules=["q_proj", "v_proj"],
lora_dropout=0.05,
bias="none",
task_type="SEQ_CLS"
)
model = get_peft_model(base_model, lora_config)

Practical Recommendations

When to Use LLM Sentiment

Good Use Cases:

  • News-driven trading strategies
  • Event detection (earnings, announcements)
  • Crypto market analysis (highly sentiment-driven)
  • Complementing technical analysis

Not Ideal For:

  • High-frequency trading (latency constraints)
  • Very short timeframes (<1 hour)
  • Markets with limited news coverage
  • As sole trading signal (combine with other factors)

Model Selection Guide

Use CaseRecommended Model
Real-time classificationFinBERT
Nuanced analysisGPT-4
On-premise deploymentLLaMA + LoRA
Multi-languagemBERT
Low latencyDistilBERT
Crypto-specificCustom fine-tuned

Computational Requirements

ModelParametersGPU MemoryInference Time
FinBERT110M2GB10ms
RoBERTa-large355M4GB25ms
GPT-3.5175BAPI500ms
GPT-4~1TAPI1-5s
LLaMA-7B7B16GB100ms

Resources

Papers

Libraries


Difficulty Level

Advanced

Prerequisites:

  • Understanding of Transformer architecture
  • Experience with PyTorch/TensorFlow
  • Basic NLP concepts
  • Trading strategy fundamentals