Skip to main content

因子选股策略

因子选股是量化投资中最主流的策略类型之一,通过多个量化指标(因子)对股票进行评分和排序,选择综合得分最高的股票。


什么是因子?

因子就是能够解释股票收益差异的某种特征变量。例如:

因子类别因子名称计算方式逻辑
动量因子过去N日收益率close.pct_change(N)强者恒强
波动率因子收益率标准差returns.rolling(N).std()低波动反而长期收益高
价值因子市盈率 PE股价 / 每股收益低估值股票可能被低估
质量因子ROE净利润 / 净资产盈利好的公司长期更优
规模因子市值股价 × 总股本小市值股票长期收益更高
流动性因子换手率成交量 / 流通股本活跃的股票可能更好

单因子测试

import pandas as pd
import numpy as np

def momentum_factor(df, period=20):
"""
动量因子:过去 N 天的累计收益率
"""
return df['close'].pct_change(period)

def volatility_factor(df, period=20):
"""
波动率因子:过去 N 天的收益率标准差
"""
returns = df['close'].pct_change()
return returns.rolling(period).std()

def volume_factor(df, period=20):
"""
成交量因子:过去 N 天的平均成交量变化
"""
return df['volume'].pct_change(period)

多因子打分模型

def multi_factor_score(df):
"""
多因子打分模型

计算多个因子,然后加权合成一个综合得分。
得分越高 = 股票越好
"""
# 1. 计算各因子
df['momentum'] = df['close'].pct_change(20) # 动量因子
df['volatility'] = df['close'].pct_change().rolling(20).std() # 波动率因子

# 2. 因子标准化(排名法)
# 对每个因子进行排名,排名越靠前分数越高
df['momentum_rank'] = df['momentum'].rank(pct=True)
df['volatility_rank'] = (1 - df['volatility']).rank(pct=True) # 低波动更好

# 3. 合成综合得分(等权或自定义权重)
df['score'] = (df['momentum_rank'] * 0.5 +
df['volatility_rank'] * 0.5)

return df

因子选股 + 择时框架

def factor_stock_selection(stock_pool, date, top_n=10):
"""
在每个调仓日,对所有候选股票打分,选择前 N 只

参数:
stock_pool: dict {code: df} 候选股票池
date: 调仓日期
top_n: 选择前多少只
"""
scores = {}

for code, df in stock_pool.items():
if date not in df.index:
continue

# 计算该股票的综合得分
df_scored = multi_factor_score(df)
score = df_scored.loc[date, 'score'] if date in df_scored.index else np.nan
scores[code] = score

# 按得分排序,选前 N 只
scores_series = pd.Series(scores).dropna().sort_values(ascending=False)
selected = scores_series.head(top_n)

return selected

组合回测

def factor_strategy_backtest(stock_pool, rebalance_freq='M', top_n=10,
initial_capital=100000):
"""
因子选股策略回测

参数:
stock_pool: 股票池
rebalance_freq: 调仓频率('M'=每月, 'W'=每周)
top_n: 持仓股票数
"""
# 获取所有调仓日期
first_date = min(df.index[0] for df in stock_pool.values())
last_date = max(df.index[-1] for df in stock_pool.values())
rebalance_dates = pd.date_range(first_date, last_date, freq=rebalance_freq)

portfolio_values = []
current_holdings = {}
capital = initial_capital

for date in rebalance_dates:
# 卖出旧持仓
for code, shares in current_holdings.items():
if date in stock_pool[code].index:
price = stock_pool[code].loc[date, 'close']
capital += shares * price
current_holdings = {}

# 选股
selected = factor_stock_selection(stock_pool, date, top_n)

# 等权买入
per_stock_capital = capital / len(selected)
for code in selected.index:
price = stock_pool[code].loc[date, 'close']
shares = per_stock_capital // price
current_holdings[code] = shares
capital -= shares * price

return portfolio_values

常见因子库总结

因子方向A 股有效性
动量正向⭐⭐⭐
低波动低波优先⭐⭐⭐⭐
小市值小盘优先⭐⭐⭐⭐
价值(低PE)低PE优先⭐⭐⭐
质量(高ROE)高ROE优先⭐⭐⭐⭐
换手率适度活跃⭐⭐⭐
分析师预期上调优先⭐⭐⭐⭐
股东增持增持优先⭐⭐⭐

下一步均值回归策略 →