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)被标记为异常
小技巧: 金融数据往往有自相关性,建议先用差分或对数收益率转换,再做 Z-Score 检测。

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 都不到——它把自己「藏」起来了。

注意: 这就是所谓的「掩蔽效应」。Z-Score 在异常值比例较高时(比如超过 5%),效果会大打折扣。

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 更稳定
MAD 的优势: 抗干扰能力强,最多能容忍 50% 的异常值而不受影响。

3.5 金融数据中的实际应用

金融时间序列有几个特点:尖峰厚尾、波动率聚集、存在跳跃。这些特性让 Z-Score 经常「翻车」。我个人建议:

  • 高频数据(分钟级): 用 MAD 更靠谱,因为异常值比例可能较高
  • 日频数据: 两者都可以试试,但建议先做去趋势处理
  • 极端行情(如熔断): 任何统计方法都可能失效,需要结合业务判断

举个例子,2015 年股灾期间,很多股票的日收益率 Z-Score 都超过了 5。但你能说这些都是异常吗?不,那是市场系统性风险。统计方法只能告诉你「偏离了常态」,但无法告诉你「为什么偏离」。

避坑指南: 我曾经在回测中直接用 Z-Score 剔除「异常」交易日,结果回测收益虚高。后来发现那些「异常日」恰恰是重大利好或利空事件,剔除后反而失真了。所以,异常值检测不等于直接删除,要区分是「数据错误」还是「真实事件」。

3.6 两种方法的对比总结

特性 Z-Score 改进的 Z-Score (MAD)
中心度量 均值(不稳健) 中位数(稳健)
离散度量 标准差(不稳健) MAD(稳健)
抗异常比例 约 5% 最高 50%
计算速度 稍慢(需排序)
适用场景 数据干净、异常极少 数据脏、异常较多

3.7 局限性与思考

说实话,这两种方法都有个共同的问题:它们假设数据是独立同分布的。但金融数据显然不是——今天的收益率和昨天的收益率是相关的,波动率也是时变的。所以,用静态的阈值去检测动态的数据,难免会误判。

另外,阈值选 3 还是 2.5?这其实是个 trade-off。选小了,误报多;选大了,漏报多。我一般会先用历史数据做一次校准,看看不同阈值下的检测效果,再结合业务容忍度来定。

我的经验: 对于日频股票数据,阈值设在 3.5 左右比较合适。对于高频数据,可以放宽到 4。因为高频数据的波动更大,正常值也可能达到 3 个标准差。

最后,我想强调一点:统计方法只是起点,不是终点。它帮你快速定位可疑点,但最终是否处理、怎么处理,还得靠你对业务的理解。毕竟,金融世界里,异常往往意味着机会或风险,而不是简单的「噪声」。

基于统计的异常值检测方法 Z-Score 方法 改进的 Z-Score (MAD) 公式: Z = (x - μ) / σ 阈值: |Z| > 3 视为异常 局限: 对异常值敏感,掩蔽效应 公式: MZ = 0.6745*(x - med)/MAD 优势: 抗异常能力强,最高50% 适用: 数据脏、异常比例高 共同局限: 假设独立同分布,不适用于金融时间序列

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