机器学习因子库
🧠 Alpha 因子 = 解释股票超额收益的因素 —— 找到这些因子,就能构建量化策略。
🎯 因子分类总览
| 类别 | 因子数 | 周期 | 难度 | 收益贡献 |
|---|---|---|---|---|
| 量价因子 | 30+ | 日 / 周 / 月 | ⭐⭐ | ⭐⭐⭐⭐⭐ |
| 财务因子 | 20+ | 季 / 年 | ⭐ | ⭐⭐⭐ |
| 情绪因子 | 15+ | 日 | ⭐⭐⭐ | ⭐⭐⭐ |
| 另类因子 | 20+ | 日 / 周 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| 宏观因子 | 10+ | 日 / 月 | ⭐⭐ | ⭐⭐ |
| 事件因子 | 10+ | 不定期 | ⭐⭐ | ⭐⭐⭐ |
📊 一、量价因子
📈 价格因子
| 因子 | 公式 | 含义 |
|---|---|---|
| 1 日动量 | close / close.shift(1) - 1 | 短期反转 |
| 5 日动量 | close / close.shift(5) - 1 | 周动量 |
| 20 日动量 | close / close.shift(20) - 1 | 月动量 |
| 60 日动量 | close / close.shift(60) - 1 | 季动量 |
| 120 日动量 | close / close.shift(120) - 1 | 半年动量 |
| 250 日动量 | close / close.shift(250) - 1 | 年动量 |
| 12-1 月动量 | close / close.shift(252) / close.shift(21) - 1 | 经典 12-1 因子 |
| 反转因子 | -ret_1d | 1 日反转 |
| 5 日反转 | -ret_5d | 周反转 |
| 距离 52 周高点 | close / high.rolling(252).max() - 1 | 突破因子 |
| 距离 52 周低点 | close / low.rolling(252).min() - 1 | 反转因子 |
| 价格 / 5 日均线偏离 | close / ma5 - 1 | 短期偏离 |
| 价格 / 20 日均线偏离 | close / ma20 - 1 | 中期偏离 |
| 价格 / 60 日均线偏离 | close / ma60 - 1 | 长期偏离 |
| 价格 / 200 日均线偏离 | close / ma200 - 1 | 经典长期因子 |
| 12 月新高 | (close == high.rolling(252).max()).astype(int) | 突破信号 |
| 52 周新高距离 | high.rolling(252).max() / close - 1 | 反向因子 |
📉 均线因子
| 因子 | 公式 | 含义 |
|---|---|---|
| MA5 / MA20 比率 | ma5 / ma20 | 短期趋势 |
| MA20 / MA60 比率 | ma20 / ma60 | 中期趋势 |
| MA60 / MA250 比率 | ma60 / ma250 | 长期趋势 |
| 5 日均线上穿 | (ma5 > ma20).astype(int) | 金叉信号 |
| 20 日均线上穿 | (ma20 > ma60).astype(int) | 中期金叉 |
| 均线发散度 | (ma5 - ma20) / ma20 | 趋势强度 |
| MA120 距离 | close / ma120 - 1 | 长期偏离 |
| MA250 距离 | close / ma250 - 1 | 牛熊指标 |
| MA250 上方 | (close > ma250).astype(int) | 牛熊市分界 |
📊 波动率因子
| 因子 | 公式 | 含义 |
|---|---|---|
| 5 日波动率 | return.rolling(5).std() | 短期波动 |
| 20 日波动率 | return.rolling(20).std() | 月波动率 |
| 60 日波动率 | return.rolling(60).std() | 季波动率 |
| 波动率变化 | vol_5d / vol_20d - 1 | 波动率变化 |
| 波动率 z-score | (vol_20d - mean) / std | 异常波动 |
| 下行波动率 | return[return < 0].std() | 风险 |
| 上下波动比 | vol_up / vol_down | 趋势稳定性 |
| BOLL 上轨距离 | (close - boll_upper) / close | 突破 |
| BOLL 下轨距离 | (close - boll_lower) / close | 反转 |
📈 技术指标因子
| 因子 | 公式 | 含义 |
|---|---|---|
| RSI | 100 - 100 / (1 + avg_gain / avg_loss) | 超买超卖 |
| MACD | ema12 - ema26 | 趋势动量 |
| MACD 信号 | macd - signal | 交叉信号 |
| KDJ-K | K = 2/3 * K_prev + 1/3 * RSV | 短线 |
| KDJ-D | D = 2/3 * D_prev + 1/3 * K | 短线 |
| KDJ-J | 3K - 2D | 短线 |
| ADX | 100 * abs(DX_avg) / DX_avg | 趋势强度 |
| CCI | (TP - MA) / (0.015 * MD) | 顺势指标 |
| ATR | TR.rolling(n).mean() | 真实波幅 |
| OBV | cumsum(volume * sign(close_diff)) | 资金流 |
📊 量价配合因子
| 因子 | 公式 | 含义 |
|---|---|---|
| 量比 | volume / volume.rolling(5).mean() | 成交量异常 |
| 换手率 | volume / total_shares | 流通性 |
| 量价同向 | sign(close_diff) * sign(volume_diff) | 量价配合 |
| 5 日均量 / 20 日均量 | vol5 / vol20 | 成交量趋势 |
| 量价背离 | close_diff * -sign(volume_diff) | 背离信号 |
| 大单占比 | (big_trade_volume / total_volume) | 主力 |
| 资金流(估算) | (close - open) * volume | 资金流入 |
🔧 完整 Python 实现
python
import pandas as pd
import numpy as np
class PriceVolumeFactors:
"""量价因子库"""
def __init__(self, df):
self.df = df.copy()
self._compute_basic()
def _compute_basic(self):
"""基础计算"""
df = self.df
df['return_1d'] = df['close'].pct_change(1)
df['return_5d'] = df['close'].pct_change(5)
df['return_10d'] = df['close'].pct_change(10)
df['return_20d'] = df['close'].pct_change(20)
df['return_60d'] = df['close'].pct_change(60)
df['return_120d'] = df['close'].pct_change(120)
df['return_250d'] = df['close'].pct_change(250)
# 均线
for n in [5, 10, 20, 60, 120, 250]:
df[f'ma{n}'] = df['close'].rolling(n).mean()
# 波动率
for n in [5, 10, 20, 60]:
df[f'vol_{n}d'] = df['return_1d'].rolling(n).std()
def momentum_factors(self):
"""动量因子"""
df = self.df
# 经典 12-1 月动量
df['mom_12_1'] = (df['close'].shift(21) / df['close'].shift(252) - 1)
return df
def mean_reversion(self):
"""均值回复"""
df = self.df
# 短期反转
df['reversal_1d'] = -df['return_1d']
# 周反转
df['reversal_5d'] = -df['return_5d']
return df
def volatility_factors(self):
"""波动率因子"""
df = self.df
# 波动率变化
df['vol_change'] = df['vol_5d'] / df['vol_20d'] - 1
# 波动率 z-score
vol_mean = df['vol_20d'].rolling(60).mean()
vol_std = df['vol_20d'].rolling(60).std()
df['vol_zscore'] = (df['vol_20d'] - vol_mean) / vol_std
return df
def ma_deviation(self):
"""均线偏离"""
df = self.df
df['ma5_dev'] = (df['close'] - df['ma5']) / df['ma5']
df['ma20_dev'] = (df['close'] - df['ma20']) / df['ma20']
df['ma60_dev'] = (df['close'] - df['ma60']) / df['ma60']
return df
def rsi_factor(self):
"""RSI 因子"""
df = self.df
delta = df['close'].diff()
gain = delta.where(delta > 0, 0)
loss = (-delta).where(delta < 0, 0)
avg_gain = gain.rolling(14).mean()
avg_loss = loss.rolling(14).mean()
rs = avg_gain / (avg_loss + 1e-9)
df['rsi'] = 100 - 100 / (1 + rs)
# 极端 RSI 反转
df['rsi_extreme'] = (df['rsi'] < 20).astype(int) - (df['rsi'] > 80).astype(int)
return df
def macd_factor(self):
"""MACD 因子"""
df = self.df
ema12 = df['close'].ewm(span=12).mean()
ema26 = df['close'].ewm(span=26).mean()
df['macd'] = ema12 - ema26
df['macd_signal'] = df['macd'].ewm(span=9).mean()
df['macd_hist'] = (df['macd'] - df['macd_signal']) * 2
return df
def volume_factors(self):
"""成交量因子"""
df = self.df
df['vol_ratio_5_20'] = df['volume'].rolling(5).mean() / df['volume'].rolling(20).mean()
# 换手率(需流通股本数据)
if 'float_share' in df.columns:
df['turnover'] = df['volume'] / df['float_share']
# 量价配合
df['price_volume_corr'] = df['close'].pct_change().rolling(20).corr(
df['volume'].pct_change()
)
return df
def all_factors(self):
"""所有量价因子"""
self.momentum_factors()
self.mean_reversion()
self.volatility_factors()
self.ma_deviation()
self.rsi_factor()
self.macd_factor()
self.volume_factors()
return self.df
# 使用
import akshare as ak
df = ak.stock_zh_a_hist(symbol='600519', start_date='20200101', end_date='20241231', adjust='qfq')
df = df.rename(columns={
'日期': 'date', '开盘': 'open', '最高': 'high',
'最低': 'low', '收盘': 'close', '成交量': 'volume'
})
factor_engine = PriceVolumeFactors(df)
df_with_factors = factor_engine.all_factors()
print(df_with_factors.columns.tolist())📊 二、财务因子
💰 估值因子
| 因子 | 公式 | 含义 |
|---|---|---|
| PE-TTM | price / EPS_TTM | 市盈率 |
| PB | price / book_value | 市净率 |
| PS-TTM | market_cap / revenue | 市销率 |
| PCF | market_cap / operating_cash_flow | 市现率 |
| EV/EBITDA | (market_cap + debt - cash) / EBITDA | 企业价值倍数 |
| PEG | PE / profit_growth | 增长调整后 PE |
| 股息率 | dividend / price | 现金回报 |
| 市值 | log(market_cap) | 规模因子 |
| 对数市值 | np.log(market_cap) | 经典规模因子 |
| A 股流通市值 | log(free_float_market_cap) | 流通规模 |
📈 成长因子
| 因子 | 公式 | 含义 |
|---|---|---|
| 营收增速 1Y | revenue / revenue.shift(4) - 1 | 同比增长 |
| 净利润增速 1Y | net_profit / net_profit.shift(4) - 1 | 盈利增长 |
| ROE 增速 | roe / roe.shift(4) - 1 | 盈利质量提升 |
| EPS 增速 | eps / eps.shift(4) - 1 | 每股收益增长 |
| 3 年复合增速 | (X / X.shift(12)) ** (1/3) - 1 | 长期增长 |
| 5 年复合增速 | (X / X.shift(20)) ** (1/5) - 1 | 5 年增长 |
💎 质量因子
| 因子 | 公式 | 含义 |
|---|---|---|
| ROE | net_profit / equity | 净资产收益率 |
| ROA | net_profit / total_assets | 总资产回报 |
| ROIC | NOPAT / invested_capital | 投入资本回报 |
| 毛利率 | (revenue - cost) / revenue | 毛利率 |
| 净利率 | net_profit / revenue | 净利率 |
| 营业利润率 | operating_profit / revenue | 营业利润率 |
| 资产负债率 | total_debt / total_assets | 财务杠杆 |
| 流动比率 | current_assets / current_liab | 短期偿债 |
| 速动比率 | (current_assets - inventory) / current_liab | 速动偿债 |
| 利息保障倍数 | EBIT / interest_expense | 偿债能力 |
| 现金流 / 净利润 | OCF / net_profit | 盈利质量 |
| 应收 / 总资产 | AR / total_assets | 应收风险 |
🔧 财务因子计算
python
import pandas as pd
import numpy as np
import tushare as ts
def get_financial_factors(stock_code='600519.SH'):
"""获取 A 股财务因子"""
pro = ts.pro_api('YOUR_TOKEN')
# 获取财务数据
income = pro.income(ts_code=stock_code, period='20241231')
balance = pro.balancesheet(ts_code=stock_code, period='20241231')
cashflow = pro.cashflow(ts_code=stock_code, period='20241231')
daily = pro.daily(ts_code=stock_code, start_date='20241201', end_date='20241231')
factors = {}
# 估值因子
price = daily['close'].iloc[-1]
eps = income.iloc[0]['n_income'] / 1e8 # 简化为总利润
factors['PE'] = price / (eps / daily.iloc[0]['total_share']) # 简化
factors['PB'] = price / (balance.iloc[0]['total_hldr_eqy_exc_min_int'] / daily.iloc[0]['total_share'])
# 质量因子
factors['ROE'] = income.iloc[0]['n_income'] / balance.iloc[0]['total_hldr_eqy_exc_min_int']
factors['DebtRatio'] = balance.iloc[0]['total_liab'] / balance.iloc[0]['total_assets']
factors['GrossMargin'] = (income.iloc[0]['revenue'] - income.iloc[0]['oper_cost']) / income.iloc[0]['revenue']
return factors📊 三、情绪因子
📊 投资者情绪
| 因子 | 数据源 | 公式 |
|---|---|---|
| 新增开户数 | 中证登 | 月度新增开户数同比 |
| 百度搜索指数 | 百度 | 关键词搜索量 |
| 微信指数 | 腾讯 | "股票" 搜索量 |
| 雪球关注度 | 雪球 | 个股关注数变化 |
| 股吧情绪 | 东方财富 | 帖子正面 / 负面比例 |
| 融资余额 | 交易所 | 融资余额变化 |
| 融券余额 | 交易所 | 融券余额变化 |
| 北向资金 | 沪深港通 | 净流入 / 净流出 |
| ETF 净申购 | 基金公司 | 净申购 / 净赎回 |
| 新基金发行 | 基金公司 | 月度新发基金规模 |
| 隐含波动率 | 期权 | 50ETF 期权 IV |
| PCR | 期权 | Put/Call 比率 |
| 信用利差 | 债券 | 高收益债利差 |
| 波动率指数 | 50ETF 期权 | 中国 VIX |
🔧 情绪因子实战
python
def get_sentiment_factors():
"""获取市场情绪因子"""
import akshare as ak
factors = {}
# 北向资金
north = ak.stock_hsgt_north_net_flow_in_em(symbol='北上')
factors['north_flow_5d'] = north['value'].head(5).sum()
# 融资融券
margin = ak.stock_margin_underlying_info_szse()
factors['margin_balance'] = margin['rzmr'].iloc[0]
# ETF 净申购
# ...
return factors📊 四、另类因子
🌐 新闻舆情
| 因子 | 数据源 | 说明 |
|---|---|---|
| 新闻情感 | 财经新闻 API | NLP 分析 |
| 公告事件 | 巨潮 | 增持 / 减持 / 业绩预告 |
| 研报评级 | Wind | 买入 / 中性 / 卖出 |
| 社交媒体情绪 | 雪球 / 微博 | 情绪打分 |
| 机构调研 | 投资者关系平台 | 调研频次 |
| 研报目标价 | Wind | 上涨空间 |
📊 分析师预期
| 因子 | 说明 |
|---|---|
| 一致预期 EPS | 分析师预测的 EPS 均值 |
| 预期上调比例 | 上调家数 / 总家数 |
| 预期 PE | 当前价 / 一致预期 EPS |
| 预期增速 | 一致预期未来 3 年增速 |
| 覆盖券商数 | 多少分析师覆盖 |
| 目标价均值 | 分析师目标价均值 |
| 目标价上涨空间 | 目标价 / 当前价 - 1 |
📅 事件因子
| 因子 | 说明 |
|---|---|
| 增持 / 减持 | 股东行为 |
| 回购 | 公司回购 |
| 股权激励 | 高管激励 |
| 业绩预告 | 业绩超预期 / 不及预期 |
| 送转股 | 高送转 |
| 解禁 | 解禁压力 |
| ST | 戴帽 / 摘帽 |
| 重大事件 | 重组、并购 |
📊 五、宏观因子
| 因子 | 频率 | 来源 |
|---|---|---|
| GDP 同比 | 季度 | 统计局 |
| CPI 同比 | 月 | 统计局 |
| PPI 同比 | 月 | 统计局 |
| M2 同比 | 月 | 央行 |
| 社会融资 | 月 | 央行 |
| PMI | 月 | 统计局 |
| LPR | 月 | 央行 |
| 国债收益率 | 日 | 财政部 |
| 汇率 | 日 | 央行 |
| 美元指数 | 日 | 外汇市场 |
📊 六、因子测试
📐 IC 测试
python
import numpy as np
import pandas as pd
from scipy.stats import spearmanr
def factor_ic_test(factor, returns, by='date'):
"""因子 IC 测试"""
# 按日期计算 IC
ic_series = []
for date, group in factor.groupby(by):
f = group.values.flatten()
r = returns.loc[group.index].values.flatten()
if len(f) > 0 and not np.isnan(f).all() and not np.isnan(r).all():
ic, _ = spearmanr(f, r)
ic_series.append({'date': date, 'IC': ic})
ic_df = pd.DataFrame(ic_series)
return ic_df
def evaluate_factor(ic_df):
"""评估因子有效性"""
ic_mean = ic_df['IC'].mean()
ic_std = ic_df['IC'].std()
ic_ir = ic_mean / ic_std if ic_std > 0 else 0
ic_positive_ratio = (ic_df['IC'] > 0).mean()
print(f'IC 均值: {ic_mean:.4f}')
print(f'IC 标准差: {ic_std:.4f}')
print(f'IC IR: {ic_ir:.4f}')
print(f'IC > 0 占比: {ic_positive_ratio:.2%}')
# 判断标准
if ic_abs := abs(ic_mean):
if ic_abs > 0.05 and ic_ir > 0.5:
print('✅ 强有效因子')
elif ic_abs > 0.03 and ic_ir > 0.3:
print('⚠️ 中等有效')
else:
print('❌ 弱效或无效')📐 分层回测
python
def layered_backtest(factor, returns, n_groups=5):
"""分层回测(多空对冲)"""
factor_with_ret = pd.DataFrame({
'factor': factor,
'return': returns
}).dropna()
# 分 5 组
factor_with_ret['group'] = pd.qcut(
factor_with_ret['factor'],
n_groups,
labels=False
)
# 计算每组平均收益
group_returns = factor_with_ret.groupby('group')['return'].mean()
# 多空收益
long_short = group_returns.iloc[-1] - group_returns.iloc[0]
print('各组平均收益:')
print(group_returns)
print(f'\n多空收益: {long_short:.4%}')
return group_returns, long_short📐 完整因子测试流程
python
class FactorEvaluator:
"""因子评估器"""
def __init__(self, factor_data, return_data):
self.factor = factor_data
self.returns = return_data
def run_full_test(self):
"""完整因子测试"""
results = {}
# 1. IC 测试
ic_df = factor_ic_test(self.factor, self.returns)
results['ic'] = evaluate_factor(ic_df)
# 2. 分层回测
group_ret, ls_ret = layered_backtest(self.factor, self.returns)
results['long_short'] = ls_ret
# 3. 多空累计收益
cum_ret = self.returns.groupby('group').apply(
lambda x: (1 + x).cumprod()
)
# 4. 画图
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 6))
for g, data in cum_ret.groupby(level=0):
plt.plot(data.values, label=f'Group {g}')
plt.legend()
plt.title('因子分层累计收益')
plt.show()
return results📊 七、因子组合
📈 多因子合成
python
class MultiFactorModel:
"""多因子合成"""
def __init__(self, factors_df, returns):
"""
factors_df: DataFrame, 包含多个因子列
returns: 目标收益
"""
self.factors = factors_df
self.returns = returns
def equal_weight(self):
"""等权组合"""
scores = self.factors.rank(pct=True).mean(axis=1)
return scores
def ic_weighted(self, ic_values):
"""IC 加权"""
weights = np.abs(ic_values)
weights = weights / weights.sum()
scores = (self.factors.rank(pct=True) * weights).sum(axis=1)
return scores
def ml_weighted(self):
"""机器学习加权"""
from sklearn.ensemble import GradientBoostingRegressor
# 训练
X = self.factors.fillna(0)
y = self.returns.fillna(0)
model = GradientBoostingRegressor(n_estimators=100, max_depth=3)
model.fit(X, y)
# 预测
scores = pd.Series(
model.predict(X),
index=X.index
)
return scores
def backtest(self, scores, top_pct=0.1):
"""回测:买入评分最高的 top_pct"""
threshold = scores.quantile(1 - top_pct)
selected = scores > threshold
# 计算组合收益
portfolio_returns = self.returns[selected].mean(axis=1)
cum_ret = (1 + portfolio_returns.fillna(0)).cumprod()
# 基准
bench_returns = self.returns.mean(axis=1)
bench_cum = (1 + bench_returns.fillna(0)).cumprod()
return {
'strategy_cumret': cum_ret,
'benchmark_cumret': bench_cum,
'excess_return': cum_ret.iloc[-1] - bench_cum.iloc[-1]
}📊 八、因子衰减
📉 因子生命周期
每个因子都有生命周期:
- 发现期(高收益)
- 拥挤期(收益下降)
- 失效期(接近 0)
📌 应对策略
- 定期重训:每季度更新因子
- 因子轮动:剔除失效因子
- 多因子组合:避免单一因子失效
- 样本外验证:保留 20% 数据
📊 九、Alpha 库速查
📋 推荐因子组合(5 因子)
| 因子 | 权重 | 来源 |
|---|---|---|
| 12-1 月动量 | 30% | 价格 |
| 盈利质量(ROE) | 25% | 财务 |
| 分析师上调 | 15% | 情绪 |
| 低波动率 | 15% | 价格 |
| 市值 | 15% | 价格 |
📋 不同市场风格
| 风格 | 因子 |
|---|---|
| 价值 | PE / PB / EV-EBITDA / 股息率 |
| 成长 | 营收增速 / 净利润增速 / PEG |
| 质量 | ROE / ROIC / 毛利率 |
| 动量 | 12-1 月动量 / 短期反转 |
| 小盘 | 流通市值(越小越偏好) |
| 低波 | 波动率(越低越偏好) |
| 高分红 | 股息率 |
| 分析师预期 | 预期 EPS / 预期上调 |
📖 相关阅读
- AI 选股模型 - 完整 AI 选股
- 量化回测教程
- 宏观数据 API 教程
- 行业研究框架
- 财务分析
来源
- 证监会公开公告
- 上交所交易规则
- 深交所 / 北交所规则
- 中国证券业协会(SAC)、中国证券投资基金业协会(AMAC)公开资料
- 国家金融监督管理总局、人社部、财政部、税务总局公开资料
💡 数据截至 2026-08;具体规则以交易所/监管机构最新公告为准。