凌晨三点,鹏城湾的灯光在窗外连成一片金色星河。林晨靠在椅背上,盯着屏幕上刚刚跑完的回测结果,眉头微皱。
新优化后的策略运行了两天,实盘收益曲线平稳上升,7万元本金已经变成了元。按年化算相当可观,但林晨总觉得缺了点什么。
他点开交易日志,一页页翻看。系统在大多数时间里表现稳健,但在几个特定交易日——通常是政策发布日或财报集中披露期——会出现明显的预测偏差。模型基于技术指标给出的信号,有时会被市场情绪瞬间淹没。
“情绪……”林晨喃喃自语,起身走到窗边。
远处城中村的灯光星星点点,那里住着无数像他一样的打工者。白天在科技园的高楼里敲代码、写方案,晚上回到十几平米的出租屋,刷手机、看股票。他们的喜怒哀乐,他们的贪婪与恐惧,汇聚成A股市场最底层、也最真实的声音。
林晨忽然想起自己刚入市那几年,每天收盘后必刷股吧。那些帖子鲜活、粗糙,有时甚至粗俗,但字里行间都是最真实的情绪宣泄——“主力死全家”“明天涨停我直播吃键盘”“套了三年终于解套了泪目”。
这些情绪,是否可以被量化?
他回到电脑前,打开一个新的 python 脚本。思路很清晰:爬取东方财富股吧的评论数据,对每条评论进行情感分析,计算每只股票在特定时间窗口内的情绪得分,然后将这个得分作为新的特征输入模型。
技术实现上分三步:数据爬取、情感分析、特征工程。
爬取数据相对简单。林晨用 requests 库模拟浏览器请求,配合 beautifulSoup 解析网页。为了避免被封 Ip,他设置了随机延时,并准备了几组 User-Agent 轮换使用。目标很明确:选取沪深300成分股,爬取过去一年每个交易日收盘后两小时内的前500条热门评论。
“这数据量可不小”。林晨估算了一下,300只股票x240个交易日x500条评论,理论上是3600万条。实际爬取时会有重复和无效内容,但至少也是千万级。他的笔记本电脑肯定跑不动,好在之前买的阿里云服务器还有三个月到期,配置虽然不高,但跑爬虫和基础分析够用了。
他花了两个小时写爬虫脚本,测试了几个股票,数据正常。设置好定时任务后,爬虫开始自动运行,预计需要两到三天才能抓完所有历史数据。
接下来是情感分析。
林晨没有选择复杂的深度学习模型——训练样本标注是大问题,而且计算成本太高。他调研了几个开源的中文情感分析工具,最终选择了 SnowNLp。这个库基于朴素贝叶斯算法,虽然精度不是最高,但胜在简单易用,且对网络语言的适应性不错。
他写了个测试脚本,输入几段典型的股吧评论:
“明天高开高走,信我!”
“垃圾公司,财报造假实锤了。”
“跌了五个点,麻了,装死吧。”
“利好出尽是利空,懂的都懂。”
SnowNLp 给出的情感分值基本符合直觉:0.85、0.12、0.35、0.45。林晨又手动标注了100条评论作为验证集,计算出的准确率约78%。对于情绪趋势分析来说,这个精度可以接受——他要的不是判断每条评论的绝对情感,而是统计整体情绪倾向。
“但还有个问题”。林晨盯着屏幕,“有些评论看似情绪强烈,其实是在反讽”。
比如那条“明天涨停我直播吃键盘”,表面看是极度看好,实际上老股民都知道,这往往是反向指标,表达的是对“涨停鼓吹者”的嘲讽。这种语言现象,简单的词袋模型很难捕捉。
林晨思考片刻,决定加入两个补充规则:一是识别常见反讽句式模板,二是引入表情符号权重。股吧评论里,“[微笑]”往往不是真的微笑,“狗头保命”更是经典的免责声明。他整理了二十几种常见模式,写了个简单的规则引擎前置处理。
做完这些,天已经蒙蒙亮。林晨煮了杯咖啡,继续第三步:特征工程。
情绪数据是时间序列,如何转化为模型可用的特征?他设计了几种方案:
当日情绪均值:收盘后两小时内所有评论的情感得分平均值。
情绪波动率:情感得分的标准差,反映情绪分歧程度。
情绪动量:当日情绪均值与过去五日均值的差值。
极端情绪占比:情感得分>0.8(极度乐观)或<0.2(极度悲观)的评论比例。
情绪词频:出现“涨停”“牛市”“抄底”等关键词的频率,与“暴跌”“割肉”“跑路”等负面关键词的频率比值。
每个特征都要做标准化处理,与原有的技术指标在同一个量纲上。林晨修改了之前重构的特征工程模块,新增了 SentimentFeatureExtractor 类,实现了这些计算逻辑。
三天后,爬虫任务完成。服务器上积累了2800多万条评论数据,压缩后仍有40多Gb。林晨在本地只下载了情绪特征的计算结果——每只股票每个交易日的几个数值,数据量骤降到几mb。
他将情绪特征加入模型,重新训练。
等待训练结果时,林晨有些忐忑。这可能是他失业以来最专注的一次技术探索——不是为了面试,不是为了证明自己,而是纯粹想解决一个真实的问题。这种状态让他想起大学时通宵写代码参加竞赛的日子,虽然累,但心里踏实。
下午四点,训练结束。
林晨屏住呼吸,点开回测报告。
策略表现对比(过去三年)
原策略(15个技术特征):年化收益19.5%,最大回撤7.1%,夏普比率2.3
新策略(技术特征+情绪特征):年化收益21.2%,最大回撤6.8%,夏普比率2.6
提升了。
虽然幅度不大,但关键是在那几个情绪化交易日,新策略的预测准确率显着提高。模型学会了识别“市场过热”和“恐慌过度”的信号,在情绪极端时给出了更保守或更激进的操作建议。
林晨靠向椅背,长长吐出一口气。
窗外的鹏城湾华灯初上,写字楼的玻璃幕墙反射着夕阳余晖。他忽然意识到,自己刚刚完成了一次有趣的“跨界”——把自然语言处理技术应用到了量化投资领域。这不是教科书上的案例,而是他为了解决实际问题自己摸索出来的路径。
这种成就感,比拿到一个高薪 offer 更让他兴奋。
他打开实盘监控界面,新策略已经自动部署。系统在下午收盘前给出了三个调仓信号,都是基于技术面稳健、但情绪面出现短期过度悲观的机会。林晨确认了风控参数,点击“执行”。
交易指令发出,7万多的资金开始流动。
做完这些,林晨才感觉到饥饿。他煮了碗面条,端着碗坐回电脑前,又点开了股吧页面——这次不是爬虫视角,而是作为一个普通用户。
他随机点开一只今天跌停的股票评论区。置顶的帖子标题是:“兄弟们,天台冷吗?我来了”。
下面的回复五花八门:
“别慌,明天肯定反弹!”
“我已经躺平了,爱咋咋地。”
“主力洗盘而已,拿住了。”
“楼上的别害人了,这公司基本面早烂了。”
每条评论背后,都是一个真实的人,真实的情绪,真实的金钱得失。林晨的模型把这些情绪转化成了0到1之间的数字,转化成了特征向量,转化成了权重参数。但那些深夜无法入睡的焦虑,那些割肉离场时的不甘,那些意外盈利时的狂喜——这些温度,代码能捕捉吗?
“也许不能完全捕捉”,林晨想,“但至少,我在尝试理解”。
他吃完面条,把碗洗了。回到电脑前,又有了新想法:情绪数据源不应该只有股吧。微博、财经新闻、券商研报的语气……这些都可以爬取分析。甚至,可以尝试用深度学习模型做更细粒度的情绪分类——乐观、悲观、愤怒、恐惧、贪婪……
这个系统,还有太多可以进化的空间。
夜深了,林晨却没有睡意。他调出今天情绪特征最极端的几只股票,一只只查看它们的走势和评论。在“鹏城科技”这只股票上,他发现了有趣的现象:技术指标显示超卖,情绪得分极低(0.18,极度悲观),但模型给出的建议却是“观望”,而非“买入”。
林晨点开这家公司的基本面资料,眉头渐渐皱起。
原来,明天是它的限售股解禁日。