【因子挖掘】A股多因子探索:价值 + 质量 + 低波
  JJ 18天前 172 0

多因子构建

选择“价值 + 质量 + 低波”作为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

6aa0fdaa370b6ec5eda2044a354b2bb0.png

因子分析结果

整体来看,这个多因子在当前样本下表现不错,可以给出 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。
  • 控制交易成本与容量:在模拟中加入合理的手续费、滑点与成交量约束,重新计算净后收益和夏普;对换手率做约束或设置缓冲区,看看在更现实约束下表现是否仍然可接受。
  • 关注单期极端风险:虽然整体回撤不大,但仍建议查看按日期的单日/单周损失分布,确保没有“尾部极端日”被平均数掩盖。

cc3a5da20928b38c38ec4f4dc7eea801.png

AI智能修复功能

当代码执行报错时,PandaAI有非常强大的“AI智能修复”功能,可以一键帮你修改代码问题,也要注意人工审阅。
image.png

最后一次编辑于 18天前 1

暂无评论

推荐阅读