第二章:数据采集与预处理——打好地基才能盖高楼

做内幕交易检测,说白了就是跟那些想钻空子的人斗智斗勇。我做了这么多年风控模型,最深的体会就是:数据质量决定了模型的天花板。你算法再牛,喂进去的是垃圾,出来的还是垃圾。这一章,我们就聊聊数据从哪里来,怎么洗,怎么对齐。

2.1 数据源介绍:三驾马车

内幕交易检测需要三类核心数据,我习惯叫它们「三驾马车」。缺了任何一匹,模型都跑不稳。

2.1.1 交易数据

这是最基础的数据。包括股票、期货、债券等金融产品的逐笔成交记录。字段通常有:

  • 证券代码:唯一标识一只股票
  • 交易时间:精确到毫秒
  • 成交价格:实际成交价
  • 成交量:成交股数或手数
  • 买卖方向:买盘还是卖盘
  • 交易席位:哪个营业部或机构

我在项目中遇到过一个问题:不同交易所的数据格式不统一。上交所和深交所的时间戳精度不一样,一个到秒,一个到毫秒。嗯,这里要注意,时间精度不一致会直接导致后续对齐失败

2.1.2 公告数据

内幕交易往往发生在重大公告发布前后。公告数据包括:

  • 定期报告:年报、季报
  • 临时公告:并购重组、业绩预告、分红方案
  • 监管问询:交易所的问询函及公司回复

你想想看,一个公司突然发了个业绩暴增的预告,股价第二天涨停。如果有人在公告前大量买入,那就有问题了。公告数据的关键是发布时间,要精确到秒,因为内幕交易者往往在公告前几分钟甚至几秒钟动手。

2.1.3 社交媒体数据

这个是我近几年才加进来的。以前觉得社交媒体噪音太大,后来发现它其实是个金矿。包括:

  • 股吧论坛:东方财富、雪球等
  • 微博大V:财经博主的发言
  • 微信群聊:部分合规的群聊记录

我曾经处理过一个案例:某公司高管在公告前三天,在亲戚群里说了句「公司要签大单了」。虽然只有几十个人看到,但随后几天的交易量异常放大。社交媒体数据虽然乱,但异常信号往往藏在最不起眼的地方

2.2 数据清洗与标准化:脏活累活我来干

数据清洗占了我整个项目时间的60%以上。别嫌烦,这一步做不好,后面全是坑。

2.2.1 缺失值处理

交易数据偶尔会有缺失,比如某只股票停牌了。我的处理原则是:

  • 连续缺失不超过3个:用前后均值填充
  • 连续缺失超过3个:直接删除该时间段
  • 公告数据缺失:从其他数据源补全,比如从巨潮资讯网爬取
注意:千万不要用0填充缺失的交易数据。我见过有人这么干,结果模型把停牌日当成了「零交易异常」,闹了大笑话。

2.2.2 异常值检测

交易数据里经常有「乌龙指」或者数据录入错误。比如某只股票正常价格10元,突然出现一笔100元的成交。这明显是错的。我常用的方法是:

  • 3σ原则:超过均值±3个标准差的数据标记为异常
  • IQR方法:四分位距法,更稳健
  • 业务规则:比如涨跌幅超过10%的,需要人工复核
# 一个简单的异常值检测示例
import pandas as pd
import numpy as np

def detect_outliers(df, column, method='iqr'):
    if method == 'iqr':
        Q1 = df[column].quantile(0.25)
        Q3 = df[column].quantile(0.75)
        IQR = Q3 - Q1
        lower = Q1 - 1.5 * IQR
        upper = Q3 + 1.5 * IQR
        return df[(df[column] < lower) | (df[column] > upper)]
    elif method == '3sigma':
        mean = df[column].mean()
        std = df[column].std()
        return df[(df[column] < mean - 3*std) | (df[column] > mean + 3*std)]

2.2.3 数据标准化

