Розроблення системи аналізу настроїв крипто-ринку
Крипто-ринок унікально чутливий до настроїв: твіт Ілона Маска рухав ціни на 20–30%. Система аналізу настроїв агрегує сигнали зі соціальних мереж, новин та on-chain даних, формуючи кількісну метрику ринкового настрою.
Джерела даних
Twitter/X: реальний час, висока активність крипто-спільноти. Хеш-теги: #BTC, #Bitcoin, #Crypto, #Ethereum. Twitter API v2 Basic tier: 500k твітів/місяць. Фільтрація за залученням (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 потоки + скрейпинг. NewsAPI для агрегації.
On-chain настрій: SOPR > 1 (profit-taking), рухи китів, потоки біржі — об'єктивні дані, не схильні до маніпуляцій.
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
Моделі для фінансового настрою:
- FinBERT (ProsusAI): навчена на фінансових текстах. Кращий général-purpose baseline.
- CryptoBERT: спеціально fine-tuned на крипто-контенті. Розуміє "hodl", "wen lambo", "rekt".
- RoBERTa-large: потужніша базова модель, потребує fine-tuning.
Fine-tuning на крипто-даних
Стратегія розмітки: беремо історичні твіти дня t, якщо ціна виросла наступного дня > 1% → позитивна, впала > 1% → негативна, інакше 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()
Агрегація сигналів настрою
Одиничний твіт — шумний сигнал. Агрегація за часом дає надійнішу метрику:
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']), # вважуємо за залученням
axis=1
)
# Ковзна агрегація
hourly = df.set_index('timestamp').resample(window)
aggregated = hourly['weighted_score'].sum() / hourly['engagement'].sum()
# Нормалізуємо до [-1, 1] через ковзну 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]
Композитний індекс настрою
Фінальний індекс поєднує кілька джерел:
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()
Дашборд та алерти
Realtime дашборд настроїв:
- Поточний композитний score настрою (0–100 gauge)
- Розбір за джерелами
- Тренд останні 24h/7d
- Топ-10 трендових токенів за настроєм
Алерти на аномалії:
- Sentiment > 2σ від середнього (дуже позитивна або негативна)
- Різкі зміни > 0.5 за 1 годину
- Розбіжність: настрій зростає, ціна падає (або навпаки)
Tech стек: Python (transformers, torch), PostgreSQL для зберігання scores, Redis для кешування останніх значень, Celery для запланованих завдань збору даних, React дашборд, Grafana для метрик системи.
Розроблення повної системи аналізу настроїв: pipelines збору даних з кількох джерел, FinBERT + fine-tuning, агрегація у композитний індекс, realtime дашборд та історичний аналіз кореляції з цінними рухами.







