Skip to content

因子 - 暴露计算与验证

暴露计算

基本用法

from jh_quant.factors import FactorEngine, FactorType
from 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 hml
0 000001 2024-12-31 0.0023 0.8956 -0.1234 0.4567
1 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())

输出格式:

factorcoefficientt_statistic_nwp_value_nwsignificant_5pct
mkt0.00822.080.041True
smb0.00341.720.089False
hml0.00562.350.022True

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())

输出格式:

factormean_lambdat_statistic_nwp_value_nwsignificant
mkt0.00782.210.031True
smb0.00211.430.158False
hml0.00452.550.014True

两种验证的区别

方面截距项验证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