4、事件检测与信号生成:基于NLP的事件抽取、正则表达式匹配事件、事件强度打分、信号阈值设定

做事件交易,最核心的问题是什么?

不是你怎么分析,而是你能不能第一时间知道事件发生了

我早年做量化的时候,吃过这个亏。有一次财报出来,我还在手动刷新页面,结果市场已经反应完了。嗯,从那以后,我就把事件检测这件事,彻底交给了代码。

4.1 事件检测的两条腿:NLP与正则

事件检测,说白了就是从海量文本里捞出我们想要的东西。我个人习惯用两条腿走路:

  • 正则表达式:快、准、稳。适合结构化的公告、财报标题。
  • NLP事件抽取:灵活、泛化。适合新闻、社交媒体这种非结构化文本。

你想想看,如果只靠正则,遇到「公司拟收购XX」和「公司完成收购XX」这种变体,你得写多少规则?反过来,如果只靠NLP,遇到「分红10派5」这种固定格式,又显得杀鸡用牛刀。

我的经验法则:能用正则的,别用NLP。正则搞不定的,再上NLP。

4.2 正则表达式匹配事件:快刀斩乱麻

正则匹配,我一般用在公告标题上。比如财报、分红、回购、增持这些,格式相对固定。

举个例子,匹配「业绩预增」类事件:

import re

# 匹配业绩预增公告
pattern = r'(业绩|净利润|营收).{0,10}(预增|增长|上升|扭亏)'
text = "公司2024年业绩预增公告"
match = re.search(pattern, text)
if match:
    print(f"检测到事件: {match.group()}")

这里有个坑,我踩过。正则写得太宽,容易误报。比如「业绩预增」和「业绩预增幅度低于预期」,前者是利好,后者是利空。所以我的做法是:先粗筛,再精分

避坑指南:我曾经写过一个「回购」的正则,结果把「回购股份用于注销」和「回购股份用于股权激励」全混在一起了。后来我加了关键词权重,才把两类事件分开。

4.3 NLP事件抽取:让机器读懂新闻

正则搞不定的,就得靠NLP了。我常用的方法是基于预训练模型+触发词的抽取方式。

具体来说,分三步:

  1. 触发词检测:先找事件关键词,比如「收购」「减持」「中标」。
  2. 实体识别:找出谁收购了谁,金额多少。
  3. 事件分类:判断是利好还是利空。

我项目中用过BERT做微调,效果不错。但说实话,对于交易场景,速度比精度更重要。所以我后来改用轻量级的模型,比如ALBERT或者蒸馏版BERT。

from transformers import pipeline

# 加载事件抽取模型
event_extractor = pipeline("text-classification", 
                          model="your-event-model")

text = "公司成功中标5G基站建设项目,金额约2.3亿元"
result = event_extractor(text)
print(f"事件类型: {result[0]['label']}, 置信度: {result[0]['score']:.2f}")

注意:NLP模型不是万能的。我遇到过模型把「公司否认收购传闻」识别成「收购事件」,因为「收购」这个词出现了。所以,否定词处理一定要做。

4.4 事件强度打分:别把蚊子当大象

检测到事件只是第一步。更关键的是,这个事件有多重要

我设计了一套打分体系,主要看三个维度:

维度 权重 说明
事件类型 40% 并购、财报、政策等基础权重
金额/规模 30% 占市值比例越高,分数越高
市场情绪 30% 同行业其他公司的反应

举个例子,一个「回购1亿元」的事件,如果公司市值才10亿,那强度分就很高。如果市值1000亿,那也就是个普通事件。

def event_strength_score(event_type, amount, market_cap, sentiment):
    # 基础分
    base_score = {
        '并购': 80,
        '财报': 70,
        '回购': 60,
        '减持': 50
    }.get(event_type, 30)
    
    # 规模分
    ratio = amount / market_cap
    scale_score = min(ratio * 100, 100)
    
    # 情绪分
    sentiment_score = sentiment * 100
    
    # 加权总分
    total = base_score * 0.4 + scale_score * 0.3 + sentiment_score * 0.3
    return total

我个人习惯:强度分低于40的事件,我基本不看。因为噪音太多,容易干扰判断。

4.5 信号阈值设定:别让系统乱叫

有了强度分,接下来就是设阈值。阈值设得太低,系统天天报警,你根本看不过来。设得太高,又容易错过机会。

我的做法是动态阈值

  • 基础阈值:固定60分,低于这个的直接过滤。
  • 动态调整:根据市场波动率调整。波动大的时候,阈值提高10-20分。
  • 事件类型差异化:并购类事件阈值设低点(50分),因为机会难得。日常公告类设高点(70分)。

我曾经犯过一个错:把所有事件的阈值都设成一样的。结果并购机会没抓到,日常公告倒是堆了一堆。后来改成差异化阈值,效果好了很多。

小技巧:你可以用历史回测来优化阈值。比如回测过去一年,看看阈值设在多少时,信号准确率最高。

4.6 知识体系总览

下面这张图,是我做事件检测的完整流程。你可以把它当成一个参考框架:

事件检测与信号生成流程 原始文本输入 结构化文本? 正则匹配 NLP抽取 事件类型 + 实体 + 金额提取 事件强度打分(类型+规模+情绪) 超过动态阈值? 生成信号

这张图里,我特别想强调一点:正则和NLP不是二选一,而是互补的。结构化文本走正则,非结构化文本走NLP,最后汇合到一起做强度打分。

好了,事件检测和信号生成这部分,核心就是这些。记住:快、准、稳,三个字就够了。