AI量化知识树

基于AI排序算法的指数增强策略

由ypyu创建,最终由iquant 被浏览 1030 用户

导语

【旧版说明】此文档已过期,请参考最新版本下的相关使用文档:

https://bigquant.com/wiki/doc/102a-ai-orWpvrhNoe

在介绍AI排序算法之前我们先介绍另外一个术语:特征工程

特征工程是使用专业背景知识和技巧来处理数据,使得特征能在机器学习算法上发挥更好作用的工程实践。这样解释可能并不直观。举例说明,当我们选择用指标来评估一个人身体健康程度时,我们一般联想到的是身高和体重指标,这是两个不同的维度对数据进行记录,如果我们用身高除以体重这个衍生计算出来的比值来评估一个人身体健康状况,可能预测准确率比单单以身高或者体重进行预测效果好,这就是特征工程中如何构建特征的具体运用。

股票市场上机构最常见的量化选股策略为:多因子选股策略,其基本假设是:相似的资产会有相似的回报, 由于某些特定的原因(特征,也称为因子),资产会表现的十分类似,例如价量变化、行业、规模或者利率变化。因此通过股票的因子就能预测股票未来收益率,一些常年有效的因子包括:动量因子、反转因子、成长因子、财务质量因子、盈利能力因子、股东因子、波动率因子等等。多因子选股策略从本质上来说也是机器学习中特征工程的运用,通过构建衍生因子来对股票未来收益率进行预测。

互联网领域由于数据量大,天生就是机器学习的主战场,本文要介绍的排序学习算法在互联网领域已经有着广泛而成熟的运用。排序学习是一种广泛使用的监督学习方法 (Supervised Learning),比如推荐系统的候选产品、用户排序,搜索引擎的文档排序,机器翻译中的候选结果排序等等,该算法可以很好地将排序和选股结合起来。

策略设计

指数增强

指数增强类产品近两年比较火,一般指买入某个指数成分股,并通过择时、仓位动态调整等方式获得超越指数收益的策略。本文的策略有所差异,不是买入所有指数成分,而是以某一指数确定股票池,然后通过算法对指数成分股票进行排序,买入排序靠前的股票来实现获得超越指数收益的目的。

股票池 以上证50指数成分股为股票池。同理,也可以以沪深300、中证800或者某一行业的股票为股票池。

训练集和测试集确定 本文以2011-01-01至2016-01-01期间的数据作为训练集,以2016-01-01至2018-01-22期间的数据作为测试集。因此本文的策略回测区间为2016年以来。

数据标注 将股票未来5日的收益率进行离散化,映射到1至20共20个分类,标注高表示收益率高,这里离散化采取的是等宽离散化。

特征抽取 本文抽取的特征需要特别介绍的是个股相对于上证50指数(000016)的超额收益率数据,该特征的抽取采取的是方法是:用户自定义表达式函数抽取衍生特征,该方法能够非常自由灵活地抽取特征,比如可以抽取A股票相对于B股票的涨幅这类的特征,将大大丰富机器学习策略所需用到的因子体系,推进机器学习量化策略的开发提升到新的高度。

资金管理 多因子选股策略一般是按月调仓,但是本文的策略并不是按月调仓,而是每日调整部分持仓,这样做最大的好处就是能够及时更新选股结果,适应市场状况,尤其是采用了一些短期变化剧烈的价量因子的时候。我们也尝试过按固定周期全部仓位调仓,效果确实差一些。在买入股票的时候,本文策略也并不是多因子策略的等权重买入股票的思想,因为AI排序算法本身是对股票是否值得买入的一个综合排序,等权重思想与之不太切合,排序在前的股票买入权重越大、排序靠后的股票买入权重越小的思想更为适合,因此每只股票的买入权重可能差异很大。

回测交易 当AI排序算法在预测集上进行预测以后,我们可以通过一些机器学习的指标(比如NDCG)来检验预测的准确性,但对于策略思想检验而言,这并不直观,最直观的方式就是按照预测结果指导投资交易行为,采取收益率曲线来检验算法预测的准确性。本文策略回测区间为测试集时间跨度,策略基准为上证50指数。

策略效果

策略总收益为52.07%,年化收益为23.37%,夏普比率为0.95,最大回撤为16.04%。由于基准总收益率为29.31%,策略总收益为52.07%,因此该策略确实达到了指数上的增强效果。

接着看了一下该策略的风险暴露,发现基本上是集中在价值因子和规模因子上,这很好解释,因为上证50的股票本身规模很大,从公司价值本身来看都很不错。完整代码 在文末附件,对量化感兴趣的朋友可以接着开发优化。

策略案例

https://bigquant.com/experimentshare/4f4d53956da24ed79d868707e21283f9

更多阅读

\

标签

排序算法
评论
  • 请问策略的风险暴露如何查看?
  • 这种限定给定股票范围的回测结果,没啥意义
  • 楼主你查看下源码里面有两个函数,时间取的不一样,你本意是各取个的,但是你确定程序是各取各的吧,你把印证的回测时间延长到2020你看看,都亏了(我怀疑就是下面这里出问题了) \ def calcu_relative_ret(df): start_date = min(m4.data.read_df().date).strftime('%Y-%m-%d') end_date = max(m4.data.read_df().date).strftime('%Y-%m-%d') \ def calcu_relative_ret(df): start_date = min(m11.data.read_df().date).strftime('%Y-%m-%d') end_date = max(m11.data.read_df().date).strftime('%Y-%m-%d')