查看全集:💎Quantopia量化分析56讲
基本面因子是从公司财务报表(如资产负债表、利润表)中提取的财务指标,用于衡量公司的财务特征。常见因子包括:
资产收益可表示为多个因子收益的线性组合:
其中:
表示资产i的收益率
表示资产i的超额收益
表示资产i对第j个因子的暴露度(敏感度)
表示第j个因子的收益率
表示资产i的特异性风险(不能被因子解释的部分)
表示模型中包含的因子数量
通过构建多空组合获取因子收益:
因子 | 组合构造方法 |
SMB | 小市值股票收益 - 大市值股票收益 |
HML | 高市净率股票收益 - 低市净率股票收益 |
MOM | 强势股收益 - 弱势股收益 |
import yfinance as yf
# 获取市场数据示例
start = '2016-01-01'
end = '2016-12-31'
# 获取股票数据
stocks = yf.download(['AAPL', 'MSFT', 'SPY', 'BIL'], start=start, end=end)
market_return = stocks['Adj Close']['SPY'].pct_change().dropna()
risk_free = stocks['Adj Close']['BIL'].pct_change().dropna()
# 计算因子收益示例
def calculate_factor_returns(data, long_condition, short_condition):
long_returns = data[long_condition]['Returns'].mean(level=0)
short_returns = data[short_condition]['Returns'].mean(level=0)
return long_returns - short_returns
SMB = calculate_factor_returns(results, 'smallest', 'biggest')
HML = calculate_factor_returns(results, 'highpb', 'lowpb')
import statsmodels.api as sm
# 第一步:时间序列回归
betas = []
for asset in assets:
model = sm.OLS(Y[asset], X[asset]) # X包含各因子收益
results = model.fit()
betas.append(results.params)
# 第二步:横截面回归
final_model = sm.OLS(mean_returns, betas)
final_results = final_model.fit()
小练习:尝试使用SMB和HML因子构建投资组合,并计算其过去一年的夏普比率。
计算标准化得分:
其中:
表示标准化后的因子值
表示原始因子值
表示因子在t时刻的截面均值
表示因子在t时刻的截面标准差
from scipy.stats import zscore
# 示例:市净率标准化
book_to_price = results['book_to_price'].unstack()
z_scores = book_to_price.apply(zscore, axis=1)
from scipy.stats.mstats import winsorize
winsorized_data = winsorize(raw_data, limits=[0.01, 0.01])
daily_model = sm.OLS(returns, z_scores)
results = daily_model.fit()
factor_returns = results.params
特征 | 组合构建法 | 因子标准化法 |
数据要求 | 需要完整历史数据 | 只需当日数据 |
计算复杂度 | 高(需构建组合) | 低 |
适用场景 | 长期因子效应研究 | 高频因子分析 |
抗噪能力 | 较强 | 需要额外数据处理 |
# 获取标普500成分股
sp500 = pd.read_html('https://en.wikipedia.org/wiki/List_of_S%26P_500_companies')[0]
tickers = sp500.Symbol.tolist()
# 下载历史数据
data = yf.download(tickers, start='2020-01-01', end='2023-01-01')['Adj Close']
# 计算20日动量
momentum = data.pct_change(20).shift(-20) # 未来20日收益
# 每月调仓
monthly_returns = data.resample('M').last().pct_change()
for date in monthly_returns.index[:-1]:
# 计算当期动量
mom_rank = momentum.loc[date].rank(ascending=False)
# 构建组合
long_stocks = mom_rank[mom_rank <= 50].index
short_stocks = mom_rank[mom_rank >= 450].index
# 计算下月收益
long_return = monthly_returns.loc[date:][long_stocks].mean(axis=1)
short_return = monthly_returns.loc[date:][short_stocks].mean(axis=1)
portfolio_return = long_return - short_return
关键点说明:动量效应通常表现为过去表现好的股票在未来继续表现优异,但实际应用中需注意反转效应的影响。
练习:使用yfinance获取中国A股数据,尝试构建市值因子(SMB)并进行有效性检验。