4. 异常值检测与修正:基于统计、距离与模型的综合策略
在金融压力测试中,异常值会严重扭曲风险因子分布、破坏协方差结构,导致压力情景下的损失估计偏差。本章系统讲解三类异常检测方法及其修正技术,确保特征工程输出的数据质量满足压力测试的稳健性要求。
4.1 异常值检测方法体系
根据数据分布假设与计算复杂度,异常检测方法可分为统计、距离与模型三大类。下表对比了核心方法的适用场景与优缺点:
| 方法类别 | 代表算法 | 分布假设 | 适用场景 | 主要局限 |
|---|---|---|---|---|
| 统计 | Z-score、IQR | 正态或对称分布 | 单变量、快速筛查 | 对多变量交互异常不敏感 |
| 距离 | LOF (Local Outlier Factor) | 局部密度可比 | 局部密度变化、簇状数据 | 计算复杂度 O(n²) |
| 模型 | Isolation Forest | 无显式分布 | 高维、非线性、大规模 | 对弱异常可能漏检 |
4.2 基于统计的异常检测
4.2.1 Z-score 方法
Z-score 衡量数据点与均值的偏离程度,适用于近似正态分布的数据。金融压力测试中常用于检测利率、汇率等单变量极端波动。
import numpy as np
from scipy import stats
def zscore_outliers(data, threshold=3):
z = np.abs(stats.zscore(data))
return np.where(z > threshold)[0]
# 示例:检测日收益率序列中的极端值
returns = np.random.randn(1000) * 0.02 + 0.001
outlier_idx = zscore_outliers(returns, threshold=3.5)
print(f"检测到 {len(outlier_idx)} 个异常点")
4.2.2 IQR 方法
IQR(四分位距)不依赖正态假设,通过箱线图规则识别异常。在信用评分、违约率等偏态分布特征中表现稳健。
def iqr_outliers(data, multiplier=1.5):
Q1, Q3 = np.percentile(data, [25, 75])
IQR = Q3 - Q1
lower = Q1 - multiplier * IQR
upper = Q3 + multiplier * IQR
return np.where((data < lower) | (data > upper))[0]
# 金融压力测试中常用 multiplier=3 作为极端值截断
extreme_idx = iqr_outliers(loan_default_rates, multiplier=3)
实践建议:在压力测试中,建议同时使用 Z-score 和 IQR 进行交叉验证。若两种方法均标记为异常,则该点应优先处理;若仅一种方法标记,需结合业务逻辑判断。
4.3 基于距离的异常检测:LOF
LOF(局部异常因子)通过比较数据点与其邻域的局部密度来识别异常。在金融特征中,能有效发现“孤立但密度高”的异常簇,如特定市场环境下的共变异常。
from sklearn.neighbors import LocalOutlierFactor
def lof_detection(X, contamination=0.05, n_neighbors=20):
lof = LocalOutlierFactor(
n_neighbors=n_neighbors,
contamination=contamination,
novelty=False
)
y_pred = lof.fit_predict(X)
# -1 表示异常,1 表示正常
outlier_indices = np.where(y_pred == -1)[0]
return outlier_indices, lof.negative_outlier_factor_
# 多变量特征矩阵:波动率、相关性、流动性
features = np.column_stack([volatility, correlation, liquidity])
outliers, lof_scores = lof_detection(features, contamination=0.03)
注意:LOF 对 n_neighbors 参数敏感。在金融时间序列中,建议使用 10~30 的邻域范围,过小会导致误报,过大会平滑掉局部异常。
4.4 基于模型的异常检测:Isolation Forest
Isolation Forest 通过随机切割特征空间来隔离异常点。异常点因路径更短而被快速隔离,适合高维金融特征(如多资产收益率、风险因子载荷)。
from sklearn.ensemble import IsolationForest
def isolation_forest_detection(X, contamination=0.05, random_state=42):
iso_forest = IsolationForest(
contamination=contamination,
random_state=random_state,
n_estimators=100,
max_samples='auto'
)
y_pred = iso_forest.fit_predict(X)
outlier_indices = np.where(y_pred == -1)[0]
anomaly_scores = iso_forest.decision_function(X)
return outlier_indices, anomaly_scores
# 压力测试情景:同时检测 50 个风险因子的异常
risk_factors = np.random.randn(5000, 50) * 0.1
anomaly_idx, scores = isolation_forest_detection(risk_factors, contamination=0.02)
4.5 极端值截尾与 Winsorize 处理
检测到异常后,不能简单删除——在压力测试中,极端值可能包含尾部风险信息。Winsorize(缩尾处理)将极端值替换为指定分位数的边界值,保留样本量同时控制极端影响。
4.5.1 截尾处理(Trimming)
直接删除异常值,适用于明显的数据录入错误或不可恢复的测量噪声。
def trim_outliers(data, lower_percentile=1, upper_percentile=99):
lower = np.percentile(data, lower_percentile)
upper = np.percentile(data, upper_percentile)
return data[(data >= lower) & (data <= upper)]
# 删除极端尾部 1% 的数据
clean_returns = trim_outliers(asset_returns, 1, 99)
4.5.2 Winsorize 处理
将异常值替换为边界值,保留数据量同时抑制极端值影响。金融压力测试中常用 1%/99% 或 5%/95% 分位数作为截断点。
from scipy.stats.mstats import winsorize
def winsorize_features(data, limits=(0.01, 0.01)):
"""
limits: (lower_fraction, upper_fraction)
例如 (0.01, 0.01) 表示将底部1%和顶部1%替换为边界值
"""
return winsorize(data, limits=limits)
# 对压力测试中的风险因子进行缩尾
risk_factor_winsorized = winsorize_features(
stress_test_factors,
limits=(0.025, 0.025) # 2.5% 缩尾
)
关键区别:截尾会减少样本量,在压力测试中可能导致尾部事件被低估;Winsorize 保留样本量但压缩极端值幅度。建议在压力测试中优先使用 Winsorize,并记录缩尾比例作为敏感性分析参数。
4.6 金融压力测试中的异常处理流程
结合上述方法,推荐以下标准化处理流程:
- 初步筛查:使用 Z-score 和 IQR 对每个风险因子进行单变量异常检测,标记极端值。
- 多变量验证:对标记的异常点,使用 LOF 或 Isolation Forest 进行多变量验证,排除因变量交互导致的误判。
- 业务审核:将检测结果与压力测试情景(如 2008 年金融危机、2020 年疫情冲击)对比,确认是否为真实市场极端事件。
- 修正处理:对确认的异常值,优先使用 Winsorize 处理;对明显错误的数据(如负价格、超范围值)进行截尾删除。
- 记录与报告:记录异常检测参数、处理比例、修正前后统计量变化,作为压力测试模型文档的一部分。
实战案例:在某银行信用风险压力测试中,使用 Isolation Forest 检测到 3% 的贷款样本在“失业率-违约率”二维空间中出现异常共变。经 Winsorize 处理后,压力损失估计的波动率降低了 18%,模型稳定性显著提升。
4.7 本章小结
| 方法 | 核心思想 | 金融应用场景 | 推荐参数 |
|---|---|---|---|
| Z-score | 标准差偏离度 | 收益率、波动率单变量检测 | 阈值 3~4 |
| IQR | 四分位距 | 信用评分、违约率偏态分布 | 乘数 1.5~3 |
| LOF | 局部密度比 | 多资产共变异常、市场微观结构 | n_neighbors=20, contamination=0.03~0.05 |
| Isolation Forest | 随机切割隔离 | 高维风险因子、压力情景筛选 | n_estimators=100, contamination=0.02~0.05 |
| Winsorize | 分位数替换 | 尾部风险保留、压力测试数据清洗 | limits=(0.01,0.01) 至 (0.05,0.05) |