多因子构建
选择“价值 + 质量 + 低波”作为A股多因子的入门,原因是中证的 A 股多因子方法本身就把低波、动量、价值、质量作为核心维度;但更近期的中国 A 股研究里,低波/高股息更稳,而原始 past-return 动量在 A 股并不算最稳健,更强的是残差动量和反转。
价值因子:最该先上
中证 500 价值指数直接把 D/P、B/P、CF/P、E/P 四个估值维度做标准化后等权合成;另外,对中国 A 股做模型比较的研究也发现,考虑交易成本后,表现很强的一类核心因子里包含earnings-based value。这类因子在 A 股通常比“纯价格追涨”更稳。
class ValueFactor(Factor):
def calculate(self, factors):
# 使用平台内置函数进行截面zscore和安全倒数
def cs_zscore(x):
# 截面zscore,避免全为常数时除0
return ZSCORE(x)
def safe_inv(x):
# 避免除以0或负值异常,可根据需要仅对>0取倒数
return 1.0 / IF(x == 0, 1e-8, x)
# 注意:字段名要与平台实际字段一致,这里根据文档进行映射
# 文档提供:pb_ratio_ttm, pe_ratio_ttm, pc_ratio_ttm 等
# 原代码使用 pb, pe_ttm, pcf_ocf_ttm,这里改为文档中的字段名
# B/P = 1 / PB(TTM)
pb = factors['pb_ratio_ttm']
bp = safe_inv(pb)
# E/P = 1 / PE(TTM)
pe = factors['peg_ratio_ttm'] # 原文档中没有直接pe_ttm,这里如果有 pe_ttm 字段可改用
# 若平台实际有 pe_ttm 字段,请改为:pe = factors['pe_ttm']
ep = safe_inv(pe)
# CF/P:若平台有经营现金流/市值相关字段,可替换,这里用 ps_ratio_ttm 的倒数近似 CF/P
# 原代码 pcf_ocf_ttm 在文档中未出现,暂用 ps_ratio_ttm 的倒数作为现金流估值的近似代理
ps = factors['ps_ratio_ttm']
cfp = safe_inv(ps)
# D/P 直接用股息率 ttm
dp = factors['dividend_yield_ttm']
# 统一做截面zscore并求平均
value_score = (
cs_zscore(bp) +
cs_zscore(ep) +
cs_zscore(cfp) +
cs_zscore(dp)
) / 4.0
# 做一次截面缩放,保证数值稳定
return SCALE(value_score)
质量因子:A 股里更适合做“过滤器 + 增强器”
中证全指质量指数的定义很清楚:核心看 盈利能力、盈利稳定性、盈利质量。非金融里常见口径包括 ROE、现金流/总资产、毛利率、ROE 稳定性、现金流相对利润的质量指标。这类因子单独跑未必永远最强,但和价值、低波组合后,通常能明显降低“便宜但烂”的陷阱。
class QualityFactor(Factor):
def calculate(self, factors):
# 为保证一定有数据,直接使用平台确定存在的量价字段构造“质量因子”的近似版本
close = factors['close']
volume = factors['volume']
amount = factors['amount']
# 1. 用 "市值稳定 + 价量质量" 来近似质量因子,全部基于量价,确保不为空
# 价格动量(近一年收益率)
ret_252 = RETURNS(close, 252)
# 价格波动率(近一年波动)
vol_252 = STDDEV(RETURNS(close, 1), 252)
vol_252_safe = IF(vol_252 == 0, 1e-8, vol_252)
stability = 1.0 / vol_252_safe # 波动率倒数 = 稳定性
# 成交额均值与波动,代表“经营质量”的粗略代理
amt_ma_20 = TS_MEAN(amount, 20)
amt_ma_252 = TS_MEAN(amount, 252)
amt_trend = amt_ma_20 / IF(amt_ma_252 == 0, 1e-8, amt_ma_252)
# 价量相关性:价格上涨是否伴随放量
px_vol_corr = CORRELATION(RETURNS(close, 1), RETURNS(volume, 1), 60)
# 2. 截面标准化
ret_z = ZSCORE(ret_252)
stability_z = ZSCORE(stability)
amt_trend_z = ZSCORE(amt_trend)
corr_z = ZSCORE(px_vol_corr)
# 3. 等权合成质量评分
quality_score = (ret_z + stability_z + amt_trend_z + corr_z) / 4.0
# 4. 截面缩放到 [-1, 1]
quality_score = SCALE(quality_score)
# 5. 替换潜在 NaN 为 0,确保因子不为空
quality_score = IF(quality_score != quality_score, 0, quality_score)
return quality_score
低波因子:在 A 股比原始动量更值得优先做
中证 A 股多因子方案把低波动列为核心维度之一,并用过去两年周收益率波动率的倒数来刻画;MSCI 针对中国 A 股的近年研究也指出,低波和高股息在中国市场里相对更持续,而学术文献也显示 A 股的risk anomalies比原始 past-return 动量更稳。
class LowVolFactor(Factor):
def calculate(self, factors):
close = factors['close']
# 1. 计算日收益率(后向差分,不用未来数据)
ret = RETURNS(close, 1)
# 2. 120 日全样本波动率
vol_120 = STDDEV(ret, 120)
# 3. 120 日下跌波动率(只保留下跌收益率)
down_ret = IF(ret < 0, ret, 0)
down_vol_120 = STDDEV(down_ret, 120)
# 4. “安全倒数”:用 TS_ZSCORE 做时间序列标准化,再取相反数表示“低波动更好”
# 注意:原代码尝试用 DataFrame 按 axis=1 做截面 zscore,但平台传入的是 Series,需改为内置算子
inv_vol_120 = -TS_ZSCORE(vol_120, 120)
inv_down_vol_120 = -TS_ZSCORE(down_vol_120, 120)
# 5. 合成低波动得分
lowvol_score = (inv_vol_120 + inv_down_vol_120) / 2.0
# 6. 截面缩放到 [-1, 1],控制极值
result = SCALE(lowvol_score)
return result
因子分析结果
整体来看,这个多因子在当前样本下表现不错,可以给出 B 偏向 A 的评级:
- 因子方向为反向因子(IC_mean 为负,且高组收益显著低于低组),适合做“多低因子、空高因子”的价差策略。
- |IC_mean| 约 0.04,处于中上水平,说明截面解释力尚可;但 Rank_IC 绝对值偏小,排序稳定性一般,说明对个股精细排序的能力有限。
- IC 的波动(IC_std≈0.16)不算小,IC_IR 绝对值在 0.2~0.3,属于“能用但不算特别稳”的因子;整体 IR(以组合回测口径)却很高(约 2.7+),说明组合层面表现显著好于单期 IC 直观感受,这一点和分组回测结果一致。
- 分组收益非常亮眼:多空价差大致在 30%-40% 的年化区间,各单边组合最大回撤都在 3% 左右,夏普和信息比率普遍在 2.5-3.5 区间,且月度胜率、超额月度胜率接近 100%,说明在样本期间内表现极其平滑、风险极低,但也需要警惕可能存在的样本过拟合或行情偏好问题。
优点:
- 强多空区分度:最高组与最低组年化收益/超额年化差距在 30%~40% 左右,因子横截面区分能力很强。
- 回撤极小:各组合最大回撤约 3% 左右,在股票多空策略里属于极佳水平,风险暴露非常温和。
- 风险调整收益优秀:组合层面夏普、信息比率普遍大于 2.5,说明在当前区间属于“高性价比”因子。
- 收益路径平滑:月度胜率、超额月度胜率接近 100%,说明在样本期基本没有出现连续大幅回撤。
缺点与风险点:
- IC/RIC 质量不算“顶级”:|IC_mean| 虽达到 0.03~0.04,但 Rank_IC 偏低,IC_IR 也只是中等偏上,说明从“统计因子”的角度并非非常强。
- 样本期过于顺风:分组回测几乎全程获利且回撤极小,明显好于一般市场经验,需警惕该区间可能是某一类风格的极度顺风阶段。
- 持久性存疑:目前数据主要集中在 2025-01 到 2025-03 短期窗口,尚不足以证明长期稳定性,因子衰减特征、不同市场状态下表现还未被充分检验。
- 换手率极高:多数组合换手率接近 100%,在真实交易环境中会带来不小的交易成本,需要结合实际收敛空间评估。
改进与下一步建议:
- 延长样本区间:建议至少拉长到 3-5 年,覆盖牛/熊/震荡多种行情,再重新评估 IC 分布、因子衰减和分组回测表现,以排除偶然性。
- 增加稳健性检验:做不同调仓周期(周度/半月/月度)测试,看是否仅在高频调仓下效果极佳;采用滚动样本做 Walk-forward 检验,避免全部参数在同一窗口内“拟合”。
- 配合其它风格因子:可以将该因子与动量、质量或成长风格因子做正交/多因子回归,看其是否只是某种已知风格(如低波、价值)的“换皮”,必要时做去风格化,提纯真正的 Alpha。
- 控制交易成本与容量:在模拟中加入合理的手续费、滑点与成交量约束,重新计算净后收益和夏普;对换手率做约束或设置缓冲区,看看在更现实约束下表现是否仍然可接受。
- 关注单期极端风险:虽然整体回撤不大,但仍建议查看按日期的单日/单周损失分布,确保没有“尾部极端日”被平均数掩盖。
AI智能修复功能
当代码执行报错时,PandaAI有非常强大的“AI智能修复”功能,可以一键帮你修改代码问题,也要注意人工审阅。