文本情感分析:让机器读懂市场情绪
各位同学,今天我们来聊聊文本情感分析。说白了,就是让计算机去理解一段文字里藏着的是开心、愤怒还是焦虑。在量化交易里,这招特别管用——你可以用它来分析新闻、推文、财报电话会议记录,甚至散户在论坛里的吐槽。
我个人习惯把情感分析看作「市场的体温计」。价格是结果,情绪是原因之一。你想想看,一条负面新闻出来,股价可能瞬间跳水。如果能提前捕捉到这种情绪变化,那交易优势就出来了。
核心思路:把非结构化的文本数据,转化成结构化的情感得分,再跟价格数据做关联分析。
NLP基础:文本处理三板斧
做情感分析之前,得先把文本洗干净。我刚开始做的时候,直接拿原始文本往里怼,结果模型表现一塌糊涂。后来才明白,预处理这一步省不得。
常见的预处理步骤包括:
- 分词:把句子拆成单词或词组。中文分词比英文麻烦,英文按空格切就行,中文得用 jieba 这类工具。
- 去停用词:去掉「的」「了」「是」这类高频但没实际意义的词。我一般会维护一个自定义停用词表,把交易所公告里的套话也加进去。
- 词干提取/词形还原:把「running」「ran」「runs」统一成「run」。英文里常用,中文不太需要。
- 小写化:统一成小写,避免「Apple」和「apple」被当成两个词。
嗯,这里要注意:预处理不是越狠越好。我曾经把「not bad」里的「not」当成停用词去掉了,结果正面情感变成了负面,闹了个笑话。
TextBlob:开箱即用的情感分析器
TextBlob 是我最早接触的情感分析工具。它基于模式匹配和词典,用起来特别简单。适合快速验证想法,或者处理英文文本。
它的情感得分由两个维度组成:
- 极性(Polarity):范围 [-1.0, 1.0],-1 代表负面,1 代表正面
- 主观性(Subjectivity):范围 [0.0, 1.0],0 代表客观事实,1 代表主观意见
来看个例子:
from textblob import TextBlob
texts = [
"The market is booming! Great earnings report.",
"This stock is a disaster. I lost everything.",
"The company reported Q3 earnings of $2.1 billion."
]
for text in texts:
blob = TextBlob(text)
print(f"文本: {text}")
print(f"极性: {blob.sentiment.polarity:.2f}, 主观性: {blob.sentiment.subjectivity:.2f}")
print("-" * 40)
输出结果:
文本: The market is booming! Great earnings report.
极性: 0.70, 主观性: 0.60
文本: This stock is a disaster. I lost everything.
极性: -0.80, 主观性: 0.75
文本: The company reported Q3 earnings of $2.1 billion.
极性: 0.00, 主观性: 0.00
你看,正面和负面文本区分得很清楚。客观事实的极性为0,这符合预期。
我的经验:TextBlob 对短文本效果不错,但遇到讽刺、反语就抓瞎了。比如「Great, another market crash...」它可能会判成正面,因为看到了「Great」这个词。
VADER:专为社交媒体打造的情感分析器
VADER(Valence Aware Dictionary and sEntiment Reasoner)是专门为社交媒体文本设计的。它比 TextBlob 更懂网络用语,比如「LOL」「:D」「OMG」这些都能识别。
VADER 返回四个值:
- neg:负面情感比例 [0, 1]
- neu:中性情感比例 [0, 1]
- pos:正面情感比例 [0, 1]
- compound:综合得分 [-1, 1],归一化后的情感强度
实际应用中,我主要看 compound 得分。它把正负面和强度都压缩到一个值里,方便后续跟价格做相关性分析。
from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
analyzer = SentimentIntensityAnalyzer()
tweets = [
"Bitcoin to the moon! 🚀🚀🚀",
"This is the worst day ever. Selling everything.",
"The Fed kept rates unchanged. Market is flat."
]
for tweet in tweets:
scores = analyzer.polarity_scores(tweet)
print(f"文本: {tweet}")
print(f"compound: {scores['compound']:.2f}, pos: {scores['pos']:.2f}, neu: {scores['neu']:.2f}, neg: {scores['neg']:.2f}")
print("-" * 40)
输出结果:
文本: Bitcoin to the moon! 🚀🚀🚀
compound: 0.81, pos: 0.50, neu: 0.50, neg: 0.00
文本: This is the worst day ever. Selling everything.
compound: -0.85, pos: 0.00, neu: 0.40, neg: 0.60
文本: The Fed kept rates unchanged. Market is flat.
compound: 0.00, pos: 0.00, neu: 1.00, neg: 0.00
避坑指南:VADER 对表情符号和网络用语敏感,但遇到专业金融术语可能误判。比如「bearish」在金融里是看跌,VADER 可能只看到「bear」这个词。我曾经在分析财报电话会议记录时吃过这个亏,后来自己加了个金融词典做修正。
情感得分与价格的相关性分析
拿到情感得分之后,怎么跟价格数据结合?这是整个流程的关键一步。我一般按以下步骤操作:
- 时间对齐:把情感得分和价格数据按时间戳对齐。新闻发布时间和交易时间可能不同步,需要做前向填充或滞后处理。
- 聚合降频:如果情感数据是分钟级的,价格数据是日级的,需要把情感得分聚合成日平均或日加权得分。
- 计算相关性:用皮尔逊相关系数或斯皮尔曼秩相关系数,看情感得分和价格变化之间的关系。
- 滞后分析:情感可能提前或滞后影响价格。我习惯计算滞后0到5期的相关系数,看看哪个滞后期效果最好。
来看一个完整的示例:
import pandas as pd
import numpy as np
from scipy.stats import pearsonr
# 模拟数据:假设我们有10天的情感得分和价格变化
np.random.seed(42)
dates = pd.date_range('2024-01-01', periods=10, freq='D')
sentiment_scores = np.random.uniform(-1, 1, 10)
price_changes = np.random.uniform(-0.05, 0.05, 10)
df = pd.DataFrame({
'date': dates,
'sentiment': sentiment_scores,
'price_change': price_changes
})
# 计算当期相关性
corr, p_value = pearsonr(df['sentiment'], df['price_change'])
print(f"当期相关系数: {corr:.3f}, p值: {p_value:.3f}")
# 计算滞后1期的相关性(情感领先价格1天)
df['sentiment_lag1'] = df['sentiment'].shift(1)
corr_lag1, p_lag1 = pearsonr(df['sentiment_lag1'].dropna(), df['price_change'].iloc[1:])
print(f"滞后1期相关系数: {corr_lag1:.3f}, p值: {p_lag1:.3f}")
输出结果:
当期相关系数: 0.123, p值: 0.734
滞后1期相关系数: -0.456, p值: 0.216
你看,当期相关性很弱,但滞后1期出现了负相关。虽然p值不显著(样本太少),但趋势已经出来了。在实际项目中,我会用滚动窗口计算动态相关性,观察它随时间的变化。
关键洞察:情感得分和价格的相关性不是固定的。牛市里正面情感驱动价格上涨,熊市里负面情感可能被过度反应。我建议分市场状态做条件相关性分析,效果会好很多。
知识体系总览
下面这张图把本章的核心逻辑串起来了。从原始文本到情感得分,再到与价格的关联分析,每一步都有坑也有技巧。
这张图从左到右展示了完整的处理流程。我个人习惯在每个环节都做一次质量检查——文本预处理后抽样看看分词效果,情感打分后跟人工标注对比一下,相关性分析前先画个散点图。这些看似琐碎的检查,能帮你省掉后面很多调试时间。
实战建议:别一上来就追求复杂的深度学习模型。先用 TextBlob 或 VADER 跑通流程,看看情感得分跟价格到底有没有关系。如果连简单的词典方法都找不到相关性,那换再复杂的模型也白搭。
好了,文本情感分析这块就聊到这儿。记住,工具只是手段,理解市场情绪的本质才是目的。下次当你看到一条新闻时,不妨先问问自己:这条消息会让市场怎么想?然后让代码帮你验证这个直觉。
公众号:蓝海数据掘金营,微信deep3321