什么是多因子量化选股模型?
》主要介绍了多因子模型产生的理论背景、基本原理和实现步骤,而《 》则对国内A股市场的三因子模型进行了实证分析。多因子量化模型研究的对象主要是因子,因此单因子的回测和有效性检验是整个多因子模型的重要组成部分。本文结合Python开源包Alphalens,以A股市场真实场景数据,手把手教你对单因子进行量化回测。Alphalens是Quantopian公司(美帝最大的量化回测平台之一,国内几个基本上都是仿他们家的)三大知名Python开源包之一,其他两个分别是Zipline(策略回测,一直没安装成功)和Pyfolio(策略分析)。Alphalens主要提供因子收益分析、因子IC分析、因子换手分析和事件研究等回测框架,由于简单易上手和科学稳定等优点,是量化分析师最常用的回测工具包之一。 数据预处理
#还是使用tushare获取数据
import tushare as ts
token='输入token'
pro=ts.pro_api(token)
df=pro.daily_basic(ts_code=get_code()[0],start_date='20110101')
for code in get_code()[1:]:
df1=pro.daily_basic(ts_code=code,start_date='20110101')
df=pd.concat([df,df1])
df_new=df.loc[:,['ts_code','trade_date','close','pe_ttm']]
df_new.loc[:,'trade_date']=pd.to_datetime(df_new.trade_date)
#设定双重重索引的数据格式
df_new=df_new.set_index(['trade_date','ts_code'])
#根据第一索引排序
df_new=df_new.sort_index()
#查看数据前几行
df_new.head()
其中,pe_ttm是动态市盈率,是本文重点考察的单因子,数据预处理的第一步是建立以日期、股票代码的双重索引,如上表所示。先来看下全市场收盘价和市盈率的描述性统计,市盈率有440万个观测值(删除了市盈率为负的观测值),均值为206,标准差高达12698,最大值为2653832,而75%分位数才77.3,可见均值受极端值影响很大,有必要对原始数据进行归一化和缩尾处理。factor_new是处理后的因子数据。prices是收盘价数据(前复权),必须转化为日期为索引,列名是相应股票代码或名称格式的数据形式。 df_new.describe().round(2)#对数据进行缩尾处理,并进行标准化
factor=df_new['pe_ttm'].groupby('trade_date').apply(winsor_data)
factor_new=factor.groupby('trade_date').apply(MaxMinNormal)
factor_new.hist(figsize=(12,6),bins=20)
prices=df_new['close'].unstack()
prices.head()
alphalens库所用到是函数名称都非常长,其中数据预处理函数是get_clean_factor_and_forward_returns,要想了解函数的详细参数可以输入help(函数名),这里不考虑分组(行业),其他参数均使用默认,factor_new为因子数据,prices为收盘价数据,quantiles=10表示将数据分成10个分位数进行考察,period是调仓周期,10,20,60,表示分布考察10、20、60日调仓情况。进行到这一步,表明数据清洗工作已完成,下面主要围绕单因子的收益率、信息比率和换手率进行回测和分析。 data=alphalens.utils.get_clean_factor_and_forward_returns(factor_new,prices,
quantiles=10,periods=(10,20,60))
data.head()
收益率分析Returns Analysis
单因子的收益率分析主要围绕10、20、60日(可自己设定)调仓周期,将因子数据从小到大排列,分为10个分位数进行回测,一行代码便可实现,但函数名称实在太冗长了。第一张表报告了不同调仓期的alpha、beta、高分位(top quantile)和低分位(bottom quantile)的收益情况。柱状图清晰地显示出该因子(市盈率)随着分位的提高收益由正转负,可见市盈率因子与股票收益存在一定的反向关系,即市盈率越小,未来收益越高,与理论和直觉基本一致。小提琴图是多收益率的分布,60日调仓的收益更加集中,方差更小,收益率更加可信。 由于对因子进行了归一化化处理,因此可以以因子值为权重构建一个全市场的股票组合进行回测。对于cumulative return by quantile的评价标准是累计收益率是否发散,越发散越好,说明因子的区分度越高,60天调仓期出现了明显的发散。好的信号:波动小,在某一个方向的占比处于绝对地位,如大部分的Top minus bottom都是正的。
alphalens.tears.create_returns_tear_sheet(data)
信息分析 Information analysis
IR全称是Information Ratio,等于IC的多周期均值/IC的标准差,或等于超额收益均值/超额收益标准差,代表因子获取稳定Alpha的能力。 整个回测时段由多个调仓期组成,每一个周期都会计算出一根不同的IC值,IR等于多个调仓周期的IC均值除以IC的标准差。因此IR兼顾了因子的选股能力和因子选股能力的稳定性,IR值越大越好。
alphalens.tears.create_information_tear_sheet(data)
热力图提供了不同时间段因子的预测能力表现,有利于进行因子的情景分析。通过热力图我们可以轻易识别哪些时间段IC值比较好,哪些时间段IC比较差,有没有突发的情况,然后可以对此进行情景分析。
ic=alphalens.performance.mean_information_coefficient(data,by_time='1y')
实际交易是有手续费的,因子对单因子的回测还需要考虑换手率的影响,换手率越高说明交易次数越多,可能产生的手续费越高。如果一个因子,今天给一个股票打了很高的分,明天就打很低的分,这将导致对该股频繁的买卖,从而造成很高的手续费。所以,因子的换手率分析也是很重要的一个部分。
还有一个角度可以查看因子造成的换手率高低,就是因子的自相关性。如果因子的自相关性低,那么就一会儿高,一会儿低,往往会造成很大的换手率。而因子的自相关性高,就不会有这样的问题。因子的截面换手率越低,因子的自相关性越高
alphalens.tears.create_turnover_tear_sheet(data)
结语 本文以动态市盈率作为选股因子,旨在为大家展示如何利用alphalens进行单因子的历史回测,没有考虑行业或市值大小的分组因素影响,实战应用到量化因子筛选时还需考虑更多因素和细节的处理,包括调仓周期和分位数确定等,本文仅提供一个因子量化回测的一般分析框架,不构成任何投资建议。关于alphalens的详细使用教程可参看其官网或东北证券金融工程研报《Alphalens使用教程》,公众号后台回复“Alphalens ”即可下载。
关于Python金融量化
专注于分享Python在金融量化领域的应用。加入知识星球,可以免费获取30多g的量化投资视频资料、公众号文章Python完整源码、量化投资前沿分析框架,与博主直接交流、结识圈内朋友等。