An NLI-Based Approach to Asset-Specific Stance Detection in Cryptocurrency Tweets
This model classifies the stance of tweets toward Bitcoin (BTC) and Ethereum (ETH) as Bullish, Bearish, or Neutral using a Natural Language Inference (NLI) approach.
It was fine-tuned from FacebookAI/roberta-large-mnli as part of a master's thesis on NLI-based cryptocurrency stance detection.
How it works
Instead of standard 3-class classification, this model frames stance detection as an entailment task. For each tweet, three hypotheses are constructed (one per stance), and the model scores which hypothesis is most entailed by the tweet:
Stance
Hypothesis
Bullish
"This tweet expresses a bullish perspective on the potential of {target}."
Bearish
"This tweet expresses a bearish perspective on the potential of {target}."
Neutral
"This tweet expresses a neutral perspective on the potential of {target}."
The predicted stance is the one with the highest entailment score.
Usage
python
1from transformers import pipeline
23classifier = pipeline("zero-shot-classification", model="syahrezapratama/roberta-crypto-stance")45tweet ="Bitcoin is going to the moon! $100k is just the beginning 🚀"67result = classifier(8 tweet,9 candidate_labels=["bullish","bearish","neutral"],10 hypothesis_template="This tweet expresses a {} perspective on the potential of BTC.",11)1213print(result["labels"][0])# "bullish"
Manual inference (more control)
python
1from transformers import AutoTokenizer, AutoModelForSequenceClassification
2import torch
34model_name ="syahrezapratama/roberta-crypto-stance"5tokenizer = AutoTokenizer.from_pretrained(model_name)6model = AutoModelForSequenceClassification.from_pretrained(model_name)7model.eval()89tweet ="I'm not sure where ETH is headed, could go either way"10stances =["bullish","bearish","neutral"]11template ="This tweet expresses a {} perspective on the potential of ETH."1213scores =[]14for stance in stances:15 hypothesis = template.format(stance)16 inputs = tokenizer(tweet, hypothesis, return_tensors="pt", truncation=True, max_length=128)17with torch.no_grad():18 logits = model(**inputs).logits
19# Entailment is index 2 for RoBERTa-MNLI20 entailment_score = torch.softmax(logits, dim=-1)[0,2].item()21 scores.append(entailment_score)2223predicted = stances[scores.index(max(scores))]24print(f"Predicted stance: {predicted}")
Performance
Evaluated on a held-out test set of 450 tweets (70/15/15 train/val/test split, seed=42).
Overall metrics
Metric
Value
Accuracy
78.22%
Macro F1
0.7376
Weighted F1
0.7850
Per-class metrics
Class
Precision
Recall
F1
Support
Bearish
0.6522
0.6383
0.6452
47
Neutral
0.8780
0.7941
0.8340
272
Bullish
0.6709
0.8092
0.7336
131
Comparison with baselines
Model
Paradigm
Accuracy
Macro F1
RoBERTa-MNLI
Zero-Shot (Baseline)
46.67%
0.4467
RoBERTa-MNLI
Zero-Shot (OPRO)
55.11%
0.5009
RoBERTa-NLI
Fine-Tuned
78.22%
0.7376
GPT-4o
Zero-Shot
76.67%
0.7275
Training details
Dataset
Source: 3,000 cryptocurrency tweets about BTC and ETH