多因子选股模型的因子构造与失效分析

多因子模型
选股
Author

示例笔记

Published

June 1, 2024

摘要

本笔记记录多因子选股模型中常见因子的构造方法、盈利逻辑及失效条件,涵盖估值因子、动量因子和反转因子。

因子构造

估值因子(EP)

\[ EP_t = \frac{Earnings_t}{MarketCap_t} \]

动量因子

\[ Mom_{12,1} = \frac{P_{t-1}}{P_{t-12}} - 1 \]

因子合成

加权方式采用等权合成ICIR加权两种方式:

\[ Score_i = \sum_{k=1}^K w_k \cdot Rank(F_{k,i}) \]

其中 \(w_k\) 为因子权重,\(Rank(\cdot)\) 为横截面排序分位数。

因子测试代码

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# 模拟因子数据
np.random.seed(42)
n_stocks = 1000
n_periods = 252

dates = pd.date_range('2023-01-01', periods=n_periods, freq='D')
factor = np.random.randn(n_stocks)
returns = 0.05 * factor + np.random.randn(n_stocks) * 0.02

# IC 计算
ic = np.corrcoef(factor, returns)[0, 1]
print(f"Rank IC: {ic:.4f}")

# 分组收益
groups = pd.qcut(factor, 5, labels=['Q1(低)', 'Q2', 'Q3', 'Q4', 'Q5(高)'])
group_returns = pd.Series(returns, index=groups).groupby(level=0).mean()

