Глава 67: Анализ настроений с помощью LLM для трейдинга
Эта глава посвящена использованию больших языковых моделей (LLM) для анализа настроений на финансовых рынках. Мы используем предобученные языковые модели для анализа новостей, социальных сетей и финансовых отчётов с целью извлечения торговых сигналов.
Содержание
- Введение в анализ настроений с LLM
- Архитектуры LLM для анализа настроений
- Источники данных
- Реализация
- Торговая стратегия
- Результаты бэктестинга
- Ресурсы
Введение в анализ настроений с LLM
Большие языковые модели произвели революцию в обработке естественного языка, достигнув передовых результатов в различных задачах понимания текста. В контексте трейдинга LLM могут анализировать огромные объёмы текстовых данных для извлечения сигналов настроений, которые предсказывают движения цен активов.
Почему LLM для анализа настроений?
Традиционные методы анализа настроений имеют ограничения:
| Метод | Ограничение |
|---|---|
| Словарный | Не понимает контекст, сарказм или специфические термины |
| ML-классификаторы | Требуют много размеченных данных, ограниченная генерализация |
| Правила | Хрупкие, не справляются с новыми выражениями |
| Word Embeddings | Не понимают полную семантику предложения |
LLM решают эти проблемы:
- Понимание контекста: Улавливают нюансы и контекст
- Zero-Shot обучение: Могут классифицировать без специфичного обучения
- Адаптация к домену: Дообучение на финансовых текстах для лучшей точности
- Многозадачность: Извлечение настроений, сущностей и связей одновременно
Ключевые преимущества
-
Контекстное понимание
- “Акции упали, но затем резко восстановились” → Смешанное, но в итоге позитивное
- “Выручка не оправдала ожиданий” → Негативное, несмотря на позитивное слово “выручка”
-
Доменные знания
- Понимание финансового жаргона (P/E, EBITDA и т.д.)
- Распознавание названий компаний и тикеров
- Парсинг сложных финансовых отчётов
-
Масштабируемость
- Обработка тысяч документов в минуту
- Оценка настроений в реальном времени
- Поддержка многих языков
-
Нюансированный анализ
- Интенсивность настроения (слегка позитивное vs очень позитивное)
- Аспектный анализ (настроение к продукту vs к менеджменту)
- Временные аспекты (прошлые результаты vs будущие перспективы)
Сравнение с традиционными методами
| Характеристика | Словарный | ML-классификатор | LLM |
|---|---|---|---|
| Понимание контекста | ✗ | Частично | ✓ |
| Zero-Shot способность | ✗ | ✗ | ✓ |
| Адаптация к домену | Вручную | Нужны данные | Дообучение |
| Интерпретируемость | Высокая | Средняя | Средняя |
| Вычислительная стоимость | Низкая | Средняя | Высокая |
| Точность | Низкая-Средняя | Средняя-Высокая | Высокая |
Архитектуры LLM для анализа настроений
Encoder-only модели
Лучше всего подходят для задач классификации. Обрабатывают весь текст сразу.
Примеры:
- BERT: Bidirectional Encoder Representations from Transformers
- FinBERT: BERT, дообученный на финансовых текстах
- RoBERTa: Оптимизированный BERT
- DeBERTa: BERT с раздельным вниманием
Вход: "Apple сообщила о рекордной квартальной выручке"
Обработка BERT:[CLS] Apple сообщила о рекордной квартальной выручке [SEP] ↓Двунаправленное Self-Attention (12 слоёв) ↓[CLS] эмбеддинг → Классификационная голова ↓Настроение: ПОЗИТИВНОЕ (0.92)Decoder-only модели
Лучше всего для генерации текста и следования инструкциям.
Примеры:
- GPT-4: Флагманская модель OpenAI
- Claude: Ассистент от Anthropic
- LLaMA: Open-source модель от Meta
- FinGPT: GPT, дообученный для финансов
Промпт: "Проанализируй настроение: 'Tesla не выполнила план по поставкам'"
Ответ GPT:"Настроение НЕГАТИВНОЕ.Причины:1. 'не выполнила' указывает на недостижение целей2. 'план по поставкам' — ключевая метрика для Tesla3. Это может сигнализировать о проблемах с производством или спросомУверенность: 0.85"Encoder-Decoder модели
Лучше для сложных задач преобразования текста.
Примеры:
- T5: Text-to-Text Transfer Transformer
- FLAN-T5: T5 с инструкционным обучением
- BART: Автоэнкодер с шумоподавлением
Источники данных
Финансовые новости
Основные источники рыночной информации:
- Bloomberg: Новости рынков в реальном времени
- Reuters: Глобальное финансовое покрытие
- CNBC: Анализ и комментарии рынка
- Financial Times: Глубокий анализ
- RSS-ленты: Автоматический сбор новостей
Социальные сети
Настроения розничных инвесторов в реальном времени:
- Twitter/X: Быстрые реакции, трендовые темы
- Reddit (r/wallstreetbets, r/stocks): Настроения розницы
- StockTwits: Социальная сеть для трейдеров
- Discord: Каналы крипто-сообществ
SEC-отчётность
Официальные корпоративные коммуникации:
- 10-K: Годовые отчёты
- 10-Q: Квартальные отчёты
- 8-K: Существенные события
- Звонки о доходах: Комментарии менеджмента
Крипто-новости
Источники, специфичные для криптовалют:
- CoinDesk: Крипто-новости и аналитика
- The Block: Институциональные крипто-новости
- Крипто-Twitter: Мнения инфлюенсеров
- On-chain данные: Движения китов, потоки бирж
Реализация
Примеры на Python
Мы предоставляем комплексные Python-скрипты:
| # | Файл | Описание |
|---|---|---|
| 1 | 01_data_collection.py | Сбор новостей из множества источников |
| 2 | 02_preprocessing.py | Очистка и подготовка текстовых данных |
| 3 | 03_finbert_sentiment.py | Анализ настроений с FinBERT |
| 4 | 04_gpt_sentiment.py | Анализ на GPT с обоснованием |
| 5 | 05_crypto_sentiment.py | Крипто-специфичный анализ настроений |
| 6 | 06_signal_generation.py | Преобразование настроений в торговые сигналы |
| 7 | 07_backtesting.py | Бэктестинг стратегий на настроениях |
| 8 | 08_comparison.py | Сравнение с базовыми стратегиями |
Базовый пример с FinBERT
from transformers import AutoTokenizer, AutoModelForSequenceClassificationimport torch
# Загрузка FinBERTmodel_name = "ProsusAI/finbert"tokenizer = AutoTokenizer.from_pretrained(model_name)model = AutoModelForSequenceClassification.from_pretrained(model_name)
def analyze_sentiment(text: str) -> dict: """Анализ настроения финансового текста с помощью 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 }
# Пример использованияnews = "Bitcoin вырос на 10% на фоне ускорения институционального принятия"result = analyze_sentiment(news)print(f"Настроение: {result['sentiment']} (уверенность: {result['confidence']:.2f})")Анализ настроений на GPT с обоснованием
import openaifrom typing import Dict, Any
def gpt_sentiment_analysis(text: str, model: str = "gpt-4") -> Dict[str, Any]: """Анализ настроений с обоснованием через GPT."""
prompt = f"""Проанализируй настроение следующего финансового текста.Укажи:1. Общее настроение (ПОЗИТИВНОЕ, НЕГАТИВНОЕ или НЕЙТРАЛЬНОЕ)2. Уровень уверенности (от 0.0 до 1.0)3. Ключевые факторы, влияющие на настроение4. Потенциальное влияние на рынок
Текст: "{text}"
Ответь в формате JSON."""
response = openai.chat.completions.create( model=model, messages=[ {"role": "system", "content": "Ты — финансовый аналитик настроений."}, {"role": "user", "content": prompt} ], response_format={"type": "json_object"} )
return json.loads(response.choices[0].message.content)
# Примерtext = "Tesla объявила о рекордных поставках, но предупредила о давлении на маржу"analysis = gpt_sentiment_analysis(text)print(analysis)Реализация на Rust
См. директорию rust_llm_sentiment для полной реализации на Rust с интеграцией Bybit.
Ключевые возможности:
- Асинхронный сбор новостей из множества источников
- Предобработка и токенизация текста
- Инференс модели настроений (через ONNX)
- Генерация торговых сигналов
- Фреймворк бэктестинга
use llm_sentiment::{SentimentAnalyzer, NewsCollector, SignalGenerator};
#[tokio::main]async fn main() -> Result<(), Box<dyn std::error::Error>> { // Инициализация компонентов let collector = NewsCollector::new(); let analyzer = SentimentAnalyzer::load("finbert.onnx")?; let signal_gen = SignalGenerator::default();
// Сбор свежих новостей по BTC let news = collector.fetch_crypto_news("BTC", 100).await?;
// Анализ настроений let sentiments: Vec<_> = news.iter() .map(|article| analyzer.analyze(&article.text)) .collect();
// Генерация торгового сигнала let signal = signal_gen.generate(&sentiments);
println!("Сигнал BTC: {:?}", signal);
Ok(())}Торговая стратегия
Генерация сигналов
Преобразование оценок настроений в торговые сигналы:
Агрегация оценок настроений:1. Собрать N последних новостных статей2. Рассчитать настроение для каждой статьи3. Взвесить по: - Свежести (новее = выше вес) - Авторитетности источника - Релевантности статьи
Агрегированная оценка = Σ(weight_i * sentiment_i) / Σ(weight_i)
Правила сигналов:- Агрегат > 0.3: Сигнал LONG- Агрегат < -0.3: Сигнал SHORT- Иначе: НЕЙТРАЛЬНЫЙ (нет позиции)Размер позиции
Размер позиции на основе силы настроения и уверенности:
def calculate_position_size(sentiment_score: float, confidence: float, max_position: float = 1.0) -> float: """Расчёт размера позиции на основе силы настроения."""
# Базовый размер от величины настроения base_size = abs(sentiment_score)
# Корректировка по уверенности adjusted_size = base_size * confidence
# Применение критерия Келли kelly_fraction = 0.5 # Half-Kelly для безопасности position_size = adjusted_size * kelly_fraction
# Ограничение максимальной позицией return min(position_size, max_position)Управление рисками
Ключевые меры контроля риска для стратегий на настроениях:
- Лимиты позиций: Максимальная экспозиция на актив
- Затухание настроения: Уменьшение позиции по мере старения настроения
- Противоречивые сигналы: Уменьшение размера при несогласии источников
- Корректировка на волатильность: Меньшие позиции в периоды высокой волатильности
- Стоп-лоссы: Выходы по времени и по цене
Результаты бэктестинга
Пример бэктеста на Bitcoin (2023-2024):
| Метрика | Стратегия на настроениях | Buy & Hold |
|---|---|---|
| Годовая доходность | 45.2% | 38.1% |
| Коэффициент Шарпа | 1.42 | 0.85 |
| Максимальная просадка | -18.3% | -35.2% |
| Процент выигрышей | 58.4% | N/A |
| Profit Factor | 1.85 | N/A |
Ключевые выводы:
- Сигналы настроений наиболее эффективны для удержания 4-24 часа
- Комбинирование нескольких источников повышает точность
- Крипто-рынки более чувствительны к настроениям, чем акции
- Негативные настроения более предсказательны, чем позитивные
Дообучение моделей
Для лучших результатов дообучайте модели на специфичных данных:
Дообучение FinBERT
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-дообучение для LLM
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)Практические рекомендации
Когда использовать LLM для настроений
Хорошие кейсы:
- Стратегии, основанные на новостях
- Детекция событий (отчётности, объявления)
- Анализ крипто-рынков (высокая чувствительность к настроениям)
- Дополнение технического анализа
Не идеально для:
- Высокочастотной торговли (ограничения по задержке)
- Очень коротких таймфреймов (<1 час)
- Рынков с ограниченным новостным покрытием
- В качестве единственного сигнала (комбинируйте с другими факторами)
Руководство по выбору модели
| Кейс | Рекомендуемая модель |
|---|---|
| Классификация в реальном времени | FinBERT |
| Нюансированный анализ | GPT-4 |
| Локальное развёртывание | LLaMA + LoRA |
| Много языков | mBERT |
| Низкая задержка | DistilBERT |
| Крипто-специфика | Кастомная дообученная |
Вычислительные требования
| Модель | Параметры | GPU-память | Время инференса |
|---|---|---|---|
| FinBERT | 110M | 2GB | 10ms |
| RoBERTa-large | 355M | 4GB | 25ms |
| GPT-3.5 | 175B | API | 500ms |
| GPT-4 | ~1T | API | 1-5s |
| LLaMA-7B | 7B | 16GB | 100ms |
Ресурсы
Статьи
- FinBERT: Financial Sentiment Analysis with Pre-trained Language Models - Araci, 2019
- Sentiment Trading with Large Language Models - 2024
- ChatGPT and Corporate Policies - 2023
- Can ChatGPT Forecast Stock Price Movements? - 2023
Библиотеки
- Hugging Face Transformers
- FinBERT
- LangChain — фреймворк для LLM-приложений
- ONNX Runtime — быстрый инференс
Связанные главы
- Глава 14: Работа с текстовыми данными — предобработка текста
- Глава 15: Тематическое моделирование — анализ документов
- Глава 16: Word Embeddings — представления текста
- Глава 61: FinGPT — финансовые LLM
- Глава 241: FinBERT — BERT для финансов
Уровень сложности
Продвинутый
Требуется:
- Понимание архитектуры Transformer
- Опыт работы с PyTorch/TensorFlow
- Базовые концепции NLP
- Основы торговых стратегий