不同股票的价格差异很大,茅台2000块,农业银行3块。如果不做标准化,模型会天然偏向高价股。我常用的标准化方法:

  • Z-score标准化:减去均值除以标准差
  • Min-Max标准化:缩放到[0,1]区间
  • 对数变换:对价格取log,减少偏态
我的习惯:对于交易量数据,我一般用对数变换。因为交易量的分布太偏了,有些股票一天成交几亿,有些只有几百万。取log之后,分布会好看很多。

2.3 时间序列对齐与事件窗口构建

这是内幕交易检测中最关键的一步。说白了,就是把不同来源的数据,按照同一个时间轴对齐,然后圈定「事件窗口」进行分析。

2.3.1 时间序列对齐

交易数据是毫秒级的,公告数据是秒级的,社交媒体数据可能是分钟级的。怎么对齐?我的做法是:

  • 统一时间粒度:我一般用「分钟」作为基本单位。交易数据聚合到每分钟的OHLC(开盘、最高、最低、收盘),公告数据取发布时间所在分钟,社交媒体数据取发帖时间所在分钟。
  • 处理非交易时间:A股只有上午9:30-11:30和下午13:00-15:00交易。非交易时间的数据要单独处理,不能简单丢弃。
  • 跨市场对齐:如果涉及港股或美股,还要考虑时区差异。我曾经因为时区问题,把港股数据错位了一天,查了三天才找到原因。

2.3.2 事件窗口构建

事件窗口是内幕交易检测的核心概念。我们假设内幕交易发生在某个「事件」前后。这个事件可以是:

  • 公告发布:比如业绩预告
  • 高管增减持:大股东买卖股票
  • 监管处罚:被证监会立案调查

事件窗口通常分为三段:

窗口名称 时间范围 含义
事前窗口 事件前[-30, -1]天 内幕信息可能泄露的时间段
事件窗口 事件当天[0, 0] 公告发布当天
事后窗口 事件后[+1, +10]天 市场消化信息的时间段

我个人习惯把事前窗口拉长到60天。为什么?因为有些内幕交易者很狡猾,他们会提前一两个月慢慢建仓,避免引起注意。短窗口容易漏掉这种「温水煮青蛙」式的交易。

核心逻辑:内幕交易检测的本质,就是比较「事件窗口内」的交易行为与「正常时期」的交易行为是否存在显著差异。如果差异过大,就说明有问题。

2.4 本章知识体系总览

下面这张图,是我自己梳理的本章知识结构。你可以把它当作一个「导航图」,随时回来对照。

数据采集与预处理知识体系 交易数据 公告数据 社交媒体数据 数据清洗与标准化 缺失值处理 → 异常值检测 → 数据标准化(Z-score / Min-Max / 对数变换) 时间序列对齐 统一时间粒度(分钟级) | 处理非交易时间 | 跨市场时区对齐 事件窗口构建 事前窗口[-60, -1] → 事件窗口[0] → 事后窗口[+1, +10]

这张图把整个流程串起来了。从三个数据源出发,经过清洗和标准化,再对齐到统一的时间轴,最后构建事件窗口。每一步都环环相扣,缺一不可。

2.5 避坑指南

最后,分享几个我踩过的坑,希望能帮你少走弯路:

  • 不要迷信「全量数据」:我曾经试图把所有股票的所有历史数据都拿来训练,结果模型又慢又差。后来只选了流动性好的前500只股票,效果反而更好。
  • 注意「幸存者偏差」:如果只拿现在还在交易的股票做训练,会漏掉那些已经退市的。退市股票里往往藏着很多内幕交易案例。
  • 社交媒体数据要「去噪」:股吧里90%的帖子都是废话。我一般先用关键词过滤,只保留跟「内幕」「消息」「提前知道」等相关的帖子。
  • 时间窗口不是固定的:不同的事件类型,窗口长度应该不同。比如并购重组,事前窗口可能要拉到90天;而业绩预告,30天就够了。

好了,数据准备这块就聊到这儿。记住一句话:数据预处理花的时间越多,后面建模就越轻松。别急着跑模型,先把数据搞干净再说。


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