readme
Table of Content
基本面量化系列(14):在手之鸟,红利优选策略-策略复现
一、复现思路¶
通过多因子策略构建量化回测系统,共构建4个筛选条件和9个因子,9个因子等权配置,对经过4个筛选条件筛选后的股票进行打分,最终筛选出得分最高的30只股票。。调仓频率:月度调仓。数据来源:Tushare、wind、baostock、聚宽等
二、因子体系介绍¶
4个筛选条件分别为:每期股息率排名前500(股息率定义为调仓日前12个月股息率,使用总分红金额/市值,考虑了多次分红的情况,这个方法可以不用再单独考虑股本变化的影响。股息率的定义参考了华泰证券的一篇研报)、连续两年分红、过去十年没有审计保留意见、市值大于50亿。9个因子分别是两年股息率均值因子(dividend_yield_z)、净利润稳定性因子(net_profit_stability_z)、换手率因子(turnover_rate_z)、股东变化因子(holder_num_z)、ep因子(ep_signal)、bp因子(bp_signal)、派息率因子(dividend_yield_signal)、经营现金流资产比(opercashflow_to_assets_signal)、留存收益资产比(retained_earnings_to_assets_signal) 筛选条件 (1)每期股息率排名前500。调用Tushare数据的接口,输出字段dv_ttm,即股息率TTM=∑近12个月现金股利(税前)/指定日股票市值×100%(与wind中的股息率(近12个月)指标结果一样,用数据验证过)。每月调仓时,将股票的dv_ttm排名,筛选出前500只股票。湘财证券2025年3月25日的研报《高股息股票精选策略》中对于股息率的定义也是最近12个月内的现金分红/当前日股票市值。依据MSCI最新发布的中国权益市场风险模型TheBarra China Equity Model (CNE6),股息率因子(dividendto price ratio/DTOP)被定义为最近12个月的每股股息除以上个月月末的股价。东方财富计算股息率分母是用的是最近一个交易日总市值。考虑到数据的可获得性,本文将股息率定义为股息率_TTM=∑近12个月现金股利(税前)/最近一个交易日股票市值。通过调用Tushare数据接口pro.daily_basic可获取每日股息率_TTM,排序取前500只股票。 因为是每月末调仓,即每个月最后一个交易日调仓,使用的是倒数第二个交易日的数据。因此,将所有股票在回测区间的倒数第二个交易日的股息率TTM数据下载至本地保存,不用每次运行都访问Tushare,提高运行效率。
(2)连续两年分红 考察调仓日前两个财年是否连续分红。通过Tushare的pro.vidend接口,导出分红数据存储到本地。构建连续两年分红函筛选函数is_consecutive_dividend_stock(date),输入参数为调仓日date。设调仓日的月份为T,则调仓日晚于最新分红预案公告日(ann_date),则考察T-1和T-2是否连续分红。否则,考察T-2和T-3是否连续分红。只使用在调仓日已披露的数据,可以避免使用未来函数。连续两年分红输出结果为True,否则输出为False,输出的数据类型为DataFrame。
(4)市值大于50亿元筛选函数 每月最后一个交易日调仓,则需要获取倒数第二个交易日的数据。一是因为当天收盘之后,才会有当天股票的市值数据,要当天调仓执行股票买卖,只能使用前一个交易日的数据。另外,如果当天调仓使用当天的市值数据,会产生未来函数的问题。使用tushare数据daily_basic接口输出total_mv参数获得总市值数据,筛选大于50亿元的股票。因为一个月调仓一次,只获取调仓日前一个交易日的total_mv数据即可,可以大量减少不必要的数据。 (5)过去十年没有审计保留意见筛选函数 获取股票在调仓日(end_date)已公告的前十年的审计报告,筛选出十年全部为标准无保留意见的股票(剔除带强调事项段的无保留意见的股票,查看了曾经出具过此类审计报告的股票,很多被ST了,绝大部分股票在分红方面不具备优势,因此,应该被筛除),返回值为True,否则为False。使用Tushare数据fina_audit接口将审计数据下载至本地。
(2)在分红预案日和股东大会公告日之间的股票+1。这个因子比较简单,对于单只股票,给定回测时间,只需要判断回测日是否处于分红预案公告日和股东大会公告日之间。但数据获取难度比较大,tushare只有预案公告日,没有股东大会公告日。Wind、东方财富有预案公告日、股东大会公告日,但受制于试用账号限流,也拿不到数据。最终通过在咸鱼买到了聚宽的数据,取到了2018年-2023年的所有股票的分红信息,输出字段为股票代码、预案公告日、股东大会公告日。数据验证,通过与wind数据较差对比,抽查了部分数据,数据一致。但聚宽数据抓取了公告中所有与分红相关的内容,包括不分红的内容,数据清洗的难度比较大一些。本文使用的是聚宽的数据。 另外,还找到了baostock数据源可以提供分红预案公告日、股东大会公告日,且是开源免费的,但只能一次导出单只股票数据,通过先遍历每年所有股票,再遍历每一年,获得2018年-2023年所有股票分红信息。通过与wind数据交叉验证发现,数据的准确性一般,比如民生银行2018年的预案公告日,baostock上的日期为4月12日,而wind上的数据是3月30日。通过查看分红公告,3月30日、4月12日均有关于独立董事对上一年度利润分配的独立意见公告,wind抓取了较早的数据,而baostock抓取了较晚的数据,同样,还有风华高科2018年的预案公告日,baostock上的日期是4月28日,而wind上的数据是3月27日,查看公告具体内容,发现确实是3月27日已发布分红预案公告,但4月28日也发布了分红信息,两次发布的关于分红预案的信息均混同在其他公告日内容中,无法从公告标题上识别,咨询了wind客服,wind抓取的是较早发布预案公告的时间。综上看,还是wind的数据质量较高(因为较早发布预案公告日所提供的信息质量比较高,选股效果也会更好)。年度分红,基本在次年度3-4月份发布分红预案公告,绝大部分都是年度分红,年中分红、特殊分红非常少。
9个因子,等权配置,对每只股票打分
三、因子定义介绍¶
(1)两年股息率均值因子(dividend_yield_z) 采用过去两个财年股息率均值,例如,回测2023年的数据,则取2022年、2021年股息率均值。 年度股息率=年度每股股利之和/上个月末股价。年度若有多次分红,则将每股股利相加得到年度每股股利之和。上个月末股价指回测日的上个月末不复权收盘价。 在tushare数据pro.vidend接口中为end_date字段,绝大部分股票年度最后一次分红的end_date都是当年12月31日。实践中,采用年度每股股利之和/上个月末的股价的案例比较多,比如国泰君安研报《基于BarraCNE6的A股风险模型实践:风险因子篇》按上述方法定义股息率因子的。江海证券研报《股票多因子系列(二):基本面类因子实测》定义股息率因子为:过去 12个月每股分红/上月末股价(更倾向于股息率TTM的概念)。天风证券研报《因子跟踪周报:盈利、股东持股比例因子表现较好-20240525》中定义股息率为:最近年度分红/当前市值。可见,计算年度股息率,分子为年度每股股利之和,分母股价采用上个月末股价具备一定的参考性,本文也采用回测日上月末收盘价(不复权)。考虑到当年年度分红预案公告日集中在3、4月份,调仓日在4月30号(含)之前,使用上上年度的年度每股股利之和(如2022年3月30日回测,用的是2020年度每股股利之和/2021年2月28日收盘价),调仓日在4月30日以后,使用上一年度每股股利之和(如2022年5月30日回测,用的是2021年度每股股利之和/2022年4月30日收盘价)。计算前面连续两年股息率,然后求均值。这种算法虽然导致股息率有一定的滞后性,但很好的规避了未来函数问题(一般只有4月30日以后才能拿到上一年度分红数据),同时,本文中定义股息率因子(筛选排名前500的股票)的时候用的是股息率_TTM,弥补了年度股息率时效性滞后的缺陷。 (2)换手波动率因子 取过去20天换手率的波动率(参考东吴证券研报《因子方法论之一:基于日内模式的因子改进-以流动性因子为例》中定义流动性因子的时候也是考虑前20个交易日换手率,调仓频率为月度调仓。天风证券研报《因子跟踪周报:盈利、股东持股比例因子表现较好- 20240525》定义换手率因子时,窗口也是取的过去20个交易日)。本文中也是月度调仓,选用20天换手率波动率,具备合理性。属于连续性因子,直接取绝对数,后面对其标准化。 (3)股东数量变化因子 股东户数在时序上的变化,定义为(最近一期股东数据-过去4个季度数据均值)/过去4个季度数据的标准差,并取相反数。Tushare中股东人数是按季度披露的最近开源证券研报《扎堆效应的识别:以股东户数变动为例》定义股东户数因子时,选取4期(即过去4个季度数据)时,稳定性及RankICIR值最高。因此,本文也选取过去4个季度的数据因为股东数量越少,说明在吸筹,因此,取相反数。也属于连续性因子,直接取绝对数,后面对其标准化 (4)ep标准分因子 定义为pe_ttm的倒数(招商证券研报《估值因子的内涵与逻辑-基本面量化系列研究之一》中定义了估值因子pe_ttm。华泰证券系列研报《上周市场整体偏弱,估值因子亮眼》也定义了估值因子pe_ttm)。通过调用tushare数据接口daily_basic输出参数pe_ttm(若pe为负值,则数据为空,通过dropna过滤掉了)再取倒数。属于绝对数,也属于连续性因子,后面对其标准化。 (5)bp因子(研报的结尾并没提到使用这个因子,本文中也不使用) 直接取pb的倒数。取绝对数,也属于连续性因子,后面对其标准化。 (6)派息率因子 定义为:派息率_TTM=股息率_TTMPE_TTM。因为股息率_TTM=过去12个月的每股股息/当前股价,PE_TTM=当前股价/过去12个月的每股收益。则派息率_TTM=股息率_TTM当前股价/(当前股价/PE_TTM)=股息率_TTM*PE_TTM。股息率_TTM和PE_TTM均可以通过调用Tushare的daily_basic接口直接获得。属于离散型因子,排名前20%和后20%的赋值-1,其余取值1,无需标准化。 (7)经营现金流资产比因子 经营性现金流资产比=最近一期财报经营活动产生的现金流量净额/最近一期财报总资产。经营性现金流就是经营活动产生的现金流量净额,因为只有充裕的净现金才具备分红的条件。研报原文提到了经营性现金流比总资产,因此,分母使用总资产。根据研报原文图31-35,可以看出,经营性现金流资产比、自由现金流资产比、现金流资产比,其中经营性现金流资产比的选股单调性最好,未来每股分红均值group5是最高的,且稳定性是最强的。因此选用经营性现金流资产比这个因子。中银证券研报《基本面财报因子的构建框 架初探》中也分析了净经营现金流比总资产_TTM是比较有效的选股因子。因受限于数据获取难度(现有数据库无法直接获取单季度财报数据,后续考虑收费数据库或者通过写函数计算),本文暂时采用最近一期财报数据代替。 通过调用Tushare数据接口pro.cashflow_vip输出参数n_cashflow_act获取区间内所有报告期的经营活动产生的现金流量净额数据(包括季度、半年度、年度)调用Tushare数据接口pro.balancesheet_vip输出参数total_assets获取区间内所有报告期的总资产数据(包括季度、半年度、年度),去除重复数据,按end_date升序排列,取最后一个数据,即得到最近一期财报数据,并将现金流量数据、总资产数据按照ts_code(股票代码)、end_date(对应报告期)合并在一起,将二者相除,即得到经营现金流资产比(要注意,回测时应该使用已经披露的数据,不能使用未披露数据,否则会产生未来数据问题,如7月10号披露0630中报,6月30日回测的时候,就不能用0630中报数据,只能用0331季报数据)。该指标属于离散型因子,排名后20%的赋值-1,其余取值0,无需标准化。 (8)留存收益资产比因子 这个定义比较明确,等于留存收益/总资产=最近一期财报留存收益/总资产。通过调用Tushare数据的pro.balancesheet_vip接口,输出参数total_assets获得总资产(total_asset)。输出参数surplus_rese获取盈余公积数据,参数undistr_porfitretained_获取未分配利润数据,将二者相加得到留存收益数据(retained_earnings)。将数据按照公告日期ann_date排序,按照股票代码ts_code、报告期end_date去重,保留最后一个数据,即得到最新一期财报数据(最近一期财报有可能为季度、半年度、年度),用retained_earnings/ total_asset得到留存收益资产比因子。排名后20%的赋值-1,其余取值0,无需标准化。 (9)财务收益稳健性因子 研报原文正文中提到计算过去八期的净利润、营业收入和营业利润的标准分,构建财务收益稳健因子,但研报结尾因子合成是净利润业绩稳健。考虑到使用净利润、营业收入和营业利润更加综合,本文使用计算过去八期的净利润、营业收入和营业利润的标准分,构建财务收益稳健因子。构建方法是,通过Tushare数据调用pro.income接口,输出revenue(营业收入)、operate_profit(营业利润)、n_income_attr_p(不含少数股东损益的净利润)取过去两年,共8期财报,将每期标准化(减去最小值,除以最大值减去最小值),再计算三者的均值。 (10)较上一个月的分红金额TTM增长因子 此处指过去12个月累计分红金额的变化值,而非每月分红,累计12个月。分红是非常低频的数据,很多情况下可能12个月只有一次。比如回测日的月份为k,则考察k到k-12月累计分红与k-1月到k-13月累计分红变化。对于分红当月,具备一定的区分度,尤其3、4月份,为分红高峰期。而对于非分红月份,则区分度较低。使用Tushare数据pro.dividend接口,输出参数cash_div_tax(税前每股分红,预案公告日会有数据,而税后每股分红cash_div只有在实施阶段才有数据)获取每股分红数据。输出参数ann_date(预案公告日,通过对比tushare分红数据和上市公司公告内容、wind数据库中的分红信息,发现只有预案公告日ann_date是准确的,可以使用。股东大会公告日和实施日的日期与ann_date是同一天,显然是不准确的,没有使用价值)。通过ts_code、end_date、ann_date、cash_div_tax去重,相同日期的数据只留一条。然后筛选过去12个月内每股分红数据求和(dividend_ttm),再筛选过去1-13个月内每股分红数据并求和(pre_dividend_ttm),二者作差,dividend_ttm – pre_dividend>0,则记为1,否则记为0 (11)
四、复现结果及问题分析¶
最终复现结果是2016年-2024年,策略年化收益率约14%,与研报中差距较大。可能原因如下:(1)研报中,在分红预案日和股东大会公告日之间的股票、较上一个月的分红金额TTM增长的股票,在回测中这两个因子没有考虑进去。tushare数据库中,只有分红预案日数据,没有股东大会公告日数据,因此,没法生成这个因子。较上个月的分红金额TTM增长,股票的分红是离散型变量而非连续型变量,且一年分红的次数也不会太多,如过用分红金额TTM增长来作为一个因子,没有太大意义,如果用分红/股价的TTM值,那就是股息率了,因此,也没有考虑这个因子。(2)因子定义差距。换手率因子,研报中未说明取多长周期的换手率,回测中我取的是过去20天换手率的波动率。股东数量变化因子同理,研报中未说明取多长周期的变化率,回测中取的过去120天的变化率。ep、bp因子研报中也未说明是否直接取pe、pb的倒数,回测中简单取前一交易日pe、pb的倒数。经营现金流资产比因子、留存收益比因子,研报中未说明取多长周期的数据,回测中取的是上一财务年度的数据。净利润稳定性因子,研报内容描述的是计算过去八期的净利润、营业收入和营业利润的标准分,构建财务收益稳健因子,但在文章结尾构建因子部分描述为净利润业绩稳健。回测中简化处理取过去八期净利润,并对其进行标准化。如果研报中对因子的定义不同或者对数据进行过特殊处理,生成的因子与本次回测生成的因子会有很大差异,导致不同的选股结果。(3)回测本身的问题。数据处理相对简单粗暴。比如ep因子数据,应该把负值过滤掉(但分红良好且净利润为负的可能性比较小)。另外,回测中未对因子的IC值、因子单调性、因子相关性进行检验及测试。
未来研究思路:重点在基本面因子研究方面,更好的配合主观投资。也可以加入技术面因子,比如MACD,KDJ,RSI等指标进行过滤。看看测试的效果。