3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在 JoinQuant(聚宽)量化平台上进行因子研究与策略开发时,对因子数据进行**去极值处理(Winsorization)**是量化因子预处理的关键步骤。中位数绝对偏差去极值(MAD, Median Absolute Deviation)是一种稳健的去极值方法,聚宽在 jqfactor 模块中提供了 winsorize_med 函数。
本文将详细解答 winsorize_med 函数中 scale 参数设置为 1 与 3 的核心区别及实际应用场景。
winsorize_med 函数基于中位数(Median)和绝对离差中位数(MAD)来计算去极值的上下边界:
inclusive=True 时,超出 $[\text{Lower Bound}, \text{Upper Bound}]$ 的极端值会被替换为边界值。scale 参数用于控制截断边界的宽窄,即容忍异常离群值的程度。
| 比较维度 | scale = 1 | scale = 3 (常用标准) |
|---|---|---|
| 截断区间范围 | 较窄 ($[med - 1 \times MAD, med + 1 \times MAD]$) | 较宽 ($[med - 3 \times MAD, med + 3 \times MAD]$) |
| 数据压缩程度 | 极高,大量分布在两侧的数据被压缩到边界 | 适中,仅调整真正极端(异常)的离群点 |
| 保留原始信息量 | 较低,可能损失因子的正常截面区分度 | 较高,保留了绝大多数正态分布/偏态分布下的有效信息 |
| 对噪点的抗干扰性 | 非常强,强烈平滑数据波动 | 良好,兼顾抗噪与真实数据特征 |
| 适用因子类型 | 高噪声、极端尾部噪声极大且波动剧烈的因子 | 标准基本面因子、技术指标、风险因子(行业通用标准) |
在 JoinQuant 策略或研究环境中,可以通过以下代码体验 scale 参数对因子分布的影响:
import pandas as pd
import numpy as np
from jqfactor import winsorize_med, get_index_stocks
# 1. 模拟生成包含极端异常值的截面因子数据
np.random.seed(42)
stocks = get_index_stocks('000300.XSHG', date='2023-01-01')[:100]
raw_factor = pd.Series(np.random.normal(0, 1, len(stocks)), index=stocks)
# 人为引入极端离群值
raw_factor.iloc[0] = 50.0 # 极大异常值
raw_factor.iloc[1] = -40.0 # 极小异常值
# 2. 当 scale = 1 时的去极值处理
factor_scale_1 = winsorize_med(raw_factor, scale=1, inclusive=True)
# 3. 当 scale = 3 时的去极值处理(量化常用标准)
factor_scale_3 = winsorize_med(raw_factor, scale=3, inclusive=True)
# 查看对比结果
print("原始数据最大值与最小值:", raw_factor.max(), raw_factor.min())
print("scale=1 处理后最大值与最小值:", factor_scale_1.max(), factor_scale_1.min())
print("scale=3 处理后最大值与最小值:", factor_scale_3.max(), factor_scale_3.min())
推荐默认选择 scale=3:
在金融学术界及主流机构量化实践中,3倍 MAD(即 scale=3)对应于正态分布下约 3 个标准差(近似 $3 \times 1.4826 \times MAD$)的裁剪范围,能够有效剔除财务错报或极端行情造成的异常噪点,同时最大程度保留因子对股票收益的解释力。
谨慎使用 scale=1:
将 scale 设为 1 会导致过度截断(Over-clipping),大量正常分位数的股票因子值被强行压平为同一个边界值,从而降低因子截面的多空区分度(区分度下降会导致回归或排序效果变差)。只有在因子尾部噪声极高且确信离群值会严重破坏多因子回归模型时才考虑缩小 scale。