因子投资基础
因子投资是现代量化投资的核心方法论,通过识别和组合影响资产收益的共同因子来构建投资组合。本章将介绍因子投资的基本概念、常用因子和因子分析方法。
因子投资概述
什么是因子?
因子是影响资产收益的共同驱动因素。不同资产对同一因子的敏感度不同,这种敏感度称为因子暴露。
以最简单的市场因子为例:股票收益可以分解为市场收益和个股特异收益。市场因子反映了整体市场的系统性风险,所有股票都受其影响,但影响程度不同。Beta系数就是股票对市场因子的暴露度。
因子投资的核心思想是:资产的收益可以被有限数量的因子所解释。通过理解这些因子,我们可以更好地预测收益、管理风险、构建投资组合。
因子的分类
风格因子:反映资产特征的风格维度,是最常用的因子类型。
- 价值因子:估值较低的股票倾向于获得超额收益
- 动量因子:过去表现好的股票倾向于继续表现好
- 质量因子:财务稳健的公司倾向于获得超额收益
- 规模因子:小市值股票倾向于跑赢大市值股票
- 波动因子:低波动股票风险调整后收益更高
宏观因子:反映宏观经济环境的影响。
- 增长因子:GDP增长、工业产出等
- 通胀因子:CPI、PPI等
- 利率因子:国债收益率、利差等
- 流动性因子:货币供应量、信用利差等
另类因子:基于非传统数据构建的因子。
- 情绪因子:投资者情绪、分析师预期等
- 网络因子:搜索热度、社交媒体讨论等
- 卫星数据:零售客流、油罐储量等
经典因子模型
CAPM模型
资本资产定价模型(CAPM)是最简单的因子模型,只有一个市场因子。
公式:
其中 是无风险利率, 是市场风险溢价, 是股票对市场因子的敏感度。
import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression
def calculate_beta(stock_returns, market_returns):
"""
计算股票Beta
参数:
stock_returns: 股票收益率序列
market_returns: 市场收益率序列
返回:
Beta值
"""
X = market_returns.values.reshape(-1, 1)
y = stock_returns.values
model = LinearRegression()
model.fit(X, y)
return model.coef_[0]
def calculate_alpha(stock_returns, market_returns, risk_free_rate):
"""
计算Jensen's Alpha
参数:
stock_returns: 股票收益率序列
market_returns: 市场收益率序列
risk_free_rate: 无风险利率
返回:
Alpha值
"""
excess_returns = stock_returns - risk_free_rate
market_excess = market_returns - risk_free_rate
X = market_excess.values.reshape(-1, 1)
y = excess_returns.values
model = LinearRegression()
model.fit(X, y)
return model.intercept_
Fama-French三因子模型
Fama和French在CAPM基础上增加了规模因子和价值因子,形成三因子模型。
公式:
其中:
- SMB(Small Minus Big):规模因子,小市值组合收益减大市值组合收益
- HML(High Minus Low):价值因子,高账面市值比组合收益减低账面市值比组合收益
def fama_french_regression(stock_returns, market_returns, smb_returns, hml_returns, risk_free_rate):
"""
Fama-French三因子回归
参数:
stock_returns: 股票收益率
market_returns: 市场因子
smb_returns: 规模因子
hml_returns: 价值因子
risk_free_rate: 无风险利率
返回:
回归结果字典
"""
excess_returns = stock_returns - risk_free_rate
market_excess = market_returns - risk_free_rate
X = np.column_stack([
market_excess.values,
smb_returns.values,
hml_returns.values
])
y = excess_returns.values
model = LinearRegression()
model.fit(X, y)
return {
'alpha': model.intercept_,
'beta_market': model.coef_[0],
'beta_smb': model.coef_[1],
'beta_hml': model.coef_[2],
'r_squared': model.score(X, y)
}
五因子模型
Fama和French后来又增加了盈利因子和投资因子,形成五因子模型。
公式:
其中:
- RMW(Robust Minus Weak):盈利因子,高盈利组合收益减低盈利组合收益
- CMA(Conservative Minus Aggressive):投资因子,低投资组合收益减高投资组合收益
常用因子构建
价值因子
价值因子基于估值指标构建,核心假设是估值低的股票被低估,未来会有更好的表现。
常用的估值指标:
- 市盈率(P/E):股价/每股收益
- 市净率(P/B):股价/每股净资产
- 市销率(P/S):市值/营业收入
- 企业价值倍数(EV/EBITDA):企业价值/息税折旧摊销前利润
def build_value_factor(df):
"""
构建价值因子
参数:
df: 包含估值指标的DataFrame
返回:
价值因子得分(越高越便宜)
"""
# 方法1:单一指标
value_factor = 1 / df['PE'] # PE倒数,越大越便宜
# 方法2:多指标综合
# 先标准化各指标
df['PE_score'] = (df['PE'] - df['PE'].mean()) / df['PE'].std()
df['PB_score'] = (df['PB'] - df['PB'].mean()) / df['PB'].std()
df['PS_score'] = (df['PS'] - df['PS'].mean()) / df['PS'].std()
# 综合得分(负号表示越低越便宜)
value_factor = -(df['PE_score'] + df['PB_score'] + df['PS_score']) / 3
return value_factor
动量因子
动量因子基于历史价格表现构建,核心假设是过去表现好的股票会继续表现好。
常用的动量指标:
- 过去N个月收益率(排除最近一个月,避免短期反转)
- 相对强度指标
- 价格动量排名
def build_momentum_factor(prices, lookback=12, skip=1):
"""
构建动量因子
参数:
prices: 价格序列(DataFrame,每列一只股票)
lookback: 回看期(月)
skip: 跳过最近N月(避免短期反转)
返回:
动量因子得分
"""
# 计算过去lookback个月收益,跳过最近skip个月
# 假设数据是日频,转换为月度
monthly_prices = prices.resample('M').last()
# 动量 = (P_t / P_{t-lookback-skip}) - 1
momentum = monthly_prices.shift(skip) / monthly_prices.shift(lookback + skip) - 1
return momentum
质量因子
质量因子基于财务质量指标构建,核心假设是财务稳健的公司更有可能获得超额收益。
常用的质量指标:
- ROE(净资产收益率)
- ROA(总资产收益率)
- 毛利率、净利率
- 资产负债率
- 经营现金流/净利润
def build_quality_factor(df):
"""
构建质量因子
参数:
df: 包含财务指标的DataFrame
返回:
质量因子得分
"""
# 标准化各指标
df['ROE_score'] = (df['ROE'] - df['ROE'].mean()) / df['ROE'].std()
df['ROA_score'] = (df['ROA'] - df['ROA'].mean()) / df['ROA'].std()
df['Margin_score'] = (df['NetMargin'] - df['NetMargin'].mean()) / df['NetMargin'].std()
# 低负债率得分高
df['Leverage_score'] = -(df['DebtRatio'] - df['DebtRatio'].mean()) / df['DebtRatio'].std()
# 综合得分
quality_factor = (df['ROE_score'] + df['ROA_score'] + df['Margin_score'] + df['Leverage_score']) / 4
return quality_factor
规模因子
规模因子基于市值构建,核心假设是小市值股票有更高的预期收益(规模溢价)。
def build_size_factor(df):
"""
构建规模因子
参数:
df: 包含市值的DataFrame
返回:
规模因子得分(越小市值得分越高)
"""
# 市值对数
log_size = np.log(df['MarketCap'])
# 标准化后取负(小市值得分高)
size_factor = -(log_size - log_size.mean()) / log_size.std()
return size_factor
波动因子
波动因子基于历史波动率构建,核心假设是低波动股票风险调整后收益更高(低波动异象)。
def build_volatility_factor(returns, window=252):
"""
构建波动因子
参数:
returns: 收益率序列
window: 计算窗口
返回:
波动因子得分(低波动得分高)
"""
# 计算历史波动率
volatility = returns.rolling(window=window).std() * np.sqrt(252)
# 标准化后取负(低波动得分高)
vol_factor = -(volatility - volatility.mean()) / volatility.std()
return vol_factor
因子分析
IC值
IC(Information Coefficient)是因子值与未来收益的相关系数,衡量因子的预测能力。
def calculate_ic(factor_values, forward_returns):
"""
计算IC值
参数:
factor_values: 因子值(截面数据)
forward_returns: 未来收益
返回:
IC值
"""
# Pearson相关系数
ic = factor_values.corr(forward_returns)
return ic
def calculate_ic_series(factor_df, returns_df, periods=252):
"""
计算IC时间序列
参数:
factor_df: 因子数据(日期x股票)
returns_df: 收益数据(日期x股票)
periods: 计算周期
返回:
IC序列
"""
ic_series = []
dates = factor_df.index[:-periods]
for date in dates:
factor = factor_df.loc[date]
future_return = returns_df.loc[date:].iloc[1:periods+1].sum()
ic = calculate_ic(factor, future_return)
ic_series.append({'date': date, 'IC': ic})
return pd.DataFrame(ic_series).set_index('date')
def analyze_ic(ic_series):
"""
分析IC序列
参数:
ic_series: IC序列
返回:
IC分析结果
"""
return {
'IC_mean': ic_series.mean(),
'IC_std': ic_series.std(),
'ICIR': ic_series.mean() / ic_series.std(), # IC信息比率
'IC_positive_ratio': (ic_series > 0).mean(), # IC为正的比例
'IC_t_stat': ic_series.mean() / (ic_series.std() / np.sqrt(len(ic_series)))
}
IC值的解读:
- |IC| > 0.05:因子有较强的预测能力
- |IC| > 0.03:因子有一定的预测能力
- |IC| < 0.03:因子预测能力较弱
- ICIR > 0.5:因子稳定性较好
- ICIR > 1.0:因子稳定性优秀
分组回测
将股票按因子值分组,比较各组的收益表现。
def factor_group_backtest(factor_values, returns, n_groups=5):
"""
因子分组回测
参数:
factor_values: 因子值
returns: 收益率
n_groups: 分组数量
返回:
各组收益统计
"""
# 按因子值分组
factor_values = factor_values.dropna()
labels = ['G' + str(i+1) for i in range(n_groups)]
groups = pd.qcut(factor_values, n_groups, labels=labels)
# 计算各组收益
group_returns = {}
for label in labels:
stocks = groups[groups == label].index
group_returns[label] = returns[stocks].mean()
return pd.Series(group_returns)
def factor_group_analysis(factor_df, returns_df, n_groups=5):
"""
因子分组分析(时间序列)
参数:
factor_df: 因子数据(日期x股票)
returns_df: 收益数据(日期x股票)
n_groups: 分组数量
返回:
各组累计收益
"""
all_group_returns = []
for date in factor_df.index[:-1]:
factor = factor_df.loc[date]
next_return = returns_df.loc[factor_df.index[factor_df.index.get_loc(date) + 1]]
group_ret = factor_group_backtest(factor, next_return, n_groups)
group_ret.name = date
all_group_returns.append(group_ret)
group_returns_df = pd.DataFrame(all_group_returns)
# 计算累计收益
cumulative_returns = (1 + group_returns_df).cumprod()
return cumulative_returns
因子正交化
多个因子之间可能存在相关性,需要正交化处理以消除共线性。
from sklearn.linear_model import LinearRegression
def orthogonalize_factor(target_factor, other_factors):
"""
因子正交化
参数:
target_factor: 目标因子
other_factors: 其他因子(需要正交化的因子)
返回:
正交化后的因子
"""
# 用其他因子回归目标因子
X = other_factors.values
y = target_factor.values
model = LinearRegression()
model.fit(X, y)
# 残差即为正交化后的因子
residual = y - model.predict(X)
return pd.Series(residual, index=target_factor.index)
多因子模型构建
因子组合方法
def combine_factors(factor_dict, weights=None):
"""
组合多个因子
参数:
factor_dict: 因子字典 {因子名: 因子值}
weights: 因子权重字典
返回:
综合因子得分
"""
if weights is None:
weights = {name: 1/len(factor_dict) for name in factor_dict}
combined = pd.Series(0, index=list(factor_dict.values())[0].index)
for name, factor in factor_dict.items():
# 标准化
factor_std = (factor - factor.mean()) / factor.std()
# 加权
combined += weights[name] * factor_std
return combined
def equal_weight_portfolio(factor_scores, n_stocks=50):
"""
等权重组合构建
参数:
factor_scores: 因子得分
n_stocks: 持仓股票数量
返回:
选出的股票列表
"""
# 选择得分最高的n只股票
selected = factor_scores.nlargest(n_stocks).index.tolist()
# 等权重
weights = pd.Series(1/n_stocks, index=selected)
return weights
因子权重优化
from scipy.optimize import minimize
def optimize_factor_weights(factor_returns, cov_matrix, target_return=None):
"""
优化因子权重(均值方差优化)
参数:
factor_returns: 因子收益历史数据
cov_matrix: 因子协方差矩阵
target_return: 目标收益
返回:
最优权重
"""
n_factors = len(factor_returns.columns)
# 目标函数:最小化方差
def portfolio_variance(weights):
return weights @ cov_matrix @ weights
# 约束条件
constraints = [
{'type': 'eq', 'fun': lambda w: np.sum(w) - 1} # 权重和为1
]
if target_return:
expected_returns = factor_returns.mean()
constraints.append({
'type': 'eq',
'fun': lambda w: w @ expected_returns - target_return
})
# 边界条件
bounds = tuple((0, 1) for _ in range(n_factors))
# 初始权重
initial_weights = np.array([1/n_factors] * n_factors)
# 优化
result = minimize(
portfolio_variance,
initial_weights,
method='SLSQP',
bounds=bounds,
constraints=constraints
)
return result.x
小结
因子投资是量化投资的核心方法论,本章介绍了因子的基本概念、常用因子类型、因子分析方法和多因子模型构建。因子投资的关键在于:
- 选择有经济学逻辑支撑的因子
- 通过IC分析验证因子的预测能力
- 处理因子之间的相关性
- 合理组合多个因子
因子投资不是简单的因子堆砌,而是需要深入理解每个因子背后的经济学逻辑,以及因子在不同市场环境下的表现。下一章将介绍机器学习在量化交易中的应用。