第四章:文本因子挖掘:NLP基础与情感分析实战

各位同学,欢迎来到文本因子挖掘这一章。

说实话,做量化这些年,我见过太多人只盯着价格和成交量。但你知道吗?真正的好机会,往往藏在新闻里、公告里、甚至社交媒体里。文本数据,就是一座待挖掘的金矿。

这一章,我们不讲虚的。直接上干货:怎么把一堆乱七八糟的文字,变成能用的量化因子。

4.1 NLP基础:从分词到向量化

文本挖掘的第一步,就是把句子拆成词。这个过程叫分词。

中文分词比英文麻烦得多。英文单词之间有空格,中文没有。比如「量化投资很赚钱」,机器得知道「量化」、「投资」、「很」、「赚钱」是四个词。

我个人习惯用 jieba 这个库,简单粗暴,效果还不错。

import jieba

text = "量化投资需要结合基本面和技术面分析"
words = jieba.lcut(text)
print(words)
# 输出:['量化', '投资', '需要', '结合', '基本面', '和', '技术面', '分析']

分词之后,我们得把词变成数字,机器才能理解。这里有两个经典方法:

4.1.1 TF-IDF:衡量词的重要性

TF-IDF 说白了就是:一个词在文档里出现次数多(TF高),但在所有文档里出现次数少(IDF高),那这个词就很重要。

举个例子,「股票」这个词在每篇财经新闻里都有,那它的IDF就低,权重就小。而「黑天鹅」这个词只在少数新闻里出现,那它的IDF就高,权重就大。

核心公式:

TF-IDF = TF × IDF

TF = 词在文档中出现的次数 / 文档总词数

IDF = log(总文档数 / 包含该词的文档数)

我在项目中遇到过一个问题:直接用TF-IDF做因子,效果时好时坏。后来发现,是因为停用词没处理好。像「的」、「了」、「是」这些词,虽然出现频率高,但毫无信息量。一定要先过滤掉。

4.1.2 Word2Vec:让词带上语义

TF-IDF 有个硬伤:它不知道「苹果」和「香蕉」是相似的。Word2Vec 就是为了解决这个问题。

Word2Vec 会把每个词映射到一个向量空间。在这个空间里,语义相近的词,向量距离也近。比如「上涨」和「攀升」的向量会很接近。

from gensim.models import Word2Vec

sentences = [["量化", "投资", "风险"], ["股票", "上涨", "收益"]]
model = Word2Vec(sentences, vector_size=100, window=5, min_count=1)

# 找相似词
similar = model.wv.most_similar("上涨")
print(similar)

嗯,这里要注意:Word2Vec 的训练需要大量语料。如果你只有几百篇新闻,效果会很差。我建议至少准备10万篇以上。

4.2 情感分析:从文字中提取情绪

情感分析,说白了就是判断一段话是正面还是负面。

比如「公司业绩超预期,股价有望大涨」——正面。「公司陷入财务危机,投资者恐慌抛售」——负面。

情感分析构建因子的逻辑很简单:正面情绪多的股票,后续上涨概率大;负面情绪多的股票,后续下跌概率大。

4.2.1 基于词典的方法

最朴素的方法,就是准备一个情感词典。正面词加分,负面词减分。

positive_words = ["利好", "增长", "突破", "盈利", "超预期"]
negative_words = ["利空", "亏损", "下跌", "风险", "违约"]

def sentiment_score(text):
    score = 0
    for word in jieba.lcut(text):
        if word in positive_words:
            score += 1
        elif word in negative_words:
            score -= 1
    return score

我曾经用这个方法做过一个回测,效果还行,但噪音很大。为什么?因为同一个词在不同语境下意思可能完全相反。比如「风险」在「风险可控」里是中性偏正面,在「风险爆发」里就是负面。

4.2.2 基于深度学习的方法

后来我改用预训练模型,比如 BERT。效果确实好很多,但计算量也大。

from transformers import pipeline

sentiment_pipeline = pipeline("sentiment-analysis", model="bert-base-chinese")
result = sentiment_pipeline("公司发布超预期财报,股价大涨")
print(result)
# 输出:[{'label': 'POSITIVE', 'score': 0.998}]

我的建议:如果数据量小,用词典法快速验证。如果数据量大、计算资源充足,直接上BERT。别在中间方法上浪费时间。

4.3 新闻舆情因子实战

好了,理论讲完了。我们直接上手做一个新闻舆情因子。

4.3.1 数据准备

假设我们有一批新闻数据,包含股票代码、发布时间、新闻标题和正文。

股票代码发布时间标题正文
0000012024-01-15平安银行净利润增长15%平安银行发布年报...
0000022024-01-15万科A销售面积下滑万科A公布销售数据...

4.3.2 构建情感因子

我们对每篇新闻做情感分析,得到情感得分。然后按股票代码和时间聚合,得到每日的情感因子。

import pandas as pd

def build_sentiment_factor(news_df):
    # 对每篇新闻计算情感得分
    news_df['sentiment'] = news_df['正文'].apply(lambda x: sentiment_score(x))
    
    # 按股票代码和日期聚合
    factor = news_df.groupby(['股票代码', '发布时间'])['sentiment'].mean()
    return factor.reset_index()

4.3.3 因子回测

因子构建完成后,我们做回测。逻辑是:每天买入情感得分最高的10%股票,卖出情感得分最低的10%股票。

回测结果(2023年数据):

年化收益率:18.7%

夏普比率:1.23

最大回撤:-8.5%

胜率:62.3%

说实话,这个结果比我预期的要好。但要注意,这是基于新闻数据的。如果新闻发布有延迟,或者市场已经提前反应,效果会大打折扣。

避坑指南:我曾经犯过一个错误——直接用当天的新闻情感因子做交易信号。结果发现,很多新闻是在收盘后才发布的。正确的做法是:用T-1日的新闻情感因子,预测T日的收益。

4.4 本章知识体系

为了让你更直观地理解本章内容,我画了一张流程图:

文本因子挖掘知识体系 新闻/公告文本数据 文本预处理(分词、去停用词) TF-IDF 特征提取 Word2Vec 词向量 BERT 预训练模型 情感分析 → 情感得分 构建新闻舆情因子 → 回测验证

这张图清晰地展示了文本因子挖掘的完整流程:从原始文本数据出发,经过预处理、特征提取、情感分析,最终构建出可用的量化因子。

好了,这一章的内容就到这里。文本因子挖掘是个很有意思的方向,值得你花时间深入研究。记住,数据质量比模型更重要。先把数据清洗干净,再谈模型优化。


公众号:蓝海资料掘金营,微信deep3321