fig, ax = plt.subplots(figsize=(8, 4))
colors = ['#c96442', '#e8927a', '#f0c4a0', '#a8c4d8', '#5a8a9a']
bars = ax.bar(group_returns.index, group_returns.values, color=colors)
ax.set_title('多空组合收益(示例)')
ax.set_ylabel('日均收益 (%)')
ax.axhline(0, color='gray', linestyle='--', linewidth=0.5)
plt.tight_layout()
plt.show()
Rank IC: 0.9240
/tmp/ipykernel_2508/3113493769.py:28: UserWarning: Glyph 20302 (\N{CJK UNIFIED IDEOGRAPH-4F4E}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/tmp/ipykernel_2508/3113493769.py:28: UserWarning: Glyph 39640 (\N{CJK UNIFIED IDEOGRAPH-9AD8}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/tmp/ipykernel_2508/3113493769.py:28: UserWarning: Glyph 26085 (\N{CJK UNIFIED IDEOGRAPH-65E5}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/tmp/ipykernel_2508/3113493769.py:28: UserWarning: Glyph 22343 (\N{CJK UNIFIED IDEOGRAPH-5747}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/tmp/ipykernel_2508/3113493769.py:28: UserWarning: Glyph 25910 (\N{CJK UNIFIED IDEOGRAPH-6536}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/tmp/ipykernel_2508/3113493769.py:28: UserWarning: Glyph 30410 (\N{CJK UNIFIED IDEOGRAPH-76CA}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/tmp/ipykernel_2508/3113493769.py:28: UserWarning: Glyph 22810 (\N{CJK UNIFIED IDEOGRAPH-591A}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/tmp/ipykernel_2508/3113493769.py:28: UserWarning: Glyph 31354 (\N{CJK UNIFIED IDEOGRAPH-7A7A}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/tmp/ipykernel_2508/3113493769.py:28: UserWarning: Glyph 32452 (\N{CJK UNIFIED IDEOGRAPH-7EC4}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/tmp/ipykernel_2508/3113493769.py:28: UserWarning: Glyph 21512 (\N{CJK UNIFIED IDEOGRAPH-5408}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/tmp/ipykernel_2508/3113493769.py:28: UserWarning: Glyph 65288 (\N{FULLWIDTH LEFT PARENTHESIS}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/tmp/ipykernel_2508/3113493769.py:28: UserWarning: Glyph 31034 (\N{CJK UNIFIED IDEOGRAPH-793A}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/tmp/ipykernel_2508/3113493769.py:28: UserWarning: Glyph 20363 (\N{CJK UNIFIED IDEOGRAPH-4F8B}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/tmp/ipykernel_2508/3113493769.py:28: UserWarning: Glyph 65289 (\N{FULLWIDTH RIGHT PARENTHESIS}) missing from font(s) DejaVu Sans.
  plt.tight_layout()
/home/runner/.local/lib/python3.12/site-packages/IPython/core/pylabtools.py:158: UserWarning: Glyph 26085 (\N{CJK UNIFIED IDEOGRAPH-65E5}) missing from font(s) DejaVu Sans.
  fig.canvas.print_figure(bytes_io, **kw)
/home/runner/.local/lib/python3.12/site-packages/IPython/core/pylabtools.py:158: UserWarning: Glyph 22343 (\N{CJK UNIFIED IDEOGRAPH-5747}) missing from font(s) DejaVu Sans.
  fig.canvas.print_figure(bytes_io, **kw)
/home/runner/.local/lib/python3.12/site-packages/IPython/core/pylabtools.py:158: UserWarning: Glyph 25910 (\N{CJK UNIFIED IDEOGRAPH-6536}) missing from font(s) DejaVu Sans.
  fig.canvas.print_figure(bytes_io, **kw)
/home/runner/.local/lib/python3.12/site-packages/IPython/core/pylabtools.py:158: UserWarning: Glyph 30410 (\N{CJK UNIFIED IDEOGRAPH-76CA}) missing from font(s) DejaVu Sans.
  fig.canvas.print_figure(bytes_io, **kw)
/home/runner/.local/lib/python3.12/site-packages/IPython/core/pylabtools.py:158: UserWarning: Glyph 22810 (\N{CJK UNIFIED IDEOGRAPH-591A}) missing from font(s) DejaVu Sans.
  fig.canvas.print_figure(bytes_io, **kw)
/home/runner/.local/lib/python3.12/site-packages/IPython/core/pylabtools.py:158: UserWarning: Glyph 31354 (\N{CJK UNIFIED IDEOGRAPH-7A7A}) missing from font(s) DejaVu Sans.
  fig.canvas.print_figure(bytes_io, **kw)
/home/runner/.local/lib/python3.12/site-packages/IPython/core/pylabtools.py:158: UserWarning: Glyph 32452 (\N{CJK UNIFIED IDEOGRAPH-7EC4}) missing from font(s) DejaVu Sans.
  fig.canvas.print_figure(bytes_io, **kw)
/home/runner/.local/lib/python3.12/site-packages/IPython/core/pylabtools.py:158: UserWarning: Glyph 21512 (\N{CJK UNIFIED IDEOGRAPH-5408}) missing from font(s) DejaVu Sans.
  fig.canvas.print_figure(bytes_io, **kw)
/home/runner/.local/lib/python3.12/site-packages/IPython/core/pylabtools.py:158: UserWarning: Glyph 65288 (\N{FULLWIDTH LEFT PARENTHESIS}) missing from font(s) DejaVu Sans.
  fig.canvas.print_figure(bytes_io, **kw)
/home/runner/.local/lib/python3.12/site-packages/IPython/core/pylabtools.py:158: UserWarning: Glyph 31034 (\N{CJK UNIFIED IDEOGRAPH-793A}) missing from font(s) DejaVu Sans.
  fig.canvas.print_figure(bytes_io, **kw)
/home/runner/.local/lib/python3.12/site-packages/IPython/core/pylabtools.py:158: UserWarning: Glyph 20363 (\N{CJK UNIFIED IDEOGRAPH-4F8B}) missing from font(s) DejaVu Sans.
  fig.canvas.print_figure(bytes_io, **kw)
/home/runner/.local/lib/python3.12/site-packages/IPython/core/pylabtools.py:158: UserWarning: Glyph 65289 (\N{FULLWIDTH RIGHT PARENTHESIS}) missing from font(s) DejaVu Sans.
  fig.canvas.print_figure(bytes_io, **kw)
/home/runner/.local/lib/python3.12/site-packages/IPython/core/pylabtools.py:158: UserWarning: Glyph 20302 (\N{CJK UNIFIED IDEOGRAPH-4F4E}) missing from font(s) DejaVu Sans.
  fig.canvas.print_figure(bytes_io, **kw)
/home/runner/.local/lib/python3.12/site-packages/IPython/core/pylabtools.py:158: UserWarning: Glyph 39640 (\N{CJK UNIFIED IDEOGRAPH-9AD8}) missing from font(s) DejaVu Sans.
  fig.canvas.print_figure(bytes_io, **kw)

数据一览

因子 IC均值 ICIR 年化超额 换手率
估值(EP) 0.042 0.76 6.8% 8%/月
动量(Mom) 0.038 0.52 5.2% 15%/月
反转(Rev) -0.035 -0.61 -4.1% 25%/月
合成(等权) 0.052 0.89 8.2% 12%/月

失效条件

  1. 估值因子:在流动性紧缩期(如2020年3月),低估值股遭无差别抛售,EP因子失效
  2. 动量因子:在市场急跌反弹时(V型反转),动量因子出现大幅回撤
  3. 反转因子:在趋势市(单边上涨)中,反转因子持续亏损
  4. 合成因子:当各因子同时失效(如2021年核心资产抱团),多因子组合也难以避险

策略限制:以上为示例数据,实盘中需考虑交易成本、冲击成本、以及因子之间的相关性变化。

参考文献

refs.bib(后续添加)