导言 / TL;DR
“Garbage in, garbage out” 是量化研究永恒的铁律。在构建因子模型、多因子选股或输入机器学习模型前,如果直接使用未经清洗的原始财务或行情指标,极易受到极值(异常值)的干扰,导致回测结论失真。本文将演示如何利用 Python 配合 QuantDash 干净的数据流,采用绝对中位数偏差法(MAD)对因子数据进行“去极值”并配合 Z-Score 进行“无量纲标准化”处理。
技术痛点拆解
量化分析师在做多因子研究时,经常遭遇以下数据预处理陷阱:
- 极端行情扭曲统计特征:当个别小盘股因复牌、重组出现暴涨,或者财报数据中存在偶发性的非经常性损益时,该因子的数值可能会比均值大几十倍。如果直接套用标准差计算,会导致整个因子的均值被严重拉高,淹没其他正常标的的信号。
- 量纲单位不一致无法融合:市盈率(PE)因子的数值通常在几十,而流通市值(MV)因子则在百亿量级。如果不经过标准化,这两个因子根本无法在多因子模型中融合成一个综合得分。
极简解决方案(基于 QuantDash SDK 与 Pandas/Scipy)
我们通过 Pandas 处理从 QuantDash 获取的多只股票的因子指标(这里以最基础的日收益率因子为例),并进行稳健的 MAD(Median Absolute Deviation)去极值以及 Z-Score 标准化。
pip install quantdash pandas scipy
import numpy as np
import pandas as pd
from quantdash import QuantDash
# 1. 初始化 QuantDash
qd = QuantDash(api_key="sk_xxxxx")
def handle_factor_preprocessing(df_factor: pd.DataFrame, factor_name: str) -> pd.DataFrame:
"""
对因子的指定列进行 MAD 去极值与 Z-Score 标准化
"""
df = df_factor.copy()
# --- 步骤 1: MAD 去极值 (Median Absolute Deviation) ---
# 相比标准差法,MAD 法更不易受极端大值的偏离影响,是量化界标准的稳健去极值方法
median = df[factor_name].median()
mad = (df[factor_name] - median).abs().median()
# 设定边界阈值(通常设定为 3 倍 MAD 或 5 倍 MAD)
# 1.4826 是一个比例常数,使 MAD 的标度与标准差大致相当
mad_limit = 3 * 1.4826 * mad
lower_bound = median - mad_limit
upper_bound = median + mad_limit
# 进行边界截断(Clip)
df[f"{factor_name}_clean"] = df[factor_name].clip(lower=lower_bound, upper=upper_bound)
# --- 步骤 2: Z-Score 标准化 ---
# 将因子的均值调整为 0,标准差调整为 1,消除量纲影响
mean = df[f"{factor_name}_clean"].mean()
std = df[f"{factor_name}_clean"].std()
df[f"{factor_name}_zscore"] = (df[f"{factor_name}_clean"] - mean) / std
return df
if __name__ == "__main__":
# 获取某一日全市场多个标的的日K线计算收益率因子
# 模拟获取 A 股部分股票的收益率表现
symbols = ["600519.SH", "000001.SZ", "000858.SZ", "300750.SZ", "601318.SH"]
print("[*] 正在获取行情并计算原始因子数据...")
raw_data = []
for s in symbols:
df = qd.klines.get(symbol=s, period="1d", limit=2, to_dataframe=True)
if df is not None and len(df) >= 2:
# 简单计算前一日到今日的收益率,作为我们的“日收益率因子”
ret = (float(df.iloc[-1]["close"]) - float(df.iloc[0]["close"])) / float(df.iloc[0]["close"])
raw_data.append({"symbol": s, "return_factor": ret})
df_factor = pd.DataFrame(raw_data)
# 假设为了测试,手动加入一极端的异常大值(模拟财报发布后极端暴涨)
df_factor.loc[len(df_factor)] = {"symbol": "ERROR_STOCK", "return_factor": 12.50} # 1250% 的极端收益率
print("\n[+] 原始因子数据(包含异常大值):")
print(df_factor)
# 运行清洗与标准化
df_processed = handle_factor_preprocessing(df_factor, "return_factor")
print("\n[+] 清洗及标准化处理后的因子数据:")
print(df_processed[["symbol", "return_factor", "return_factor_clean", "return_factor_zscore"]])
数据输出样例
经过 MAD 去极值和 Z-Score 转换后,极端的 ERROR_STOCK 的值被截断并平滑,其余股票的因子大小重新归一化至同一数量级:
[+] 原始因子数据(包含异常大值):
symbol return_factor
0 600519.SH 0.015200
1 000001.SZ -0.005100
2 000858.SZ 0.021000
3 300750.SZ 0.048200
4 601318.SH 0.002300
5 ERROR_STOCK 12.500000
[+] 清洗及标准化处理后的因子数据:
symbol return_factor return_factor_clean return_factor_zscore
0 600519.SH 0.015200 0.015200 -0.068201
1 000001.SZ -0.005100 -0.005100 -0.915201
2 000858.SZ 0.021000 0.021000 0.173792
3 300750.SZ 0.048200 0.048200 1.308695
4 601318.SH 0.002300 0.002300 -0.606341
5 ERROR_STOCK 12.500000 0.048200 1.308695
AI 编程助手专属提示词
如果您正在 Cursor 中构建完整的因子看板,可直接复用以下 Prompt 扩展:
我目前使用 pandas 为 quantdash 因子数据做标准化处理。
请帮我把上面的 MAD 替换为行业(Industry)中性化的预处理。
要求:
1. 传入一个包含行业分类(industry)字段的 DataFrame。
2. 在每个行业板块内部,分别独立进行因子去极值与 Z-Score 转换,避免不同行业的基准偏差(例如科技股与银行股本身的估值中枢差异)。
总结与三步走指引
- 第一步:获取完整源码。访问官方开源托管仓库获取本文 Demo:https://github.com/quantdash-net/QuantDash。
- 第二步:申请专属密钥。注册获取您的个人免费 API Key:https://quantdash.net/。
- 第三步:查阅开发细节。更多高频行情、多市场 Tick 接口参数:https://docs.quantdash.net/。

