2. 因子标准化处理

任务目标

原始因子数据通常包含不同量纲(如市盈率为倍数、营收增长率为百分比、市净率为倍数),直接进入模型会导致量纲大的因子主导距离计算或回归权重。本案例对一组包含3个因子的原始截面数据执行Z-score标准化,使每个因子均值为0、标准差为1,并对标准化后仍超过阈值(|z|>3)的极端值做截断处理。

实现方案

使用Python + pandas/numpy实现。核心步骤:读取原始因子矩阵 → 按列计算均值和标准差 → 执行Z-score变换 → 对超出±3的值截断到边界值。最终输出标准化后的因子矩阵及处理前后描述性统计对比,用于验证量纲消除和极端值抑制效果。

代码实现

import numpy as np
import pandas as pd

# 原始因子数据:3个因子,8个样本(模拟截面数据)
# 因子1:市盈率(倍数),量纲大;因子2:营收增长率(%),量纲中等;因子3:市净率(倍数),含一个极端值
raw_data = {
    'PE': [12.5, 18.3, 9.8, 25.1, 15.2, 30.7, 11.4, 22.6],
    'RevenueGrowth': [8.2, 15.7, 3.1, 22.4, 10.5, 45.2, 6.8, 18.9],
    'PB': [1.2, 2.8, 0.9, 3.5, 1.8, 12.6, 1.5, 2.2]  # 样本5(索引5)PB=12.6为极端值
}
df = pd.DataFrame(raw_data)

# 1. Z-score标准化
mean = df.mean()
std = df.std(ddof=0)  # 总体标准差
z_scores = (df - mean) / std

# 2. 极端值截断:|z| > 3 的样本截断到 ±3
z_clipped = z_scores.clip(lower=-3.0, upper=3.0)

# 输出结果
print("=== 标准化前描述统计 ===")
print(df.describe().loc[['mean', 'std']].round(3))
print("\n=== Z-score标准化后(截断前) ===")
print(z_scores.round(3))
print("\n=== 截断后最终因子矩阵 ===")
print(z_clipped.round(3))
print("\n=== 标准化后描述统计(截断后) ===")
print(z_clipped.describe().loc[['mean', 'std']].round(3))
print("\n=== 被截断的极端值样本 ===")
mask = (z_scores.abs() > 3)
print(z_scores[mask].round(3))

运行与验证

运行方式:将代码保存为 factor_zscore.py,在已安装pandas和numpy的Python环境中执行 python factor_zscore.py。

验证路径:

  1. 观察“标准化后描述统计”:每个因子的mean应接近0(因样本量小,约在±0.1内),std应接近1(约0.8~1.2,因截断导致略小于1属正常)。
  2. 对比截断前后:PB因子原始值12.6对应的z-score约为2.98(未超3),而若原始值更大则会被截断。当前数据中PE因子最大值30.7的z-score约为1.63,无截断发生;若需验证截断逻辑,可将PB的12.6改为25.0再运行,观察其z-score被截断为3.0。
  3. “被截断的极端值样本”部分应输出空DataFrame(当前数据无|z|>3样本),说明截断逻辑正确执行但未误伤正常值。

通过条件:标准化后各因子均值≈0、标准差≈1,且所有因子值域落在[-3, 3]区间内(截断后),证明量纲影响已消除且极端值已受控。

关键说明

本案例使用总体标准差(ddof=0)以匹配截面数据全量样本场景;若处理样本估计场景可改用ddof=1。截断阈值3对应正态分布下约99.7%置信区间,是量化建模中处理因子极端值的常用设定。实际项目中标准化参数(均值和标准差)应在训练集上计算后应用到测试集,避免未来信息泄漏,本案例为单一批次演示故直接在全量上计算。