问题描述
data 输入只是一小部分的股票代码时,计算中性化的方式是全A股票做回归,取data里的股票的对应的残差,还是直接用data里股票做回归取残差啊?
解决方案
在 JoinQuant(聚宽)平台中使用 neutralize 函数进行因子中性化时,计算方式是直接用你输入的 data 里的股票做回归,然后取残差,而不是用全A股做回归后再截取。
详细原理解析
当你调用 neutralize(series, how=None, date=None, ...) 时,底层逻辑如下:
- 数据对齐:系统会根据你传入的
series(其 index 为股票代码)以及指定的date,去获取这些特定股票对应的市值(如market_cap)或行业分类(如jq_l1)数据。 - 截面回归:系统仅使用你传入的这部分股票池,以你的因子值为因变量(Y),以市值、行业哑变量等为自变量(X),进行横截面 OLS 线性回归。
- 提取残差:回归完成后,提取这部分股票的残差作为中性化后的因子值返回。
注意事项与最佳实践
由于回归是基于你输入的股票池进行的,如果你输入的股票数量非常少(例如只有几十只股票),会导致以下问题:
- 统计显著性不足:样本量太小,回归得到的系数(行业暴露、市值暴露)可能严重失真。
- 非严格意义上的市场中性:在小样本内做中性化,无法代表该因子在整个市场或宽基指数中的真实剥离效果。
💡 最佳实践建议:
如果你希望得到严格意义上的“全市场中性化”或“宽基中性化”因子,应该先传入全A股或宽基指数(如沪深300、中证500)的所有成分股进行 neutralize 计算,得到全样本的残差后,再从中筛选出你实际需要操作的那一小部分股票。
代码示例:
import pandas as pd
from jqfactor import neutralize
from jqdata import get_index_stocks, get_factor_values
# 1. 获取宽基指数(如中证800)作为回归样本池,保证回归样本量充足
universe = get_index_stocks('000906.XSHG', date='2023-10-10')
# 2. 获取这些股票的原始因子值(假设为某自定义因子或库内因子)
factor_data = get_factor_values(universe, ['VOL20'], end_date='2023-10-10', count=1)['VOL20'].iloc[0]
# 3. 在大样本池上进行中性化回归(市值+行业中性化)
neutralized_factor = neutralize(factor_data, how=['jq_l1', 'market_cap'], date='2023-10-10')
# 4. 从中性化后的结果中,提取你真正需要的一小部分股票(例如你的自选股池)
my_small_pool = ['000001.XSHE', '600000.XSHG', '000002.XSHE']
final_factor = neutralized_factor.loc[my_small_pool]
通过这种方式,你的因子值既剥离了全市场的市值和行业影响,又准确地应用到了你的目标股票池上。