查看原文
其他

【万矿新品】因子研究利器——WindAlpha

WindQuant 万矿 2022-05-14


因子选股模型是我们在量化策略研究中使用最多的一种方法。今天,万矿重磅推出一款高效、便捷的因子分析工具——WindAlpha,让您在万矿上用于进行一站式的因子测试和研究。


WindAlpha是万矿开发的一款基于Python的因子分析函数库它包括了:


数据获取与处理

对原始数据进行了剔除停牌、ST、新上市、缺失值处理,同时做了去极值、标准化,中性化处理。

原始数据与处理后的数据分布对比


单因子分析

对于因子分析,进行了4个维度的分析:


  • IC序列分析、IC衰弱


  • 收益率分析


  • 换手率分析


  • 板块分析



多因子组合分析

主要的组合得分计算有以下几种方法:


  • 等权法:该方法对所有因子同等看待,不论其有效性的优劣

  • IC加权:根据IC均值的大小决定因子的权重,IC高的因子,权重就大,IC的均值为滚动计算

  • ICIR加权:根据因子ICIR的大小决定因子的权重,ICIR越大,权重越大,ICIR的值为滚动计算


AlphaModel

AlphaModel是一个类,实例化为对象后可以一键对因子进行以上几个维度的分析,也能构建组合进行选股。具体用法请查看帮助文档。


接下来,让我们具体了解一下WindAlpha的用法吧!


数据获取与处理

在这个之前,我们需要确定选股的频率(日度还是月度?),以及在哪里选股(股票池,如沪深300),选择哪些因子。


在接下来的示例中,我们以沪深300指数成分股为股票池,每月调仓。选择因子,获取以下数据(每个月最后一个交易日):


  • 沪深300成分股的数据

  • 所有成分股的因子数据

  • 所有成分股的收益率

  • 所有成分股的市值数据

  • 所有成分股的所属行业

  • 策略收益比较基准的数据


先引入WindAlpha库,获取原始因子数据:

#20日收集派发指标, 净利润/营业总收入(TTM), 增长率-净利润(TTM)
ind_code =   ['TECH_AD20', 'FA_ROENP_TTM', 'FA_NPGR_TTM']
raw_inds_ret = wa.prepare_raw_data('000300.SH',ind_code,
'2016-01-01', '2018-04-30')


 prepare_raw_data函数用于获取原始因子数据,参数见帮助文档,该函数返回一个多重索引的Dataframe,第一层索引为日期('date'),第二层索引为股票代码('codes')。


原始因子数据处理(去极值、标准化):

对于原始数据(在获取的过程中已经去除了停牌、新上市、因子值缺失的股票),接下来我们需要做的是对每一个选股期的数据作数据处理:


process_raw_data函数用于处理原始因子数据,处理的过程包括去极值、标准化处理,去极值的主要目的是为了使因子数据在一个合理的范围之内,而不会因为某些异常值对因子的整体分布造成影响,去极值的方法一般有两种:


* 平均绝对离差法(MAD)

* 标准差法(Std)


标准化是使得横截面数据在一个固定的范围内(量纲的一致性),主要的方法有普通标准化行业标准化,区别是因子均值的计算方法不一样,具体的区别请看代码实现。


单因子分析

WindAlpha主要对单因子进行四个维度的分析:IC分析收益率分析换手率分析版块分析


  • IC分析:计算每一期因子值与下一期股票收益率之间的相关性(信息系数IC),并对IC序列进行进一步分析


  • 收益率分析:每一期对股票池内的股票按因子值由优到劣进行排序,并分为N组,对每一组的收益率进行分析


  • 换手率分析:通过每一期买入股票的变动,评价因子的交易成本暴露


  • 版块分析:对于所选出来的股票的行业分布进行分析


ic_analysis()-具体用法见帮助文档

IC分析在整个单因子分析的过程中起主导性作用。

IC的大小反应了因子暴露值与股票表现之间的线性关系,IC的值越大说明因子的预测性越高,选股的效果就越好。IC的计算方法主要有两种 ,但常用的更有解释性的为RankIC。

代码实现:

ic_ana = wa.ic_analysis(processed_inds_ret)
ind = "FA_ROENP_TTM"
fig_ic=WLine("IC序列:{}".format(ind),"2016.01-2018.03", ic_ana.ic_series.ix[ind])
fig_ic.plot()



知识拓展

IC信号衰减

我们经常在研报上听到这个词,那什么是IC信号衰减,怎么计算出来的呢?WindAlpha提供了这样的算法(ic_decay为每个因子12期的IC衰减)

具体的计算方法如下:


如果一共有N期的因子数据和收益率数据,我们先把所有i期因子和i+1期收益率的IC值算出来求平均,再把i期因子和i+2收益率的IC求平均....(i=1,...,N-LAG),最终我们得到LAG个IC的均值,这几个均值就体现了IC的衰减。


