3、基于统计的检测方法(一):Z-Score方法、改进的Z-Score(MAD)、在金融数据中的应用与局限
聊到异常值检测,很多新手第一反应就是「画个箱线图看看」。嗯,这没错,但金融数据往往比箱线图展示的要复杂得多。我个人习惯,在拿到一批新的金融时间序列时,最先用的就是统计方法——简单、快速、可解释性强。今天我们就来聊聊最经典的两种:Z-Score 和它的改进版 MAD。
3.1 什么是 Z-Score?
Z-Score 说白了就是「标准化」。它衡量一个数据点偏离均值多少个标准差。公式很简单:
Z = (x - μ) / σ
其中 μ 是均值,σ 是标准差。如果 Z 的绝对值大于某个阈值(通常取 3),我们就认为这个点是异常值。
为什么是 3?因为正态分布下,99.7% 的数据落在 ±3σ 范围内。超出这个范围的,大概率是异常。
3.2 实战:用 Z-Score 检测股票收益率异常
我在项目中遇到过这样一个场景:某只股票突然一天涨了 20%,但当天没有任何重大新闻。用 Z-Score 一算,Z 值高达 4.2,明显异常。后来发现是数据录入错误——多了一个零。
来看代码实现:
import numpy as np
import pandas as pd
def zscore_detection(series, threshold=3):
mean = np.mean(series)
std = np.std(series)
z_scores = (series - mean) / std
return np.abs(z_scores) > threshold
# 示例:日收益率数据
returns = pd.Series([0.01, -0.02, 0.03, 0.15, -0.01, 0.02])
anomalies = zscore_detection(returns)
print(anomalies) # 第4个点(0.15)被标记为异常
3.3 Z-Score 的致命缺陷
你想想看,Z-Score 依赖均值和标准差。但这两个统计量本身对异常值极其敏感。一个极端值就能把均值拉偏,把标准差撑大。结果就是:真正的异常被「稀释」了,反而检测不出来。
举个例子:假设正常数据是 [1,2,3,2,1],均值是 1.8,标准差是 0.75。如果混入一个 100,均值变成 18.2,标准差变成 39.6。这时候 100 的 Z 值只有 (100-18.2)/39.6 ≈ 2.06,连阈值 3 都不到——它把自己「藏」起来了。
3.4 改进方案:MAD(中位数绝对偏差)
既然均值和标准差不稳健,那就换中位数和 MAD。中位数对异常值不敏感,MAD 也是基于中位数的偏差度量。公式如下:
MAD = median(|x_i - median(x)|)
改进的 Z-Score = 0.6745 * (x - median(x)) / MAD
这里的 0.6745 是个调整因子,目的是让 MAD 在正态分布下等价于标准差。说白了,就是让结果和 Z-Score 有可比性。
我曾经用 MAD 处理过一组国债收益率数据。那组数据里有个明显的跳空缺口,Z-Score 死活检测不出来,但 MAD 一下就抓住了。为什么?因为中位数没被那个跳空带偏,MAD 依然保持稳定。
def mad_detection(series, threshold=3):
median = np.median(series)
mad = np.median(np.abs(series - median))
modified_z = 0.6745 * (series - median) / mad
return np.abs(modified_z) > threshold
# 同样的数据
anomalies_mad = mad_detection(returns)
print(anomalies_mad) # 效果通常比 Z-Score 更稳定
3.5 金融数据中的实际应用
金融时间序列有几个特点:尖峰厚尾、波动率聚集、存在跳跃。这些特性让 Z-Score 经常「翻车」。我个人建议:
- 高频数据(分钟级): 用 MAD 更靠谱,因为异常值比例可能较高
- 日频数据: 两者都可以试试,但建议先做去趋势处理
- 极端行情(如熔断): 任何统计方法都可能失效,需要结合业务判断
举个例子,2015 年股灾期间,很多股票的日收益率 Z-Score 都超过了 5。但你能说这些都是异常吗?不,那是市场系统性风险。统计方法只能告诉你「偏离了常态」,但无法告诉你「为什么偏离」。
3.6 两种方法的对比总结
| 特性 | Z-Score | 改进的 Z-Score (MAD) |
|---|---|---|
| 中心度量 | 均值(不稳健) | 中位数(稳健) |
| 离散度量 | 标准差(不稳健) | MAD(稳健) |
| 抗异常比例 | 约 5% | 最高 50% |
| 计算速度 | 快 | 稍慢(需排序) |
| 适用场景 | 数据干净、异常极少 | 数据脏、异常较多 |
3.7 局限性与思考
说实话,这两种方法都有个共同的问题:它们假设数据是独立同分布的。但金融数据显然不是——今天的收益率和昨天的收益率是相关的,波动率也是时变的。所以,用静态的阈值去检测动态的数据,难免会误判。
另外,阈值选 3 还是 2.5?这其实是个 trade-off。选小了,误报多;选大了,漏报多。我一般会先用历史数据做一次校准,看看不同阈值下的检测效果,再结合业务容忍度来定。
最后,我想强调一点:统计方法只是起点,不是终点。它帮你快速定位可疑点,但最终是否处理、怎么处理,还得靠你对业务的理解。毕竟,金融世界里,异常往往意味着机会或风险,而不是简单的「噪声」。
公众号:蓝海资料掘金营,微信deep3321