【国信金工】资产周转率选股模型

来源:https://uqer.io/community/share/565012a0f9f06c4446b48545

资产周转率选股模型

一、背景介绍

根据研究报告20151113-国信证券-国信alpha选股系列:资产周转率选股模型构建。

二、周转率选股模型

这里,研究报告中使用周转率以及相关基本面因子去预测公司 ROE 的改善,实证检验表明, ROE 的改善大概率会随着未来半年业绩的兑现而传导到股票收益上。综合考虑,研究报告用以下方式构建周转率选股模型:

  • 总资产周转率同比改善;
  • 营业收入同比增长;
  • ROE 在全市场处于较低水平;
  • 营业利润同比增长。 一年调仓两次,分别在每年 5 月初、 11 月初调仓。每期选股数量在 50 至 140只之间。平均每期股票 80 只左右。

使用“业绩快报”与“合并利润表”API或缺营业收入与营业利润只有年报,1月初发行的。所以5月与11月调仓使用的是同意的数据。

所以本策略对原模型稍加改变,使用了‘营业利润增长率’、‘营业收入增长率’代替‘营业利润’与‘营业收入’。

PS:其实是懒 - -! 没找其他的API,坐等大神实现原策略!^_^

三、研究报告回测结果

【国信金工】资产周转率选股模型 - 图1

上图显示, 从绝对收益角度来看,周转率选股模型在 2011 年 11 月至 2013 年 4月这三期当中绝对收益为负; 2011 年 5~10 月,虽然整体市场下跌,但模型组合绝对收益为正; 2015 年 5~10 月,市场先扬后抑,但模型组合仍斩获正收益。

在 2012 年 11 月至 2015 年 4 月这五期当中,市场经历了一波牛市,模型组合不但收益为正,而且每期都跑赢了全 A 等权和中证 500。最近 10 期中有 7 期绝对收益为正,而全 A 等权 10 期中有 6 期收益为正,中证 500 在近 10 期中仅有 5 期收益为正。

【国信金工】资产周转率选股模型 - 图2

在最近 10 期当中,除 2011 年报期之外,模型组合有 9 期跑赢中证 500。 其中,在 2011 年 11 月年报期,模型的相对收益最低,为-1.03%;在 2015 年 5 月中报期,模型的相对收益最高,有 19.30%。平均年化超额收益 20.68%。

从绝对收益角度考虑,由于全 A 等权并无实际对冲标的,而且模型相对中证 500的超额收益较高,所以该模型在中证 500 指数的基础上做绝对收益不失为一个不错的选择。

  1. from CAL.PyCAL import *
  2. start = '2010-11-01' # 回测起始时间
  3. end = '2015-05-01' # 回测结束时间
  4. benchmark = 'ZZ500' # 策略参考标准
  5. universe = set_universe('ZZ500')# + set_universe('HS300') # 证券池,支持股票和基金
  6. capital_base = 10000000 # 起始资金
  7. freq = 'd' # 策略类型,'d'表示日间策略使用日线回测,'m'表示日内策略使用分钟线回测
  8. refresh_rate = 122 # 调仓频率,表示执行handle_data的时间间隔,若freq = 'd'时间间隔的单位为交易日,若freq = 'm'时间间隔为分钟
  9. cal = Calendar('China.SSE')
  10. stocknum = 80
  11. def initialize(account): # 初始化虚拟账户状态
  12. pass
  13. def handle_data(account): # 每个交易日的买入卖出指令
  14. global stocknum
  15. # 获取时间
  16. today = Date.fromDateTime(account.current_date).strftime('%Y%m%d') # 当天日期
  17. lasttime = cal.advanceDate(today,'-1Y',BizDayConvention.Preceding).strftime('%Y%m%d')
  18. print '调仓日期:' + str(account.current_date)
  19. # 根据条件获取buylist
  20. tf1 = DataAPI.MktStockFactorsOneDayGet(tradeDate=today,secID=account.universe,ticker=u"",field=['secID','OperatingProfitGrowRate','OperatingRevenueGrowRate','TotalAssetsTRate','ROE'],pandas="1")
  21. tf1.set_index('secID',inplace=True)
  22. tf1 = tf1[(tf1.OperatingProfitGrowRate>0.0)&(tf1.OperatingRevenueGrowRate>0.0)&(tf1.TotalAssetsTRate>0.0)&(tf1.ROE>0.0)].dropna()
  23. tf2 = DataAPI.MktStockFactorsOneDayGet(tradeDate=lasttime,secID=account.universe,ticker=u"",field=['secID','OperatingProfitGrowRate','OperatingRevenueGrowRate','TotalAssetsTRate','ROE'],pandas="1")
  24. tf2.set_index('secID',inplace=True)
  25. tf2 = tf2[(tf2.OperatingProfitGrowRate>0.0)&(tf2.OperatingRevenueGrowRate>0.0)&(tf2.TotalAssetsTRate>0.0)&(tf2.ROE>0.0)].dropna()
  26. per_buylist=[]
  27. for stock in list(tf1.index):
  28. if stock in list(tf2.index):
  29. if((tf1['OperatingProfitGrowRate'][stock]>tf2['OperatingProfitGrowRate'][stock])&(tf1['OperatingRevenueGrowRate'][stock]>tf2['OperatingRevenueGrowRate'][stock])&(tf1['TotalAssetsTRate'][stock]>tf2['TotalAssetsTRate'][stock])):
  30. per_buylist.append(stock)
  31. by = DataAPI.MktStockFactorsOneDayGet(tradeDate=today,secID=account.universe,ticker=u"",field=['secID','ROE'],pandas="1")
  32. by.set_index('secID',inplace=True)
  33. by = by[by.ROE>=0.0].dropna().sort(columns='ROE',ascending=True)
  34. by = by.head(80)
  35. buylist = list(by.index)
  36. # 卖出股票
  37. for stock in account.valid_secpos:
  38. if stock not in buylist:
  39. order_to(stock, 0)
  40. else:
  41. pass
  42. # 买入股票
  43. for stock in buylist:
  44. if stock not in account.valid_secpos:
  45. order(stock, account.cash/account.referencePrice[stock]/stocknum)
  46. # print list(account.valid_secpos.keys())

【国信金工】资产周转率选股模型 - 图3

  1. 调仓日期:2010-11-01 00:00:00
  2. 调仓日期:2011-05-03 00:00:00
  3. 调仓日期:2011-10-31 00:00:00
  4. 调仓日期:2012-05-04 00:00:00
  5. 调仓日期:2012-10-31 00:00:00
  6. 调仓日期:2013-05-08 00:00:00
  7. 调仓日期:2013-11-08 00:00:00
  8. 调仓日期:2014-05-12 00:00:00
  9. 调仓日期:2014-11-07 00:00:00