代码实现:

fig_decay=WBar('{} IC Decay'.format(ind), '',ic_ana.ic_decay[ind].to_frame())
fig_decay.plot()


return_analysis()-具体用法见帮助文档

收益率分析也是对因子的进一步分析,在因子通过IC分析后,我们知道了因子对于股票收益的相对关系有预测性的作用,但具体反应到收益上还得根据收益率分析的相关指标来判断


由于运算效率的取舍问题,在因子筛选的初期,我们可以直接用每期股票的平均收益率来计算分析期间的分组累计收益率等指标,而不用写到策略中每日回测。


代码实现:

group_data_ind =
wa.add_group(processed_inds_ret,ind_name=ind, industry_neu=True)

## 根据FA_ROENP_TTM分组后的数据,按组排序
group_data_ind.groupby(level=0).apply
(lambda x: x.reset_index(level=0,drop=True).sort_values('GROUP'))

# 分组后每组收益的平均值
direction_dict = {'TECH_AD20': 'descending'}
ret_ana = wa.return_analysis(processed_inds_ret,'000300.SH',
'2016-01-01', '2018-04-30',ind_direction=direction_dict)

# 计算相关的收益率指标
ret_ana.return_stats.applymap(lambda x: round(x,4)
if not isinstance(x, tuple) else (round(x[0],4), round(x[1],4)))


sig_ret_line = WLine("收益率:{}".format(ind),
"2016.01-2018.03", round(ret_ana.group_cum_return
[['G01-G05','BENCH_RET']].ix[ind],4),auto_yaxis=True)
sig_ret_line.plot()




turnover_analysis()-具体用法见帮助文档

对于换手率的分析,常用的方法有两种:个数法权重法


所谓个数法就是计算每期之间股票变动的数量并处以股票的总数量计算出的比率,例如t期买入[A,B,C,D,E]五只股票,t+1期买入[A,D,E,F,G]五只股票,那么这期间的换手率就是(2/5=40%)。


权重法不仅考虑股票本身的变化,还考虑了股票权重的变化。


代码实现:

turnover_ana=wa.turnover_analysis(processed_inds_ret)

fig3=WLine("换手率:TECH_AD20","2016.01-2017.12",
turnover_ana.turnover.ix["TECH_AD20"])
fig3.plot()




知识拓展

买入信号衰减与反转

在因子分析过程中,我们经常看到衰减这个词,实际上很好理解,衰减的越快持续性越差,衰减的越慢持续性越好


买入信号反转与衰减的原理类似,唯一的区别是统计的组别不一样。当对因子进行排序后,我们默认买入的是G1组(第一组),卖出G5组(最后一组),买入信号衰减度量的是当前买入的股票在后续调仓期卖出的比率


代码实现:

fig_signal=WBar('FA_ROENP_TTM Buy Signal Decay',
'',turnover_ana.buy_signal.ix["FA_ROENP_TTM"])
fig_signal.plot()



sector_analysis()-具体用法见帮助文档

该函数用于对处理后的因子数据进行版块分析。


代码实现:

code_ana = wa.sector_analysis(raw_inds_ret)

fig_mean_cap=WBar('FA_ROENP_TTM Mean Cap',
'',code_ana.group_cap_mean.ix['FA_ROENP_TTM'].mean().
to_frame(name='CAP'))
fig_mean_cap.plot()

code_ana.group_industry_ratio.ix['FA_NPGR_TTM'].ix['G05'].fillna(0)



data =code_ana.group_industry_ratio.ix['FA_NPGR_TTM'].ix['G01'].fillna(0)
chart = WStacking_bar(title='FA_NPGR_TTM因子选股行业占比', data=data.T, data_label=False)
chart.plot()



code_ana.group_industry_mean_ratio



ind_mean_G01=code_ana.group_industry_mean_ratio.ix['FA_NPGR_TTM']['G01']
ind_mean_G01 = pd.DataFrame({'name':ind_mean_G01.index, 'value': ind_mean_G01.values})
fig5 = WPie('G01 Section Percent', '', ind_mean_G01)
fig5.plot()



多因子组合分析

打分法函数 score_indicators()

返回数据会合并各因子列并新增‘SCORE’列为打分结果:


回归法函数 regress_indicators()

返回数据会合并各因子列并新增‘PRED_RET’列为下期收益率预测:


—end—


Wind账号的朋友将终端升级到最新版

即可直接使用,自带高级权限

↓↓↓

个人用户也可登陆网页版免费注册使用

网页版地址:www.windquant.com


iWind交流群:463249

QQ群:465776969

↙↙↙点击“阅读原文”【可免费注册万矿账号哦】

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存