因子 - 暴露计算与验证
暴露计算
基本用法
from jh_quant.factors import FactorEngine, FactorTypefrom jh_quant.data import JHData, DataTypes
engine = FactorEngine()
# 1. 计算因子收益率ff3 = engine.calculate_factor_returns( factor_type=FactorType.FF3, period='M', start_date='2023-01-01', end_date='2024-12-31',)
# 2. 获取个股收益率jh = JHData()stock_returns = jh.get_data( DataTypes.AK_STOCK_ZH_A_HIST_QFQ, symbol="000001,600519", start="2023-01-01", end="2024-12-31",)
stock_returns = stock_returns[['symbol', 'date', 'pct_chg']].rename( columns={'pct_chg': 'return'})stock_returns['return'] = stock_returns['return'] / 100
# 3. 计算暴露度exposures = engine.calculate_stock_exposures( stock_returns=stock_returns, factor_returns=ff3, n_jobs=4,)print(exposures.head())输出示例:
symbol date alpha mkt smb hml0 000001 2024-12-31 0.0023 0.8956 -0.1234 0.45671 600519 2024-12-31 -0.0012 0.7234 0.0890 -0.2340便捷函数
from jh_quant.factors import calculate_exposures
exposures = calculate_exposures( stock_returns=stock_returns, factor_returns=ff3, period='M', # 影响默认 lookback lookback=36, # 滚动窗口大小,默认 36(月频)/ 252(日频))计算方法
暴露度通过 OLS 时序回归 计算:
r_i - r_f = alpha_i + beta_1 * MKT + beta_2 * SMB + beta_3 * HML + epsilon_i底层使用 numpy.linalg.lstsq 拟合。
滚动窗口 vs 全样本
# 滚动窗口(默认)exposures_rolling = engine.calculate_stock_exposures( stock_returns=stock_returns, factor_returns=ff3, n_jobs=4,)
# 全样本(pooled OLS)from jh_quant.factors.exposure import StockExposureCalculator
calc = StockExposureCalculator(min_observations=24, n_jobs=4)exposures_pooled = calc.calculate_all_exposures( stock_returns, ff3, rolling=False,)因子验证
截距项验证
检验因子收益率序列是否显著不为零。
from jh_quant.factors.validators import validate_factor_intercept
result = validate_factor_intercept(ff3)print(result.to_dataframe())
# 所有因子是否都在 5% 水平显著print(result.is_all_significant())输出格式:
| factor | coefficient | t_statistic_nw | p_value_nw | significant_5pct |
|---|---|---|---|---|
| mkt | 0.0082 | 2.08 | 0.041 | True |
| smb | 0.0034 | 1.72 | 0.089 | False |
| hml | 0.0056 | 2.35 | 0.022 | True |
Fama-MacBeth 两步验证
Step 1(横截面回归):每个月用个股收益率对因子暴露度做横截面回归
Step 2(时序检验):对风险溢价序列做 t 检验
from jh_quant.factors.validators import FamaMacBethValidator
validator = FamaMacBethValidator()
result = validator.validate( stock_returns=stock_returns, factor_returns=ff3, exposures=exposures, # 可选,不传则自动计算 nw_lags=12,)
print(result.to_dataframe())输出格式:
| factor | mean_lambda | t_statistic_nw | p_value_nw | significant |
|---|---|---|---|---|
| mkt | 0.0078 | 2.21 | 0.031 | True |
| smb | 0.0021 | 1.43 | 0.158 | False |
| hml | 0.0045 | 2.55 | 0.014 | True |
两种验证的区别
| 方面 | 截距项验证 | Fama-MacBeth |
|---|---|---|
| 检验对象 | 因子收益率均值是否非零 | 因子风险溢价是否显著 |
| 数据需求 | 仅需因子收益率 | 需要个股收益率 + 因子收益率 |
| 计算复杂度 | 低 | 高 |
| 学术地位 | 初步检验 | 黄金标准 |
一站式验证
from jh_quant.factors.validators import validate_factor
results = validate_factor( factor_returns=ff3, stock_returns=stock_returns, exposures=exposures, # 可选)
# results['intercept']: InterceptValidationResult# results['fama_macbeth']: FamaMacBethValidationResult