基于量化指标的回测统计方法在中国远没有得到广泛使用,大多数投资者采用跟风投资或K线图形的策略。也正因为很少有人用这种方法买卖股票,这种方法在中国更加高效。在欧美市场,量化统计已经被很多聪明人研究透彻,这造成一般量化策略有效性降低,击败大盘指数是件不容易的事情。而在中国,一个相对简单的量化选股模型就有可能轻松跑赢大盘。
果仁策略默认的交易模型(模型I)是一种定期调仓的量化轮动模型。在每一个调仓日,果仁策略卖出仓内的所有股票,并依据调仓日前一交易日的数据,选出股票等权重买入。如果选出的股票已经在仓内,这支股票的仓位也会被重新调整成和其它股票一样的仓位,但如果这只股票因为停牌或涨停跌停无法调整仓位,则仓位保持不变。这种买卖模型比较简单,适合轮动交易策略。
果仁交易模型II是一种按卖出条件调仓的的量化轮动模型。在每一个调仓日,卖出满足卖出条件的股票,把余下的资金等权重买入符合买入条件的新股票。不满足卖出条件的股票可以保持自己的仓位,在规定的仓位范围内不作调整。模型II分离买入和卖出条件,是一种更加灵活的交易模型。
果仁依据申万2014版一类行业标准对股票进行分类。
为了做到回测的真实性,果仁回测引擎作了如下处理:使用精准的(point-in-time)历史数据,彻底回避了使用未来信息的隐患;对停牌和涨跌停股票的买卖限制做出真实处理;对交易成本进行合理估算。历史回测结果可以全部导出到Excel文件里,方便验算。经过许多细心用户的验证,果仁历史回测结果是真实可靠的。
果仁使用“先筛选后排名”的选股流程。当选股策略既有筛选条件又有排名条件时,筛选条件将首先被使用,从几千只股票里选出一批股票做为候选股票,然后排名条件将被用来对这些候选股票做出排名,排名最靠前的N只股票将被买入(N是最大持仓股票数)。
策略收益根据回测日期区间和调仓周期来计算。每个周期的收益单独计算,最后策略的总收益是各个周期的收益累积而成,即(1+周期1收益)×(1+周期2收益)×。。。=1+总收益。调仓日是在每个周期的第一天,股票买卖价格按照调仓日的价格计算,默认是收盘价。每一个周期的选股日调仓日的前一天。比如一个调仓周期的第一天是T日,这个周期的调仓日就是T日,而选股日是T-1日。果仁收益计算包含股息,拆股和配股的收益。
在默认情况下,策略会等权重全仓买入股票,对每只股票的仓位不做限制。比如策略只选出一只股票,则会用100%的资金持有这支股票,如果选出2只股票,则每只股票占用50%的现金,依次类推。在每个调仓日,回测程序都会自动调整仓位,把股票仓位重新设回到等权重的状态。
当有市场择时条件时,用户可以限制熊市整体股票仓位,比如在50%。这时,在每个熊市调仓日,回测程序都会把整体股票仓位设置为50%。
(如果用户认为用100%资金买入一只股票过于危险,可以在策略回测的高级设置里限制个股最大买入仓位。)
股票交易成本默认按双边千分之二计算,即买的时候要扣除千分之二的交易成本,卖的时候再一次扣除千分之二的交易成本。在调仓日,继续持有的股票仓位被调整时不扣除交易成本,比如一只股票的仓位从50%调整为20%,不会扣除交易成本。
股票如果停牌或者一字板涨停跌停,则不能买卖,即便是按照选股策略应该被买入或被卖出,买卖也不能进行。不能卖出的股票会被继续持有到下一个调仓日,并根据下一个调仓日的市场情况来决定是否可以买卖。
在排名分析里收益率挺好的策略,到策略回测里收益经常会低很多,这是因为排名分析回测计算做了简化,没有考虑交易成本和股票停牌等问题。比如排名分析算出的收益率可能是20%,可到了策略回测里,收益率变成了5%甚至是-5%,这往往是由交易成本造成的。一个策略假设每天都买入卖出不同的股票,双边的交易成本合计千分之四,交易费一年就会吃掉100%的收益增长。第二点,策略回测考虑到停牌股票不能买卖,这一点也会造成和排名分析回测的收益不一样。
排名分析主要用于验证选股策略的相对有效性,通过从高分段到低分段股票的收益分布趋势来判断选股策略有效性。而使用策略回测可以得到更接近实际情况的收益曲线。
有些策略起始日期往前或往后调整一天,策略的回测收益会变化很多。大约有两个原因,
一是统计样本数量过少,造成收益计算的随机性较大。比如一个策略最大持仓股票数量是2只,调仓周期是20天,回测时长是5年,按一年有240个交易日算,回测统计数据点有2X12X5=120个。这种策略的回测数据点少,随机性大,收益计算的波动自然较大。比如起始日变化一天,回测收益就可能从80%变成30%。建议用户增加策略回测统计的数据点至少到1000个。增加回测数据点数量的方法有增加最大持仓股票数量,减少调仓周期的天数,手工做起始日期的滚动回测再取平均值。
二是策略本身过度拟合,造成结果不稳定。这往往是策略过于复杂或者参数对于某个起始日过于调优造成的。
我们建议用户根据自己的风险承受能力慎重跟随,果仁网不承担任何由于策略跟随做成的损失。
使用“每日选股”,用户可以看到每一天具体有哪些股票通过筛选条件被选中。如果有排名条件,在“每日选股”的结果中还可以看到每只股票的排名得分。一个选股策略往往能选出上百只或上千只股票,而实际上,一般用户最多能买入10到20只股票。比如用户限定一次最多买入10只股票,筛选条件产生100只股票,程序将挑出排名得分最高的10只股票买入,如果没有指定排名条件,程序会选择成交额最大的股票买入
策略评分。帮助用户快速的判定策略的质量。70分以上的策略是相对较好的策略,60分以下是相对较差的策略。但是评分不能简单对待,还应该仔细研究策略的成分分数。策略评分由5个成分组成:
收益分。根据策略的年化收益打分。100分表明过去5年的策略年化收益大约是50%,60分表明策略年化收益在10%-15%之间。
抗风险分。根据策略的最大回撤率和赢率计算得出。80分以上的策略表明抗风险的能力强,60分以下表明抗风险能力一般。
流动性分。代表策略的容量。果仁根据保守的假设估算出策略的容量。90分以上策略表示策略是大容量策略,60分以下是小容量策略。
稳定性分。代表策略收益波动率的大小。70分以上代表策略月收益波动率在5%以下。40分以下代表策略月收益波动率在15%以上。
为了公平起见,评分程序不使用策略作者规定的起始日期进行回测,还是选用几个时段对策略进行进行多次回测,各项得分从多次回测中取平均值成为为最后得分,唯一的例外是抗风险分,使用表现最差的那次得分为最后得分。
果仁建议用户使用Chrome,其它支持的浏览器有Opera、360极速模式、Safari。还有高版本IE,不支持IE9以下的版本。
前复权价格包含未来信息,为了防止用户错误使用未来信息做策略,果仁只提供后复权收盘价作为选股指标。但在策略结果页面,展现历史股票买入卖出价格时,果仁使用前复权价格,这样便于用户做价格比较。
使用未来函数是量化分析最容易犯的错误之一,为了防止这个错误的发生,果仁网在数据准备和回测算法上做了大量工作,以确保未来函数不会被使用。
果仁已经提供了较为清晰的文档阐述以上功能。使用每日选股查看选股结果,是搞清这些功能的最好方法。例如,在筛选条件里,加入“换手率最大全部10”是得到当日全市场换手率最大的10只股票,这个使用每日选股,其中的含义便一目了然,如果有疑惑,还可以更换条件为“换手率最小全部10”或者“换手率最大全部20”,再看结果。
另外查看策略回测结果里的调仓详情也是理解策略功能的一个重要工具。这样做可以知晓策略具体的运作情况。点击策略详情右上方的导出图标,可以将策略在每个周期的持仓详情导出到一个Excel文件里。
2015年12月,著名量化对冲基金WorldQuant公布了101个Alpha因子,其目的是给策略设计者更多的灵感和思路,能做更多样化的量化策略。果仁对这些因子公式做了去重和修正,并按照因子的公式组成部分,将其中的100个因子分成3类,在果仁平台上对外开放,供所有用户所使用。
价格类因子,公式只用到股票价格指标。大多数因子的设计思路是反转。
例子:WQ_Alpha4,“PercentRank(hrank(最低价,1,0),9)”,思路是股票价格在所有股票中占的位置,跟过去9天相比,是越低越好。这里,hrank(最低价,1,0)返回股票在当日最低价格在所有股票中的排名,价格越低,返回的排名值越大。PercentRank(指标,9)返回过去9天里,指标值占的百分位,从0到1,指标值越大,返回的值越大。
量价类因子,公式里用到成交量和价格指标。大多数因子的设计思路是看价格变化和成交量变化之间的关系。
二分类因子,公式成分和量价类因子一样,只是最后的输出或者是0或者是1,也就是将整个股票分成了两个大类。
--------------------------------------------------------------------------------------------------
100个果仁短周期交易因子公式附录:
股票筛选在各个股票网站和软件上都有提供,大家都很熟悉。使用筛选,用户可以迅速挑出满足筛选条件的股票剔除不满足筛选条件股票。股票排名是一种更有效的更被专业投资者青睐的选股方法,也是果仁网推荐的选股方法。大家在过去一直没有机会接触排名选股的方法,会感到比较陌生,其实它的原理非常简单。在学校里,一个班的学生按各科成绩的综合起来进行排名,排在前面的学生会得奖学金。类似的方法,用户可以对市场上的股票按几项指标进行综合排名,并买入排名靠前的股票。和筛选相比,排名可以实现更精细更稳定的选股策略,原因如下:
排名虽然一直是专业人士的投资方法,但原理非常简单,只要有初级算术的知识就能理解排名分的计算规则。
下面我们用一些实例来介绍果仁排名分的具体计算规则。比如一共有5只股票A,B,C,D,E参加排名。它们的收盘价分别是10,12,20,30,40。按收盘价从小到大排名,A,B,C,D,E的排名就是1,2,3,4,5。果仁根据排名先后算出排名分,排名分的公式是(股票数–股票排名+1)/股票数*100。按照这个公式,排名第1得100,排名第二得80,依次类推,排名第5得20。详细情况如下表列出:
当某只股票的指标为空时,这只股票将一直排在最后,排名分最低。比如A,B,C,D,E的市盈率分别为10,20,30,空,空(当一个公司亏钱时,市盈率无法算出,则市盈率为空。),排名分的计算详细在下表列出:
当有两个以上的指标作为排名条件时,用户可以给每个指标设定权重(默认值为1),综合排名分=排名分1×权重1+排名分2×权重2+...
为了方便展示,我们对综合排名分再做一次排名,算出排名总分。
比如,我们用如下排名条件对股票A,B,C,D,E进行排名
收盘价,从小到大,权重1
市盈率,从大到小,权重1
空值处理
一个指标经常有空值,比如5年净资产收益率很多股票没有数值。无论是从大到小排,还是从小到大排,空值一直排在最后,也就是指标为空的股票排名分最低,值为空的股票都排在最后。
用户可使用排名分析判断排名策略是否有效。回测程序将所有股票按照排名总分分成5段,10段或更多段,计算每段里的股票总收益,输出一个年化收益柱状图和一个累计收益曲线,以便让用户检查是否排名越高的分段收益越好。
比如我们可将所有股票按排名条件分成5段,从低到高依次为0-20,20-40,40-60,60-80,80-100。如果年化收益图(如下图所示)高低排列整齐,则表示此排名策略可能含有较强的投资意义,排名高的股票更有可能产生超额收益。专业对冲投资者也非常喜欢此类形状的图形,他们可以买入最高分段股票,卖空最低分段股票,以获得相对收益。图中0-20分段代表综合排名分在0-20之间的股票,0-20这个分段里的股票是排名分最低的股票,也就是排在最后的股票。80-100分段代表综合排名分在80-100之间的股票,80-100这个分段里的股票是排名分最高的股票,也就是排在最前面的股票。用户可以在每日选股里查看到每个股票的综合排名分。
图1整齐的高低排列代表较好的排名策略
图2累计收益曲线展示更加详细的收益变化
反过来,如果在年化收益图中(如下图)各分段收益高低错落,则代表此排名策略的投资意义不强,即便排名策略在策略回测中收到较好的收益,也需要谨慎的使用这个排名策略。
图3高低不齐图形往往代表排名策略投资意义不强
如果排名指标里含有空值(NULL),那么无论从小到大排还是从大到小排空值一直排在最后。所以从大到小排名的80-100分段和从小到大排名的0-20分段收益不一定一样。如果将指标中的空值筛掉,从大到小的80-100分段和从小到大的0-20分段的收益将会一样或者非常近似。数据空值代表数据库里就没有这样的数据,比如有很多股票的预期盈利增长是空值,表明很多股票没有5年净资产收益率的数据。用户可以通过将指标放入到筛选条件来排除指标里的空值,只要指标在筛选条件使用,指标的空值就会被筛掉。比如筛掉市盈率中的空值,可用筛选条件市盈率>0。
以公共指标为原材料,用户可以自己定义更多的指标。比如:
5日20日均价差值=5日平均复权价–20日平均复权价
1日5日量比=当日成交量/5日平均成交量
5日前收盘价=ref(收盘价,5)
Ref(指标,天数),取得指标几个交易日前的值。当天数为0时,返回数据起始第一天的指标数据。例子“Ref(收盘价,5)”就是5个交易日前收盘价。“Ref(收盘价,0)”返回上市第一天收盘价,2007年以前上市的股票返回2007-01-04的收盘价。该函数支持变量天数的计算,例子:“Ref(收盘价,countbars(收盘价>0,9999)-5)”返回股票上市后第5天的收盘价。
BarRef(指标,天数),取得指标几根日K线前的值.和Ref()功能类似,很多情况返回同样的值.区别是Ref()包括停牌日,BarRef()跳过停牌日,只数几根K线。比如“barRef(收盘价,5)”就是5根K线前的收盘价。该函数支持变量天数的计算,例子:“BarRef(收盘价,countbars(收盘价>0,9999)-5)”返回股票上市后第5根K线的收盘价。
Delta(指标,天数),指标当天的值和N天前的值的差值。等于指标-Ref(指标,天数)。例子:“Delta(收盘价,5)”就是当天收盘价与5个交易日(包括停牌日)前收盘价的差值。
EMA(指标,天数)计算指标在过去几个交易日(不包含停牌日)的指数平均值;比如“EMA(收盘价,5)”就是过去5日指数平均收盘价。该函数的天数参数必须是常数,不可以是变量。
SMA(指标,天数,权重)计算指标在过去几个交易日(不包含停牌日)的平滑移动平均值。EMA(指标,天数)相当于SMA(指标,天数,2);比如“SMA(收盘价,5,1.5)”就是以1.5为权重的过去5日平滑移动平均收盘价。该函数的天数参数必须是常数,不可以是变量。
DMA(指标1,指标2),计算指标1在过去几个交易日(不包含停牌日)以指标二为平滑因子的动态移动平均。例子:“DMA(收盘价,换手率)”,表示以换手率作平滑因子的平均价。
WMA(指标,权重指标,天数)计算指标在过去几个交易日(不包含停牌日)的加权平均值;天数为0时,从数据起始日开始计算加权移动平均。比如“WMA(收盘价,当日成交量,5)”就是过去5日成交量加权平均收盘价,它比过去5日简单均线更能反映股票的成本线。“WMA(收盘价,当日成交量,0)”从上市第一天算起的加权平均收盘价(2007年以前上市的股票从2007-01-04算起的加权平均收盘价)。该函数支持变量天数的计算,例子:“WMA(收盘价,当日成交量,barslast(Crossover(5日复权均价,20日复权均价)))”返回股票自上次均线金叉以来的成交量加权平均收盘价。
DecayMA(指标,天数),对过去N天(不包含停牌日)的指标进行衰减加权滚动平均,越近的日期,权重越大。日期从最近到最远的值,分别乘以衰减权重N,(N-1),。。。1(权重最后进行标准化,使和为1)。例子:“DecayMA(收盘价,5)”就是过去5日收盘价的衰减加权平均。该函数不支持变量天数的计算
Med(指标,天数)计算指标在过去几个交易日(不包含停牌日)的中值;比如“Med(市净率,30)”返回过去30个交易日的市净率中值。该函数的天数参数必须是常数,不可以是变量。
Sum(指标,天数)计算指标在过去几个交易日(不包含停牌日)的聚合值;天数为0时,从数据起始日开始计算聚合值。例子:“Sum(当日成交量,10)”就是过去10日总成交量。该函数支持变量天数的计算,例子:“Sum(当日成交量,barslast(Crossover(5日复权均价,20日复权均价)))”返回股票自上次均线金叉以来的成交量之和。
Product(指标,天数),计算指标在过去几个交易日(不包含停牌日)的累乘值;天数为0时,从数据起始日开始计算累乘值。例子:“Product(1+1日涨幅,10)-1”就是过去10日涨幅;“Product(1+1日涨幅,0)-1”从上市第一天算起的总涨幅(2007年以前上市的股票从2007-01-04算起的总涨幅)。该函数不支持变量天数的计算
Max(指标,天数)计算指标在过去几个交易日(不包含停牌日)的最大值;天数为0时,从数据起始日开始计算。最大值。“Max(收盘价,10)”就是过去10日最高收盘价。该函数支持变量天数的计算,例子:“Max(收盘价,barslast(Crossover(5日复权均价,20日复权均价)))”返回股票自上次均线金叉以来的最高收盘价。
Min(指标,天数)计算指标过去几个交易日(不包含停牌日)的最小值;天数为0时,从数据起始日开始计算最小值。“Min(收盘价,10)”就是过去10日最低收盘价;“Min(收盘价,0)”上市以来最低收盘价(2007年以前上市的股票从2007-01-04算起的最低收盘价)。该函数支持变量天数的计算,例子:“Min(收盘价,barslast(Crossover(5日复权均价,20日复权均价)))”返回股票自上次均线金叉以来的最低收盘价。
Stdev(指标,天数)*计算过去几个交易日(不包含停牌日)的标准方差;天数为0时,整个数据历史上的标准方差。比如股价在过去20日涨幅波动率=”Stdev(1日涨幅,20)”;全部历史的涨幅波动率=”Stdev(1日涨幅,0)”。该函数支持变量天数的计算,例子:“Stdev(1日涨幅,barslast(Crossover(5日复权均价,20日复权均价)))”返回股票自上次均线金叉以来的1日涨幅波动率。
Var(指标,天数)*计算指标在过去N个交易日(不包含停牌日)的方差;天数为0时,整个数据历史上的方差。例子:var(收盘价,250)返回收盘价在过去250天的方差;var(收盘价,0)返回收盘价在过去全部历史的方差。该函数支持变量天数的计算,例子:“Var(1日涨幅,barslast(Crossover(5日复权均价,20日复权均价)))”返回股票自上次均线金叉以来的1日涨幅方差。
Percentile(指标,百分点,N天数),计算在过去N个交易日排名百分点对应的值,指标数值从大到小排序。
percentile(收盘价,0.95,21)过去21天里的第二高收盘价(95%分位点的价格)。
percentile(收盘价,0.12,10)过去10天里的第二低的收盘价(12%分位点的价格)。
四、时序回归函数(纵向回归函数)。最小二乘法线性回归函数。以下函数是对每一只股票的指标在连续的一段日期里进行聚合运算:
Forcast(指标,天数),计算指标在过去N个交易日(不包含停牌日)的线性回归预测值;天数为0时,计算指标在整个数据历史上的线性回归预测值。例子:Forcast(收盘价,20)用当天和过去19天一共20天的收盘价作线性回归,返回收盘价的预测值;Forcast(收盘价,0)用过去全部历史收盘价作线性回归,返回收盘价的预测值。该函数的天数参数必须是常数,不可以是变量。
Slope(指标,天数),计算指标在过去N个交易日(不包含停牌日)的线性回归斜率;天数为0时,计算指标在整个数据历史上的线性回归斜率。例子:Slope(收盘价,20)用当天和过去19天一共20天的收盘价作线性回归,返回过去20日的收盘价线性斜率;Slope(收盘价,0)返回过去全部历史的收盘价线性回归斜率。该函数的天数参数必须是常数,不可以是变量。
Neutralize(指标Y,指标X,天数),返回指标Y剔除指标X因素后的值。根据过去N个交易日(不包含停牌日)指标Y和指标X的线性回归模型,将指标X的成分从指标Y中剔除,中性化指标Y。天数为0时,根据过去整个数据历史的线性回归模型,清洗指标Y。例子:Neutralize(当日成交额,总市值,20)根据过去20日的线性回归模型,清洗当日成交额指标,返回剔出总市值成分后的当日成交额;Neutralize(当日成交额,总市值,0)根据过去全部历史的线性回归模型,清洗当日成交额指标,返回剔出总市值成分后的当日成交额。该函数的天数参数必须是常数,不可以是变量。
SlopeXY(指标Y,指标X,天数),返回指标Y和指标X过去N个交易日(不包含停牌日)的线性回归斜率;天数为0时,返回过去整个数据历史上的线性回归斜率。例子:Slopexy(当日成交额,总市值,20)返回过去20日成交额与总市值的线性回归斜率;Slopexy(当日成交额,总市值,0)返回过去全部历史成交额与总市值的线性回归斜率”。该函数的天数参数必须是常数,不可以是变量。
InterceptXY(指标Y,指标X,天数),返回指标Y和指标X过去N个交易日(不包含停牌日)的线性回归的Y轴截距;天数为0时,返回过去整个数据历史上的线性回归Y轴截距。例子:InterceptXY(当日成交额,总市值,20)过去20日成交额与总市值的线性回归Y轴截距;InterceptXY(当日成交额,总市值,0)返回过去全部历史成交额与总市值的线性回归Y轴截距。该函数的天数参数必须是常数,不可以是变量。
SSresid(指标Y,指标X,天数),返回指标Y和指标X过去N个交易日(不包含停牌日)的线性回归的残差平方和。该函数的天数参数必须是常数,不可以是变量。
RSquare(指标Y,指标X,天数),返回指标Y和指标X过去N个交易日(不包含停牌日)的线性回归的R平方;天数为0时,计算指标在过去整个数据历史上的线性回归的R平方。例子:RSquare(当日成交额,总市值,0)返回过去全部历史成交额与总市值的的线性回归的R平方。该函数的天数参数必须是常数,不可以是变量。
hNeutralize2(指标Y,指标X1,指标X2,指标X3,指标X4,范围)
多因子回归函数求残差函数,最多支持4个X指标。用法和hNeutralize()类似,只是可以支持最多4个X指标。比如“hNeutralize2(当日成交额,总市值,20日涨幅,0)”对全部A股的股票作线性回归,返回排除总市值和20日涨幅影响的当日成交额残差值。
hNeutralizeMI(指标),返回市值和行业中性化的指标。比如hNeutralizeMI(EP)返回EP的市值和行业中性化后的值。
hScale(指标,范围),将指标的值标准化,使所有股票指标的绝对值的和为1。例子:“HScale(EP,0)“返回在全部A股里标准化后的EP值。范围可以是0,1,2;含义同上。
hDemean(指标,范围),返回指标减去范围内全部股票的指标在当天的平均值,等同于“指标-HAvg(指标,范围)”。围可以是0,1,2;含义同上。例子:“HDemean(BP,1)“返回BP减去股票同一级行业内的股票平均BP。
hDemedian(指标,范围),返回指标减去范围内全部股票的指标在当天的中值,等同于“指标-HPercentile(指标,0.5,范围)”。围可以是0,1,2;含义同上。例子:“HDemedian(BP,1)“返回BP减去股票同一级行业内的股票BP中值。
SPercentile(指标,分位数,股票池,范围)
范围等于0(默认值)时,返回股票池内指标的当天分位值,范围等于1或2时,返回股票池一级行业或二级行业内的股票指标的当天分位值。例子:“SPercentile(收盘价,0.9,低价股,0)”返回股票池“低价股”中的股票在当天的收盘价的90%分位值,也就是收盘价最高10%的值。
SWinsorize(指标,上限分位,下限分位,股票池,范围)
在股票池内使用简单分位数去极值。范围等于0(默认值)时,返回股票池内指标的当天去极值化的值,范围等于1或2时,返回股票池一级行业或二级行业内的股票指标的当天去极值化的值。例子:“SWinsorize(收盘价,0.01,0.05,低价股,0)“在股票池”低价股”中,将收盘价最高的1%的股票的收盘价设为99%分位的收盘价,将收盘价最低的5%的股票的收盘价设为5%分位的收盘价。
SStandarize(指标,股票池,范围)
范围等于0(默认值)时,返回股票池内指标的标准化值。范围等于1或2时,返回股票池一级行业或二级行业内的指标的标准化值。例子:“SStandarize(市盈率,低价股,0)“返回股票池“低价股”中的市盈率的标准化值。对于熟悉统计学的用户,标准化值就是Z分数。
SNeutralize(指标Y,指标X,股票池,范围)
范围等于0(默认值)时,返回股票池内的指标Y剔除指标X因素后的值。范围等于1或2时,返回股票池一级行业或二级行业内的指标Y剔除指标X因素后的值。根据指标Y和指标X的线性回归模型,将指标X的成分从指标Y中剔除,指标Y相对指标X中性化。比如“SNeutralize(当日成交额,总市值,低价股,1)”,对股票池“低价股”同一行业内的股票作线性回归,返回市值中性的当日成交额。
SNeutralize2(指标Y,指标X1,指标X2,指标X3,指标X4,股票池,范围)
多因子回归函数求残差函数,最多支持4个X指标。用法和SNeutralize()类似,只是可以支持最多4个X指标。比如“SNeutralize(当日成交额,总市值,20日涨幅,低价股,0)”对股票池“低价股”内的股票作线性回归,返回排除总市值和20日涨幅影响的当日成交额残差值。
Svalue(起始日期,股票池)返回股票池从起始日期开始计算的净值,起始日期和起始日期之前的净值设置为1。净值计算假设股票池中的股票等权重。例子:Svalue(2010/01/04,低价股),返回股票池“低价股”以2010/01/04为起始日的净值。
SScale(指标,股票池,范围)
将指标的值标准化,使股票池内所有股票指标的绝对值的和为1。例子:“SScale(EP,中证800,0)“返回在中证800股票池里标准化后的EP值。范围可以是0,1,2;含义同上。
SBelong(股票池),判定当前股票是否属于股票池,如果当前股票属于股票池返回1,否则返回0。例子:sbelong(次新股票),如果股票属于“次新股票”池,返回1,否则返回0。
Square(指标)计算指标的平方。例子:“Square(收盘价)“得到收盘价的平方。
过去10天里涨停的天数=“CountDays(当日涨停标记=1,10)”过去30天里停牌的天数=“CountDays(当日成交量=0,30)”过去30天里出现金叉的天数=“CountDays(Crossover(5日复权均价,20日复权均价),30)”
该函数支持变量天数的计算,例子:
上次发生金叉后股价上涨天数=“CountDays(1日涨幅>0,barslast(Crossover(5日复权均价,20日复权均价)))”
CountBars(条件,天数N),统计在过去N个交易日里(不包含股票停牌日),条件值为真的天数。例子:
过去10天里涨停的天数=“CountBars(当日涨停标记=1,10)”。
上次发生金叉后股价上涨天数=“CountBars(1日涨幅>0,barslast(Crossover(5日复权均价,20日复权均价)))”
CountBars与CountDays区别是CountDays()包括停牌日,CountBars()跳过停牌日,只数几根K线。
BarsLast(条件),统计条件为真最后一天到现在的交易日数量(不包股票含停牌日)。例子:连续涨停的天数=“BarsLast(当日涨停标记=0)”,也就是距离上次没有涨停的天数。BarsLast()与DaysLast区别是DaysLast()包括停牌日,BarsLast()跳过停牌日,只数几根K线。
IfNULL(指标1,指标2),如果指标1为空值,返回指标2,否则返回指标1。指标2可以是常数或表达式。例子:"ifNULL(市盈率,0)",如果股票的市盈率是空值,返回0,否则返回市盈率。
Null(),返回NULL值。用于构造返回NULL值的表达式。比如PEG=if(or(EP<0,新预期盈利增长<0),null(),1/EP/新预期盈利增长),如果EP小于0或者预期盈利增长为负数,返回空值,否则返回计算的值。
DayW(顺序标记),返回今天是周内第几交易日,如果顺序标记=0,返回周内正数第几个交易日,如果顺序标记=1,返回周内倒数第几个交易日。比如今天是2017/04/06,DayW(0)返回2,表示今天是周内第2个交易日,DayW(1)返回2,表示今天是周内倒数第2个交易日。
DayM(顺序标记),返回今天是月内第几交易日,如果顺序标记=0,返回月内正数第几个交易日,如果顺序标记=1,返回月内倒数第几个交易日。比如今天是2017/04/06,DayM(0)返回2,表示今天是月内第2个交易日,DayM(1)返回17,表示今天是月内倒数第17个交易日。
DayY(顺序标记),返回今天是年内第几交易日,如果顺序标记=0,返回年内正数第几个交易日,如果顺序标记=1,返回年内倒数第几个交易日。比如今天是2017/04/06,DayY(0)返回61,表示今天是年内第61个交易日,DayY(1)返回184,表示今天是年内倒数第184个交易日。
Level(15min,当日成交量)返回当天14:45到15:00的成交量。
Level(15min,ref(当日成交量,1))返回当天14:30到14:45的成交量。
Level(15min,ref(当日成交量,16))返回当天集合竞价的成交量。
Level(15min,ma(当日成交量,4))返回从14:00到15:00四个15分钟线的平均成交量。
Level(15min,sum(当日成交量,2))返回收盘前半小时的成交量。
Level(15min,sum(if(barofday()>8,当日成交量,0),85))返回最近5天下午成交量总和。
如果策略为实时策略,计算以当日交易时刻为基准。比如策略是10:00交易的实时策略,Level(15min,当日成交量)返回当天9:45到10:00的成交量,Level(15min,ref(当日成交量,1))返回当天9:30到9:45的成交量。
Level里面能支持函数有:时序函数包括Ref(),MA(),EMA(),SMA(),WMA(),Med(),Sum(),Max(),Min(),Stdev(),Var()。横向统计函数包括HMax(),HMin(),HAvg(),HWAvg(),HMed(),HSum(),HStdev()。
AccuQ(季报指标,前移年数=0)返回季报指标的年内季度累计数据,前移年数=0时,返回最近季度年内累计数据。例子:假设现在最新的季报是2016Q3,AccuQ(营业收入,0)就是2016年1-9月的累计营业收入,而AccuQ(营业收入,1)就是2015年1-9月的累计营业收入。
持仓股票变量:
后复权买入价:$beginPrice
持有天数:$Days
买入后涨幅:$change。买入时点的价格到选股时点的价格的变化。
买入后最高点跌幅:$withdraw。买入后从最高收盘价到选股时点的价格的跌幅。比如跌幅是10%,$withdraw是0.1.
买入时排名:$beginRank
买入时排名分:$beginScore
最新排名:$rank
最新排名分:$score
持仓统计函数:
$max(指标,股票池代码)
$min(指标,股票池代码)
$sum(指标,股票池代码)
$avg(指标,股票池代码)
股票池代码可以是:1代表持仓股票池,2代表经过筛选条件的股票池,3代表经过筛选条件而且不在持仓股票池中的股票,即候选买入股票池。默认值是1。
$max(指标),返回持仓股票里的指标最大值。比如$Max(市盈率)返回现有持仓股票的最高市盈率。
$min(指标),返回持仓股票里的指标最小值。比如$Min(市盈率)返回现有持仓股票的最小市盈率。
$sum(指标),返回持仓股票里的指标之和。比如$Sum(成交额)返回现有持仓股票在选股日的成交额之和。
$avg(指标),返回持仓股票里的指标平均值。比如$avg(市盈率)返回现有持仓股票的平均市盈率。
使用例子:
卖出排名下跌10名以上的股票,可定义卖出条件$rank-$beginRank>=10
卖出在持仓股票中排名下降最多的股票,可定义卖出条件$rank-$beginRank=$max($rank-$beginRank)
如果买入后跌幅超过2个ATR,止损卖出,可定义卖出条件后复权收盘价-$beginPrice<0-2*ATR(14)
候选买入股票统计函数(候选股票是经过筛选而且不在仓内的股票)
$max(指标,3),返回候选股票里的指标最大值。比如$Max(市盈率,3)返回候选股票的最高市盈率。
$min(指标,3),返回候选股票里的指标最小值。比如$Min(市盈率,3)返回候选股票的最小市盈率。
$sum(指标,3),返回候选股票里的指标之和。比如$Sum(成交额,3)返回候选股票在选股日的成交额之和。
$avg(指标,3),返回候选股票里的指标平均值。比如$avg(市盈率,3)返回候选股票的平均市盈率。
函数中的“3”是候选股票池的代码。
卖出比候选股票排名靠后10名以上的持仓股票,卖出条件:$rank>=$min($rank,3)+10
卖出市盈率超过候选股票1.1倍的持仓股票,卖出条件:市盈率>=$min(市盈率,3)*1.1。
二十、K线聚合函数
将日线级别指标调整到周线或月线级别。目前有效的高K线级别有:y-年线,m-月线,w-周线。
KFirst(指标,高K线级别),返回高K线的第一个值。KFirst(开盘价,m),返回月线开盘价。
KLast(指标,高K线级别),返回高K线的最后一个值。KLast(收盘价,m),返回月线收盘价。
KMax(指标,高K线级别),返回高K线的最高值。KMax(最高价,m),返回月线最高价。
KMin(指标,高K线级别),返回高K线的最低值。KMin(最低价,m),返回月线最低价。
KSum(指标,高K线级别),返回高K线的和值。KSum(成交量,m),返回月线总成交量。
以下两图展示自定义指标管理器的使用方法。
图1点击自定义Tab中的管理图标,进入自定义指标管理器
图2用户可以在自定义指标管理器中添加、修改、删除指标
趋势择时
趋势择时有4个技术面指标,分别是MA(移动平均),MACD,DMA(平均线差指标),和TRIX(三重指数平滑移动平均指标)。当指标出现金叉时,转为牛市,即买入;当指标出现死叉时,转为熊市,即卖出。大盘指数默认为上证指数,用户可以在指标编辑界面选择其它主要大盘指数和行业指数。
MA金叉和死叉的判定条件
DMA=MA短线–MA长线(MA短线默认为上证5日均线,MA长线默认为上证60日均线。)
金叉条件:MA短线(t)>MA短线(t-1)andDMA(t)>0andDMA(t-1)<0
死叉条件MA短线(t)0
其中‘XX(t)’表示当日的指标,‘XX(t-1)’表示前一日的指标。以下公式皆同。
MACD金叉和死叉的判定条件
DIF(快线)=EMA短线-EMA长线(EMA短线默认为上证12日指数移动平均线,EMA长线默认为上证26日指数移动平均线。)
DEA(慢线)=EMA(DIF,M)(DEA默认为DIF的9日指数移动平均线。)
金叉条件:DIF(t)>0andDIF(t)>DIF(t-1)andDIF(t)>DEA(t)andDIF(t-1)
死叉条件:DIF(t)<0andDIF(t)DEA(t-1)
DMA金叉和死叉的判定条件
AMA=MA(DMA,M)(AMA默认为20日DMA移动平均)
金叉条件:DMA(t)>DMA(t-1)andDMA(t)>AMA(t)andDMA(t-1)
死叉条件:DMA(t)AMA(t-1)
TRIX金叉和死叉的判定条件
TR=EMA(EMA(EMA(上证指数,N),N),N)(N默认值为120天)
TRIX=(TR(t)–TR(t-1))/TR(t-1)
MATRIX=MA(TRIX,M)(M默认为5天)
金叉条件:TRIX(t)>TRIX(t-1)andTRIX(t)>MATRIX(t)andTRIX(t-1)
死叉条件:TRIX(t)MATRIX(t-1)
用户可以点击择时条件的编辑图标来修改条件参数。
成交量均线择时
成交量均线择时(MAVol金叉死叉)也是趋势择时的一种。MAVol是指数成交量的多日均线。量在价先,根据大盘成交量趋势来判定牛熊有可能比只用价格来判定取得更好的效果。
MAVol金叉死叉的判定条件
DMAVol=MAVol短线–MAVol长线(MAVol短线默认为上证5日成交量均线,MA长线默认为上证60日成交量均线。)
金叉条件:MAVol短线(t)>MAVol短线(t-1)andDMAVol(t)>0andDMAVol(t-1)<0
死叉条件MAVol短线(t)0
反转择时
反转择时根据主要板块两个基本面指标PE(市盈率)和PB(市净率)来实现。当PE小于某个值时,市场过于悲观,可以抄底买入,发出牛市信号,即买入信号;当PE大于某个值时,市场过于疯狂,需要逃顶卖出,发出熊市信号,即卖出信号。PB择时的工作机制和PE相同。板块默认为全市场,用户可以自己选择主板,中小板和创业板作基本面择时。
趋势加反转择时
MA_Bias均线择时附加根据乖离率的逃顶和抄底。设计源于网络大V持有封基的乖离率择时。
这个择时需要设置4个参数,MA短线和MA长线是MA择时参数,金叉就是牛市,死叉就是熊市。
当MA短线高于MA长线超过上限(默认10%)时,转为熊市逃顶。当MA短线低于MA长线超过下限时(默认-10%)时,转为牛市抄底。
同时使用多个择时条件
一个策略可以同时使用多个技术面条件来判断大市的牛熊转换。比如一个策略同时使用了3个择时条件,在策略回测的高级设置中,用户可以分别指定牛市转换需要满足几个条件,熊市转换需要满足几个条件,比如这三个条件同时满足牛市条件才能转牛,但只要其中2个满足熊市条件,就能转熊。
限制
市场择时条件只对策略回测有效,不影响每日选股或者排名分析的结果。
策略回测计算只在调仓日根据牛熊条件判定买或者不买股票,不会在调仓周期中间某一天买入或卖出股票。
果仁策略研究界面将策略定义分成三个主要部分:选股、择时、交易。选股设置包括筛选条件和排名条件,择时设置就是市场择时,交易设置包含交易模型I--定期轮转重平衡仓位的交易模型和交易模型II--根据是否满足卖出条件来作轮转。(目前基金策略只支持交易模型I。)
交易模型I是果仁原有的定期轮动模型,在每个调仓日,卖出不满足选股条件的股票,买进满足选股条件的股票,所有仓内股票在调仓日重新平衡为等权重(除了那些因停牌或涨跌停而无法操作的股票)。这种模型尤其适合快速轮动短周期策略。
交易模型II是果仁新加入的交易模型,其特点是必须有单独的卖出条件。现在用户可以定义4个卖出条件,排名名次大于某个阈值,持有天数大于某个阈值,止盈和止损。仓内股票只要满足一个卖出条件,就会被卖出,也就是说卖出条件之间是或的关系。在调仓日,策略首先会卖出可以卖出的股票,然后使用仓内资金买入符合买入条件的股票。当仓内资金过少时(少于理想仓位的10%),就无法买入新股票。当股票不满足卖出条件时,就会被继续持有。所以如果卖出条件发生不频繁,即便是调仓周期只有1天,交易模型II的买卖次数也会比较少。相对于模型I,模型II的交易次数会比较少,而且个股的仓位一般不做重新平衡。
在交易模型I里,用户直接指定持仓股票个数,而在交易模型II里,用户使用个股理想仓位来间接指定持股股票个数。比如理想仓位是10%,则策略尽量用10%的仓内资金买入新股票,策略大约持仓10只股票。用户可以设定仓位偏离比例,只要在理想仓位的偏离比例内,个股仓位不作调整。比如理想仓位是10%,仓位偏离比例是30%,则股票仓位的合理范围是7%到13%,在这个范围内,仓位不作调整。当股票仓位低于这个范围而且在买入清单前面,则补仓至(尽量)理想仓位;当股票仓位高于这个范围,则卖出部分仓位,仓位调回到理想仓位。
在交易模型II里,用户还可设置新股票买入限制。进一步过滤来自于选股策略的买入清单。在买入清单的股票只要不满足一个限制,就会被过滤掉。注意:用户必须设置至少一个卖出条件,但不必设置买入限制。不设置买入限制,从选股策略来的所有股票都会被尝试买入。
选择模型I或模型II?
模型I更简单且容易理解,我们建议新用户首先使用交易模型I来研究策略。模型II不会在每个调仓日自动平衡仓位,交易频率较低,相对来说更容易操作。而且单独的卖出条件使模型II更加灵活。一些实盘的用户可以尝试使用模型II。
模型I策略如何变成摸型II策略?
比如下图1中模型I策略,选股条件为成交量>0,按价格从小到大排序,调仓周期为5天,持仓股票为10只。这个策略买入价格最低的10只非停牌股票,每5天调一次仓。转换到模型II策略时,选股条件不变,调仓周期可依然设为5天,而理想仓位为10%,即表示策略大约可以持有10只股票。卖出条件为排名名次大于等于11,即如果排名不在10名以内就卖出。这样设置的模型II可以和模型I有类似的结果.
图1模型I变成模型II。
模型I和模型II有些不兼容的设置。股票备选买入数量在模型I里可以被修改为0到20之间的任何数字,在模型II里,股票备选只数固定为5只,用户不可调。在模型I里,个股最大买入仓位默认为100%,意思是如果选股策略选出来的股票只能买入1只,那么100%的资金会投入到同一只股票里。在模型II里,个股最大买入仓位就是理想仓位,无论选出1只股票还是10只股票,都使用10%的仓位买入。模型I里不允许仓位偏离,在每个调仓日都要重新平衡所有股票的仓位,在模型II,股票仓位在一定范围内不用调整。以上区别使同一个选股策略在模型I和模型II之间收益不同。
模型II可以实现更严格的买入限制:比如只买入排名在前5名的股票(不设这个限制,则和模型I类似,前10名股票+5只备选股票都可以被买入)。仓内同行业的股票不超过3只,以分散行业风险。距离上次卖出间隔大于等于20天,这样刚卖出的股票不会在下一个调仓或下几个调仓日被买入。(模型II默认在调仓日卖出的股票不会再同一调仓日买入。)这个限制可以防止止损股票被立即买回的情况。加入这些买入限制后,一次能被买入的股票就会变少,这时缩短调仓周期,比如设置调仓周期为1天,可以实现逐步建仓的策略,这样不必在一天只内一定要买入10只股票。
在卖出条件里,可以适当放宽按排名卖出的条件,比如到排名20名以后才卖出,这样可以减少交易频度。用户还可以按照持有天数卖出,一只股票在仓内最长可以持有100个交易日,过了这个时期,无论排名再高,也要卖出。止赢止损也分别可以设置条件。
图2模型II的参数设置。
图2显示了比图1更复杂的模型II交易策略。所有的买入限制和卖出条件都被设置,调仓周期缩短为一天。通过这些交易条件的设置,我们可以看到模型II可以实现较为复杂的交易策略。
回测效果对比
将同样选股策略做过去4年回测,图1模型I和图2模型II得到的结果在图3和图4中展示。
图3模型I的回测结果
图4模型2的回测结果。
我们可以看到模型II交易策略可以减小最大回测率,增加夏普比率。注意在这里作者只是为了讲解目的,并没有对模型II交易策略作任何调优。模型II有可能得到比模型I更好的结果。
牛熊转换的仓位控制
牛转熊时,比如熊市仓位是30%,在模型I里,尽量将总仓位压到30%,如果有的股票停牌无法减仓,其它股票的仓位会减小更多;在模型II里,30%一方面代表总仓位的30%,另一方面是指个股理想仓位的30%,比如牛市里个股理想仓位是20%,则在熊市里个股理想仓位为6%,每只股票的仓位都会尽量向理想仓位靠,从而达到减仓至30%的目的。特殊情况是碰到停牌或涨跌停导致股票无法减仓,此时会继续以理想仓位(6%)持有不符合卖出条件的个股;而对于达到卖出条件的个股,将其卖出后如果仓位大于熊市仓位即30%,则不会买入新的股票。如果卖出后小于熊市仓位,则会根据排名条件依次以理想仓位(6%)买入新的股票,直到达到熊市仓位。
熊转牛时,模型I会将总仓位升到100%,满仓平权买入股票;模型II会将个股理想仓位复原,仓内的股票和新买入的股票仓位都会尽量向理想仓位靠拢。
排名分析是否受到交易模型的影响?
交易设置只影响策略回测的结果,对每日选股和排名分析都没有影响。排名分析使用类似于模型I的交易模型,但不会考虑停牌涨跌停的影响。它只受到选股设置的影响,完全忽略市场择时设置和交易设置。
使用股指对冲设置,可以回测策略对冲股指期货以后的收益情况。
股指对冲设置
在策略回测设置中,点击股指对冲标签页,可以看到如下设置:
由于受到政策影响,历史上保证金比例和贴水率变化很大,且不可重复,使用历史期货数据作回测对未来的指导意义较小。果仁对冲计算让用户自己根据未来的预期设置保证金比例和月贴水率,这样算出来的对冲收益对未来指导意义更大。
注意:对冲比例以及对冲收益计算不考虑手数约束。
仓位分配算法
每个资金调整周期开始时,果仁将总仓位按对冲比例分配成两个部分,一部分是策略仓位,另一部分是股指期货保证金仓位。以下为关系式:
总仓位=策略仓位+股指期货保证金仓位
=策略仓位+股指期货仓位*保证金比例
=策略仓位+策略仓位*对冲比例*保证金比例
=策略仓位(1+对冲比例*保证金比例)
将上式中的(1+对冲比例*保证金比例)移到等号左边,得到下式:
策略仓位=总仓位/(1+对冲比例*保证金比例)
总仓位是100%,表达式可以简化成策略仓位=1/(1+对冲比例*保证金比例)
如果对冲比例为100%,则表达式可进一步简化成:策略仓位=1/(1+保证金比例)
例子“对冲比例100%,保证金比例30%,则策略仓位=1/1.3=76.9%,期货保证金仓位=1-策略仓位=23.1%。
注意:策略仓位是股票策略的整体仓位,策略内部如果有空仓的闲置资金,都算入策略仓位。
收益计算
果仁每天根据前一天的策略资金以及股指期货资金计算当天的收益。对冲后日收益的组成部分有:策略本身的日收益,做空股指期货的日收益(包含股指期货的日贴水损失),如下式:
T日对冲后收益=T-1日策略资金*策略T日涨幅-T-1日股指期货资金*(股指T日涨幅+日贴水率)
其中:日贴水率=月贴水率/20。
再分别算出:
T日总资金=T-1日总资金+T日对冲后收益
T日策略资金=T-1日策略资金*(1+策略T日涨幅)
T日股指期货资金=T-1日股指期货资金*(1+股指T日涨幅-日贴水率)
其中T日策略资金和T日股指期货资金为T+1日对冲后收益计算输入。
这样重复计算可以得到每日总资金额,然后将其换算成对冲后收益净值曲线。
例子,对冲比例=100%,策略T日涨幅=2%,股指T日涨幅=1%,日贴水率=2%/20=0.1%,保证金比例=30%
假设T-1日的总资金为100万,并刚好进行了资金重平衡,那么按照上一节的算式,T-1日策略资金为76.9万,T-1日保证金为23.1万,T-1日股指期货资金为76.9万。(这里的计算不考虑手的约束。)
T日对冲后日收益=76.9*2%-76.9*(1%+0.1%)=0.692万
T日总资金=100+0.692=100.692万
T日策略资金=76.9*(1+2%)=78.438万
T日股指期货资金=76.9*(1+1%-0.1%)=77.592万
这样依此类推,可以计算出每个非资金调整日的总资金变化,当碰到资金调整日时则按上一节公式重新分配策略资金及股指期货资金。
果仁有两个交易模型,模型I和模型II,它们的调仓指令有不同的含义。
模型I调仓
模型I是一个定期调仓并且重新平衡仓位的交易模型。模型I对持仓股票的最大数量做出了规定,比如最多持有5只股票,意思就是在每个调仓日策略都试图买入或持有5只股票,每只股票的仓位是20%,当可以买入的股票数小于5只时,比如只有3只,策略会按照33%的个股仓位买入3只股票。(用户可以改变个股最大买入仓位100%的设置,设为比如20%,在这种情况下,即便只能买入3只股票,策略依然会按照20%的个股仓位买入3只股票,空出40%的仓位为现金。)
调仓指令有5个信号,卖出,持有,买入,持有(备选),买入(备选)。仓内的股票如果不符合选股条件,就要被卖出,如果依然符合选股条件,则继续持有。卖出股票空出来的资金就可以买入新的符合条件的股票。两个备选信号的目的是为了应对由于停牌或涨跌停而引起的股票不能买卖的情况。信号是买入的股票有可能停牌或一字涨停而无法买入,这时策略将会试图买入排在前列的备选股票,标记为买入(备选)。如果被持仓的股票也在备选名单里,这只股票的信号就是持有(备选),意思是如果排在它前面的股票可以被买入,则卖出这只股票,如果排在前面的股票不能被买入,则可以继续持有这只股票。
备选股票的数量默认是5只,用户可以在0只(也就是不要备选)和20只之间做调整。
模型I调仓指令首先列出需要卖出的股票,然后按排名顺序列出需要买入或持有的股票,排在最大持有只数以外的股票会标记为备选。举个例子,一个模型I策略最多持有2只股票,备选股票数为5只。当前持仓的股票为股票A(60%)和股票B(40%)。调仓日的调仓指令是:
1.股票A卖出2.股票C买入3.股票D买入4.股票B持有(备选)5.股票E买入(备选)6.股票F买入(备选)7.股票H买入(备选)8.股票G买入(备选)以上调仓指令,如果没有停盘和涨跌停这些复杂的因素,调仓结果就是卖出A和B,买入C和D,C和D的仓位各是50%。
以下例子列出一些停牌情况的调仓结果:
停牌情况调仓后持有股票C停牌B(50%)和D(50%)--卖出A,无法买入C,顺位买入D和继续持有B。B和D的仓位重平衡。B和C停牌B(40%)和D(60%)--卖出A,无法买入C,顺位买入D和继续持有B。B的仓位不变。C和D停牌B(50%)和E(50%)--卖出A,无法买入C和D,顺位继续持有B和买入E。B和E的仓位重平衡。A停牌A(60%)和C(40%)--无法卖出A,只有一个空位,卖出B,买入C。A的仓位不变。B停牌B(40%)和C(60%)--无法卖出B,只有一个空位,卖出A买入C。B的仓位不变。以上策略,在调仓后,仓内两只股票的仓位将尽量调整为50%,即便是A和B一直持有下去它们的仓位也会每次重平衡为50%。当A和B有停牌的情况时,停牌股票的仓位不变。模型I仓位总的原则是:当仓内股票停牌时,这只股票的仓位保持不变,余下的资金平均买入或持有股票。
一字涨跌停会使一只股票不能买或不能卖,处理方式和停牌一样。比如,当A一字跌停时,无法卖出,按照A停牌处理。当C和D一字涨停时,无法买入,按照C和D停牌处理。当B一字跌停时,无法卖出,按照B停牌处理,B一字涨停时,无法买入补平仓位。
模型II调仓
模型II定期卖出符合卖出条件的股票,再用空下的资金按顺序买入在清单里的股票。和模型I不同,模型II不规定最多持仓股票数,而是规定个股理想仓位。比如想持有两只股票的策略可以设定理想仓位为50%。当策略买入新股票时,将尽量按照50%的总仓位买入新股票,如果仓内资金不足50%,则能买多少是多少。当仓内资金小于理想仓位的十分之一时,则不再买入新股票,以避免造成碎片化持股。比如理想仓位是50%时,仓内资金小于5%,则不再买入新股票。和模型I的一个重要区别是模型II有仓位偏离比例概念,也就是说只要股票仓位在理想仓位的偏离范围之内,在调仓日就可以保持现有仓位,不作重新平衡。如果股票仓位在偏离范围之外,在调仓日就需要减仓或补仓。比如理想仓位是50%,仓位偏离范围是30%,则这只股票的最低合理仓位是50%*(1-30%)=35%,最高合理仓位50%*(1+30%)=65%。当股票仓位高于65%时,策略会减仓这只股票到理想仓位;当股票仓位低于35%时,而且被策略选中时,会尽量加仓至理想仓位。
模型II的调仓信号有5个,卖出,减仓至目标仓位,持有,买入,加仓至目标仓位。(目标仓位也就是理想仓位。)当仓内股票符合一个卖出条件时,就被卖出;当仓内股票不符合卖出条件时,有三种情况,第一种情况是仓位在偏离范围之内,维持原有仓位不变,标记为持有;第二种情况是仓位高于最高合理仓位,减仓至理想仓位,标记为减仓至目标仓位;第三种情况是仓位低于最低合理仓位而且被策略选中,加仓至理想仓位,标记为加仓至目标仓位。一只新股票被策略选中时,将按理想仓位买入,标记为买入。
模型II也有备选股票的概念,备选只数固定5只。比如调仓日需要买入1只股票,模型II会推荐1+5=6只买入(或加仓)的股票。意思是如果排在前面的股票能买入,就买入,如果不能买入,就试图买入排在后一名的股票,直到可以买入股票为止或者扫描完买入清单为止。当策略有较严格的买入条件时,比如在新股买入限制里设定排名名次小于等于3,备选股票可能小于5只股票。
使用一个和模型I类似的例子,一个模型II策略的理想仓位是50%,仓位偏离范围是30%。备选股票数为5只。当前持仓的股票为股票A(60%)和股票B(40%)。调仓日的调仓指令是:
1.股票A卖出2.股票B持有3.股票C买入4.股票D买入5.股票E买入6.股票F买入7.股票H买入8.股票G买入模型II调仓指令首先列出需要卖出和减仓的股票,然后列出继续持有的股票,最后列出需要买入和加仓的股票。
上例中股票A满足卖出条件,需要卖出。股票B的仓位是40%,在合理的仓位范围(35%到65%)之内,所以仓位不变,继续持有。接下会有6股票按先后顺序在买入清单里。如果所有的股票都可以买卖,调仓的结果是B(40%),C(50%),D(10%)。也就是卖掉股票A后,将得到60%资金,用50%买入C,用剩下的10%买入D。(这里需要注意的是个股的仓位权重是按照调仓日前一天的收盘价算出,在调仓日,由于股票价格波动,股票的仓位会变化,所以股票A被卖出后,得到的资金有可能比60%多,也有可能比60%少,所以C和D的仓位,尤其的是D的仓位,会根据调仓日的实际情况作出决定。这里只是为了说明方便,忽略价格波动引起的仓位变化。)
以下列出一些停牌情况和调仓结果的例子:
停牌情况调仓后持有股票C停牌B(40%),D(50%),E(10%)--卖出A,无法买入C,顺位买入D和E。A停牌A(60%),B(40%) --无法卖出A,无法调仓。C和D停牌B(40%),E(50%),F(10%)--卖出A,无法买入C和D,顺位买入E和F。以上例子表明,模型II会尽量按理想仓位买入新的股票,当资金不足时,也会买入部分仓位的股票,而不是让资金闲置。比如用50%的仓位买入C,用10%的仓位买入D,这时D的仓位小于最小合理仓位35%,所以到下一个调仓日,如果有足够资金而且D排在股票清单前列,将被加仓。
模型II另一特点是不会频繁自动平衡仓位,只要个股仓位在合理范围之内,仓位就保持不变,这和模型I在每个调仓日重平衡仓位很不一样。
以上所介绍的都是果仁量化引擎如何去执行调仓指令,果仁的调仓历史和实盘收益是按照这一套规则计算出来的。用户在实际执行调仓指令时,在仓位和买卖价格方面必然会有一些差别,最后的结果可能比果仁的结果好也有可能比果仁的结果差。
用户有很多时候需要在指定的几只股票或几只基金里制作轮动策略,比如在4只银行股票里轮动或者在两个基金里做二八轮动。这时候,就需要使用股票池(或者基金池)。
一个股票池可被看作一个自定义投资域,股票池功能可以让用户为策略设定一个更灵活的投资域。用户可以到我的主页里创建股票池.股票池分为三种:静态股票池,动态股票池和合成股票池。静态股票池是一个手工键入的股票代码集合(或者拷贝粘贴一个股票代码表)。静态股票池是最常用的一个股票池,使用静态股票池用户可以实现几只股票之间的轮转策略,比如几个银行股票之间的轮转策略。动态股票池是根据选股条件和排名条件产生的动态股票集合,股票清单可以每日动态变化。使用动态股票池,用户可以实现分层量化策略,也就是将筛选排名条件分在两步里完成,这样策略的表达能力更强。比如用户可以首先创建一个动态股票池:总市值和股价综合排名最小的100只股票,然后再在这个股票池里面选择市盈率最小的10只股票。动态股票池创建界面和策略创建界面及其相似,只是更简单些,没有策略回测那些设置。合成股票池可以实现两个股票池之间的集合操作,目前合成股票池的功能还很简单,只实现了黑名单的功能。也就是股票全集减去黑名单股票池。
创建股票池在个人主页的股票池页进行。一经创建,就可以在创建股票策略->选股设置页面里的选择范围使用股票池。选择范围默认是全部股票,用户可以通过下拉菜单看到可以使用的股票池。
基金池和股票池基本一样,区别是基金池里的代码都是基金代码,而股票池里的代码是股票代码。基金池目前不支持动态基金池,只有静态基金池和合成基金池。除了基金以外,静态基金池还可以放入指数代码,支持指数回测。比如对上证指数进行回测,可以创建一个静态基金池,键入上证指数代码“000001I”,在果仁网里,所有的A股指数代码都有一个”I”(大写的i)后缀,以区别于股票/基金代码。
股票池使用示例
示例1四大银行轮动策略
1在个人主页—>股票池,点击’+’图标,首先选择股票池类型,如下图:
2创建一个4大银行的静态股票池,我们可以将四大银行(即工商银行601398,建设银行601939,农业银行601288,中国银行601988)的股票代码直接输入到股票列表里,然后点击保存。如下图:
3创建股票池完毕后,去创建股票策略->选股设置页面,“四大银行”股票池出现在选择范围的下拉菜单里,如下图。
4选择四大银行股票池,就可以制作在四大银行之间轮动的量化策略。使用每日选股可以确认股票池里的股票确实是四大银行。如下图。
示例2排除四大银行的银行股轮动策略
有用户认为四大银行没有增长潜力,需要制作非四大行的银行量化轮动策略。这时候,可以将四大银行股票池作为黑名单,从股票中排除。
1在个人主页->股票池页面,创建一个合成股票池“排除四大行“,定义是”全部股票排除四大银行“。
2在创建股票策略->选股设置页面,选择范围设定为“排除四大行“,行业为“银行”,通过每日选股,可以看到银行股票列表里已经排除四大行。如下图。
3现在可以制作出一个非四大行的银行个量化策略。比如按照示例1的公式做出一个最小市盈率非四大行银行股策略,最近四年的总收益是181%。如下图。
示例3指数轮动回测
1比如创建一个沪深300和中小板指数的轮动策略。首先可以创建一个指数池,叫做“沪深中小指数轮动”如下图:
这里需要注意指数代码后面需要加一个后缀”I”(大写的i),以便和股票基金代码区别。
2比如创建一个沪深300和中小板指数的轮动策略。首先可以创建一个指数池,叫做“沪深中小指数轮动”如下图:
3设置选股排名条件进行回测,步骤类似上例,省略。
示例4动态股票池示例
使用动态股票池可以做出更加复杂或更加灵活的选股策略。比如从市盈率最小的100只股票里选出市值最小的5只股票持有策略。
1创建一个叫做“小PE100”的动态股票池,定义是市盈率最小的100只股票。下图显示这个动态股票池的定义。
2基于这个股票池创建一个市值最小的5只股票策略。如下图设置
3最近4年的回测结果如下:
专业投资者和一般股民最大的差别是专业投资者有能力将选股策略放回到真实的历史数据中回测,做出客观的评估。
专业投资者的投资流程大致分为3步:
在果仁网上,股民可以使用鼠标点击在几秒之内创建选股策略,并在真实的历史数据中评估策略的有效性。有了这个能力,业余人士和专业人士的差距就大大缩小了。
果仁网的选股策略和回测流程是基于以下投资理念而设计的:
用户首先选择几类指标制定选股策略,然后查看每日选股结果,如果符合预期,可在历史的日期区间进行回测。下图展示使用流程,非常简单。
以上只是真实还原历史的一部分复杂点。即便是专业投资者也需要花费很多资源来解决真实还原历史的问题,对于严肃的业余投资者来说,想在真实的历史数据作回测,到目前为止,基本是不可能的。果仁网为一般用户提供了真实的历史回测平台,为理性评估选股策略是否会赚钱提供了可能。