问题描述
scale: 倍数,默认为 1.0。会将位于 [med - scale distance, med + scale distance] 边界之外的值替换为边界值/np.nan
中的distance距离是如何求的是,是各因子值偏离中位数的平均值么?还是其他什么方法求得的值?
解决方案
在 JoinQuant 的 winsorize_med(中位数去极值)函数中,distance 并不是各因子值偏离中位数的平均值,而是绝对中位差(MAD,Median Absolute Deviation)。
在 JoinQuant 的官方文档(如 BarraConstraint 风险暴露限制函数的说明中)也有提及,这个值通常被称为 MEDMED。
distance (MAD) 的具体计算步骤如下:
假设你有一组因子值序列 $X = [x_1, x_2, ..., x_n]$:
-
计算中位数 (MED):
首先求出这组因子值序列的中位数 $MED = Median(X)$。 -
计算绝对偏差:
计算每个因子值与中位数的绝对差值,得到一个新的序列:
$D = [|x_1 - MED|, |x_2 - MED|, ..., |x_n - MED|]$ -
计算绝对偏差的中位数 (distance / MAD / MEDMED):
对上一步得到的绝对偏差序列 $D$ 再次求中位数,得到的值就是distance:
$distance = Median(D)$
最终的去极值边界:
得到 MED 和 distance 后,函数会根据你设置的 scale(倍数)来确定正常值的上下界:
- 下界:$MED - scale \times distance$
- 上界:$MED + scale \times distance$
任何小于下界或大于上界的因子值,都会根据 inclusive 参数的设置,被替换为边界值(inclusive=True)或者 np.nan(inclusive=False)。
总结:distance 是绝对偏差的中位数,而不是平均值。使用中位数而不是平均值的原因是,中位数对极值(异常值)更加鲁棒(不敏感),这正是“中位数去极值法”的核心优势所在。