Разработка системы sentiment analysis крипторынка
Крипторынок уникально чувствителен к настроениям: твит Илона Маска двигал цены на 20–30%. Система анализа настроений агрегирует сигналы из социальных сетей, новостей и on-chain данных, формируя количественную метрику рыночного sentiment.
Источники данных
Twitter/X: реальное время, высокая активность крипто-сообщества. Hashtags: #BTC, #Bitcoin, #Crypto, #Ethereum. Twitter API v2 Basic tier: 500k tweets/month. Filtering по engagement (retweets > 10, likes > 50) снижает шум.
Reddit: r/CryptoCurrency (3M+ членов), r/Bitcoin, r/ethfinance. Pushshift API или официальный Reddit API. Комментарии с высоким upvote особенно информативны.
Telegram: крупные крипто-каналы (часто закрытые). Telethon (Python) для парсинга публичных каналов. Требует аккаунт и осторожное использование согласно ToS.
Новостные источники: CoinDesk, Cointelegraph, Decrypt, Bloomberg Crypto. RSS фиды + scraping. NewsAPI для агрегации.
On-chain sentiment: SOPR > 1 (profit-taking), whale movements, exchange flows — объективные данные, не подверженные манипуляции.
NLP Pipeline
from transformers import pipeline, AutoTokenizer, AutoModelForSequenceClassification
class CryptoSentimentAnalyzer:
def __init__(self, model_name='ProsusAI/finbert'):
self.tokenizer = AutoTokenizer.from_pretrained(model_name)
self.model = AutoModelForSequenceClassification.from_pretrained(model_name)
self.pipeline = pipeline(
'sentiment-analysis',
model=self.model,
tokenizer=self.tokenizer,
device=0 # GPU
)
def analyze_batch(self, texts, batch_size=32):
results = []
for i in range(0, len(texts), batch_size):
batch = texts[i:i+batch_size]
# Обрезаем до 512 токенов
truncated = [t[:512] for t in batch]
batch_results = self.pipeline(truncated)
results.extend(batch_results)
return results
def get_sentiment_score(self, text):
result = self.pipeline(text[:512])[0]
# Конвертируем в скалярный score [-1, 1]
label = result['label']
score = result['score']
if label == 'positive':
return score
elif label == 'negative':
return -score
return 0 # neutral
Модели для финансового sentiment:
- FinBERT (ProsusAI): обучен на финансовых текстах. Лучший general-purpose baseline.
- CryptoBERT: fine-tuned специально на крипто-контенте. Понимает «hodl», «wen lambo», «rekt».
- RoBERTa-large: более мощная базовая модель, требует fine-tuning.
Fine-tuning на крипто-данных
Labelling стратегия: берём исторические твиты за день t, если цена выросла на следующий день > 1% → positive, упала > 1% → negative, иначе neutral.
from transformers import TrainingArguments, Trainer
from datasets import Dataset
def fine_tune_crypto_sentiment(base_model, train_texts, train_labels):
training_args = TrainingArguments(
output_dir='./crypto_sentiment_model',
num_train_epochs=3,
per_device_train_batch_size=32,
warmup_steps=200,
weight_decay=0.01,
learning_rate=2e-5,
eval_strategy='steps',
eval_steps=500,
save_strategy='best',
load_best_model_at_end=True
)
trainer = Trainer(
model=base_model,
args=training_args,
train_dataset=train_dataset,
eval_dataset=eval_dataset
)
trainer.train()
Агрегация sentiment сигналов
Отдельный твит — шумный сигнал. Агрегация по времени дает более надёжную метрику:
def aggregate_sentiment(sentiment_scores, weights, window='1h'):
"""
sentiment_scores: DataFrame с колонками (timestamp, score, source, engagement)
weights: {source: weight} — разные источники имеют разные веса
"""
df = sentiment_scores.copy()
df['weighted_score'] = df.apply(
lambda row: row['score'] * weights.get(row['source'], 1.0) *
np.log1p(row['engagement']), # взвешиваем по engagement
axis=1
)
# Rolling aggregation
hourly = df.set_index('timestamp').resample(window)
aggregated = hourly['weighted_score'].sum() / hourly['engagement'].sum()
# Нормализуем к [-1, 1] через rolling z-score
rolling_mean = aggregated.rolling(168).mean() # 7 дней
rolling_std = aggregated.rolling(168).std()
normalized = (aggregated - rolling_mean) / (rolling_std + 1e-8)
return normalized.clip(-3, 3) / 3 # [-1, 1]
Composite Sentiment Index
Финальный индекс объединяет несколько источников:
SENTIMENT_WEIGHTS = {
'twitter': 0.25,
'reddit': 0.20,
'news': 0.20,
'on_chain_sopr': 0.15,
'funding_rate': 0.10,
'fear_greed': 0.10
}
def compute_composite_index(signals):
total_weight = sum(SENTIMENT_WEIGHTS[s] for s in signals if s in SENTIMENT_WEIGHTS)
composite = sum(
signals[s] * SENTIMENT_WEIGHTS[s]
for s in signals
if s in SENTIMENT_WEIGHTS
) / total_weight
return composite
Корреляционный анализ
Исторический анализ показывает корреляцию sentiment → price с лагом 0–24 часа. Кросс-корреляция:
from scipy.signal import correlate
def cross_correlation_lag(sentiment, price_returns, max_lag_hours=48):
correlation = correlate(price_returns, sentiment, mode='full')
lags = np.arange(-max_lag_hours, max_lag_hours + 1)
max_corr_idx = correlation[len(sentiment)-max_lag_hours-1:len(sentiment)+max_lag_hours].argmax()
optimal_lag = lags[max_corr_idx]
return optimal_lag, correlation.max()
Dashboard и алерты
Realtime Sentiment Dashboard:
- Текущий composite sentiment score (0–100 gauge)
- Breakdown по источникам
- Trend последних 24h/7d
- Топ-10 трендинговых токенов по sentiment
Алерты на аномалии:
- Sentiment > 2σ от среднего (очень позитивный или негативный)
- Резкое изменение > 0.5 за 1 час
- Divergence: sentiment растёт, цена падает (или наоборот)
Технический стек: Python (transformers, torch), PostgreSQL для хранения scores, Redis для кеширования последних значений, Celery для scheduled задач сбора данных, React dashboard, Grafana для метрик системы.
Разрабатываем полноценную систему sentiment analysis: data collection pipelines для нескольких источников, FinBERT + fine-tuning, агрегацию в composite index, realtime dashboard и исторический анализ корреляции с ценовыми движениями.







