量化交易backtrader实践(五)_策略综合篇(2)_简单叠加

01_逻辑函数

A_backtrader的逻辑函数

在backtrader中,有一些经常使用的逻辑函数,它们可以直接用在__init__()中,注意它们的返回值都是"线" lines,这些函数不能放到next()里去使用。

  • bt.And:用于逻辑与操作,当所有条件都满足时返回True。
  • bt.Or:用于逻辑或操作,当任一条件满足时返回True。
  • bt.If:用于条件选择,类似于Python的三元操作符,如果条件为真,则返回第一个参数,否则返回第二个参数。
  • bt.All:与bt.And相同,用于检查所有条件是否都满足。
  • bt.Any:与bt.Or相同,用于检查至少有一个条件是否满足。
  • bt.Cmp:用于比较两个线对象,如果第一个大于第二个则返回1,否则返回-1。
  • bt.Max:返回同一时刻所有线对象中的最大值。
  • bt.Min:返回同一时刻所有线对象中的最小值。
  • bt.Sum:对同一时刻所有线对象进行求和。

B_股票软件的逻辑函数

我们再来看一下股票软件中的逻辑函数

  • CROSS
  • DOWNNDAY
  • EVERY
  • EXIST
  • IF
  • LAST
  • LONGCROSS
  • NDAY
  • UPNDAY

这些与backtrader的逻辑函数在某一些功能上是相对应或相似的。而我们这一节的主要实践内容,就是使用这些函数,将相关的指标或条件给组合起来。

C_简单应用

001_多头排列DTPL

N:=5;
N1:=10;
N2:=20;
N3:=30;

A1:=MA(CLOSE,N);
A2:=MA(CLOSE,N1);
A3:=MA(CLOSE,N2);
A4:=MA(CLOSE,N3);
CLOSE>A1 AND A1>A2 AND A2>A3 AND A3>A4 AND CLOSE>OPEN;

多头排列的指标公式如上,其实就是用AND把多个条件联合起来。这个指标公式也是股票软件的内置指标,所谓多头排列就是MA5在MA10之上,MA10在MA20之上,以此类推。这样,就在数据表格中添加了一列判断,假设列名为 Signal1,这一列就记录了每一个时间索引下多头排列的条件是否满足,用True/False表示。类似的指标还有KTPL等。

在backtrader中,就可以使用bt.AND()将这些条件做成线(lines)

002_连涨数天UPDAY

在股票软件中,还封装了很多函数来简化指标公式的代码,比如要判断连涨5天,如果自己用AND需要写成

b3: C>REF(C,1)
AND REF(C,1)>REF(C,2)
AND REF(C,2)>REF(C,3)
AND REF(C,3)>REF(C,4);

而如果使用系统提供的内置函数,则可以使用COUNT(x,N)=N或UPNDAY进行

up:=C>REF(C,1);
b2:COUNT(up,4)=4;


B1:UPNDAY(C,5);

而我们在backtrader中,就需要自己制作indicators来实现了

import backtrader as bt

class UPNDAY(bt.Indicator):
    lines = ('upnday',)
    params = (('period', 5),)

    def __init__(self):
        self.lines.upnday = bt.indicators.CustomUpNDay(self.data.close, period=self.p.period)

class CustomUpNDay(bt.Indicator):
    def __init__(self, data, period):
        self.data = data
        self.period = period
        self.upnday = self._upnday(self.data, self.period)

    def _upnday(self, data, period):
        upnday = [0] * period
        for i in range(period, len(data)):
            if data[i] > data[i - 1]:
                upnday.append(1)
            else:
                upnday.append(0)
        return upnday

003_两指标综合

多指标综合在股票软件中可以通过综合选股的选项得到,如下图我们先使用了KDJ指标并选择K上穿D为第一套条件,然后在形态特征中选择了多头排列为第二套条件,这两组条件相与。

在股票软件中,这个操作是多用于选股,这是一个很好的引导,当然我们在买卖策略上也可以这么去使用,也就是同时满足两组条件的情况下开仓买入。比如说使用DTPL和威廉指标的买点相结合

在这个组合指标公式中,将DTPL和WR_buy相与,就得到了两者都满足的买入信号OUT。在这里我们看到了股票软件除了技术指标之外,在选股指标的大类中还有走势特征,形态特征甚至基本面等小类,其中走势特征包含如单日放量,持续缩量等,而形态特征中包含如早晨之星,出水芙蓉,蜻蜓点水,多头排列等多根K线的形态,这些不仅仅可以用在选股中,也可以作为买卖的指标项。

只不过到了backtrader中,这些形态特征、走势特征都需要自己来写相关的自定义indicators了。我们可以把完成的单个自定义指标放到策略类中来,再用bt.And以及bt.Or等逻辑函数把它们组合起来,形成更加强大和有效的组合指标。

但是,这里的组合只针对买入条件,前面我们就说过了,在股票软件中对于卖出策略几乎就不控制,但对于backtrader回测来说,卖出策略却是不可或缺的。因此,请千万注意这一点,在进行买入条件组合的时候,也需要考虑卖出条件。

D_典型多指标组合

D01_双金叉组合

参考文章

 市场最常用的技术指标是KDJ与MACD指标。KDJ指标是一种超前指标,运用上多以短线操作为主;而MACD又叫平滑异同移动平均线,是市场平均成本的离差值,一般反映中线的整体趋势,这两者结合起来判断市场可以更为准确地把握住KDJ指标短线买入与卖出的信号。

一般来说,只要两个交叉的策略组合一下,都能算做双金叉,常见的有均线金叉比如5-10,5-20等,还有就是MACD,KDJ,RSI 等,一般常用的指标两两结合就能够组成所谓的双金叉组合。

然而并不是任意的两个指标组成的双金叉组合都是有效的,有些指标的特点,周期往往类似,比如KDJ,WR,RSI,CCI等相对强弱指标,行情起来时都是金叉,行情下跌时都是死叉;还有些指标的特点和周期却差得太远,两个指标几乎没什么关联,这样的双金叉也没有什么叠加效果,基本上也就只跟着某一个指标在走。

我们可以尝试一下参考文章的MACD+KDJ的双金叉策略,并用backtrader来回测它与单独用MACD或单独用KDJ的收益等评价指标;另外也把ADTM和KD中的RSV与K的金叉组合成策略来测试一下。

SJC01_MACD+KDJ双金叉

现在我们有两套工具,股票软件以及backtrader,在测试某个策略时一方面可以用backtrader得到它的精确的回测结果和评价,另一方面又可以到股票软件中从细节的图形中去分析和思考。

首先,在股票软件中把KDJ和MACD的两组公式放到一起,KDJ的金叉命名为G1,MACD的金叉命名为G2,两者同时金叉则命名为G3,为了能把三者区分开,分别乘上了0.6,1.1,1.5的系数。所有的参数全部使用默认,即KDJ的9,3,3;MACD的12,26,9。

RSV:=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100;
K:=SMA(RSV,M1,1);
D:=SMA(K,M2,1);
J:=3*K-2*D;
G1:0.6*CROSS(K,D);

DIF:=EMA(CLOSE,SHORT)-EMA(CLOSE,LONG);
DEA:=EMA(DIF,MID);
MACD:=(DIF-DEA)*2,COLORSTICK;
G2:1.1*CROSS(DIF,DEA);

G3:1.5*(G1 AND G2);

当副图指标编写好了后,在几支股票上观察,可以发现有的股票几乎不出现二者同时金叉,而有的股票容易出现。比较常见的情况是KDJ出现但MACD不出现,或者KDJ先出现MACD金叉会迟几个周期再出现。

从上图三次双金叉进行分析,第1次双金叉在收盘买入是能获利的,但第2次和第3次收盘价几乎是最高价,相当于买入就会被套。分析一下原因,KDJ的周期是9的短周期,而MACD是EMA12和EMA26这两个周期,从周期长短来看,KDJ是明显快于MACD的。而要使不同周期的金叉出现在同一天,那就意味着当天的K线一定是至少中阳,从上图三次的涨幅分别是12%,15%,8%可以证明。因此,对于主板的一些弹性一般的个股而言,它很难在同一天中出现双金叉。

根据以上分析,KDJ+MACD的双金叉适用的股票可能并不多,而且成功率也不高,容易碰到指标触发已经涨过了的情况。但换个思路,它可以帮助我们筛选出弹性比较好的股票。

接着在backtrader中使用双金叉组合策略进行回测。

class double_gold_crs(BaseSt):
     params = (
         ('stra_name','双金叉1'),
         ('p1',24),  
         ('tradeCnt',1),
         ('sucessCnt',0),)            
               
     def __init__(self): 
         self.order = None
         
         macd = bt.indicators.MACD(self.data)
         kdj1 = bt.indicators.Stochastic(self.data,period=9)

         crs1 = bt.indicators.CrossUp( macd.l.macd,macd.l.signal)
         crs2 = bt.indicators.CrossUp( kdj1.l.percK, kdj1.l.percD)
         self.crs = bt.And(crs1, crs2)

如果代码按照上面这样写,那么crs1和crs2会在副图中出现,但self.crs是不会绘制的,bt.And() 在 Backtrader 中并不是一个指标(indicator),而是一个逻辑操作符,用于组合多个条件。因此,它默认情况下不会在图表上绘制。要绘制它可以通过自定义指标的方式来实现。

class DoubleCrs(bt.Indicator):
    lines = ('crsup',)  # 定义输出线
    params = (
    ('p1',24),('p2',6),)

    def __init__(self):
        macd = bt.indicators.MACD(self.data)
        kdj1 = bt.indicators.Stochastic(self.data,period=9)
        crs1 = bt.indicators.CrossUp( macd.l.macd,macd.l.signal, plot=False)
         
        crs2 = bt.indicators.CrossUp( kdj1.l.percK, kdj1.l.percD)
        crs = bt.And(crs1, crs2)
        
        self.lines.crsup = crs
        super(DoubleCrs, self).__init__()

定义后的指标就可以在副图上绘制输出了,这样就能观察到双金叉的出现位置。下图出现2次双金叉的情况,但很明显这两笔交易都是亏钱的,在这里我们又发现了双金叉的另一个问题,就是处在连续交叉的过程中,也会让KDJ和MACD同时产生金叉,但这种都是无效金叉,金叉之后马上死叉,并不是好的买入点。 

SJC02_ADTM+RSV双金叉

在第三章第6节中,已经讨论过ADTM这个指标——动态买卖气指标,从计算公式上看,它的计算逻辑与RSI很相似,但使用的价格不是收盘价而是开盘价,它把上涨段定义为买盘DTM即开盘价高于上个周期,而把下跌段定义为卖盘DBM即开盘价低于上个周期开盘价。所以它是从另一个维度对当前的行情做出的指标。

KD随机指标,它的原始随机值RSV(Raw Stochastic Value)是使用收盘价减最低价再除以(H-L)得到的,也就是收盘价与最低价的关系。

这两个指标联合就可以得到开盘价的关系以及收盘价和最低价的关系两套,同时出现金叉时也就是买方力量增强的同时收盘价也在上升,形成了合力。我们先在股票软件中实现这个指标:

N:=23;
M:=8;
N2:=9;
M1:=3;

DTM:=IF(OPEN<=REF(OPEN,1),0,MAX((HIGH-OPEN),(OPEN-REF(OPEN,1))));
DBM:=IF(OPEN>=REF(OPEN,1),0,MAX((OPEN-LOW),(REF(OPEN,1)-OPEN)));
STM:=SUM(DTM,N);
SBM:=SUM(DBM,N);
ADTM:=IF(STM>SBM,(STM-SBM)/STM,IF(STM=SBM,0,(STM-SBM)/SBM));
MAADTM:=MA(ADTM,M);

G1:0.5* CROSS(ADTM,MAADTM);

RSV:=(CLOSE-LLV(LOW,N2))/(HHV(HIGH,N2)-LLV(LOW,N2));
K:=SMA(RSV,M1,1);

G2:0.7*CROSS(RSV,K);

G3:1.2* G1 AND G2;

选择某几支股票进行观察,把ADTM买卖气指标金叉为0.5,RSV与K的金叉为0.7,两者同时发生金叉则为1.2,在副图1上就可以把双金叉的情况显示出来。

由图可知,对于某些股票在某些情况下,双金叉形成是有概率形成一波上涨的。同时也观察到第一个红箭头之前6个周期也有双金叉产生但并没有上涨,简单分析可以看到RSV上穿K值后马上又下穿回去,所以它的上升力量没有持续。再从成交量上看,这个双金叉位置没有成交量的放大,而后面2次双金叉位置都伴随着放量,这里我们还可以添加一个成交量大于5周期平均的条件。

在加上成交量的条件后,优点是会规避一些下跌阶段的缩量的双金叉错误买入点,但缺点是某些大涨前的缩量也被避开了。

研究指标叠加的时候还需要明白这两个指标本身的灵敏度,KDJ已经是非常灵敏的指标,而过滤之前的RSV是和威廉指标相同的高灵敏度的,所以高灵敏度必然对应着高失效率,很多时候当天人气上来了,两个指标都金叉,但第二天由于其他的原因又跌下去了,这都是很正常的情况,可能就是突破上篮迈出一步被堵截,所以需要变向、转身,然后再突破的几个步骤,有概率上篮得分当然也有概率投不进。

目前而言,这个组合策略在backtrader中还实现不了,原因是只有买入点没有卖出点。我们已经制定了双金叉买入的策略,但根本没有正确且有效的卖出点策略,从上面的图可以看到,第一次买入后在RSV与K的死叉卖出是不错的,但对于第二次来看,死叉位置卖出后还有很大一段上涨。这就涉及到买入点和卖出点采用不同指标策略的问题,先简单的看一下,这里采用KAMA,EMA9,MA5,以及固定盈亏,还有BOLL和左高压力线(唐奇安通道)得到的盈利是不同的,可能收益最好的是阳线突破左高那根K线的收盘价卖出吧。但是,它突破左高或许继续上涨呢?

从这些分析我们能够更深刻的认识到“会买的是徒弟,会卖的是师傅”这句话的含义了。你使用固定涨10%卖出,有可能这支股票恰好就涨到10.1%然后回落下跌,此时就相当于是MVP的卖出策略,但它要恰好只涨到9.9%呢?或者它会涨到50%呢?行情走完了再来选卖出策略是没有意义的,所以稳健的、激进的、可能的、恰好的......你需要使用哪一种呢?所以我们很有必要把这些卖出策略都做出来,并在backtrader中进行回测,某些股票在某段时间适合某种卖出策略这个结论我们早就提出来了,但能不能把它们具体出来,以及能否让卖出策略也根据其股票的行情走势进行自动选择也是我们后续可以深入探讨的一些方向

D02_有先后关系的组合

XH01_黄金眼

黄金眼是一种相对漂亮的均线形态,它是由短期均线连续上穿中长期均线而形成的。其他形态还有例如蚂蚁上树、老鸭头、一阳指等。其实在股票软件的“条件选股公式”中的“形态特征”中已经有很多内置的,这些名称可能有的相同,有的不相同。

这里所讲的黄金眼形态,是以网上比较流行的说法,在某些文章或视频中又被称为黄金三角形。它主要包含3组条件:

  1. 5周期均线上穿10周期均线
  2. 5周期均线继续上穿20周期均线
  3. 10周期均线上穿20周期均线

如果简单的在股票软件中把这个组合条件画出来,那么只需要几句代码

S1:=CROSS(MA(C,5),MA(C,10));
S2:=CROSS(MA(C,5),MA(C,20));
S3:=CROSS(MA(C,10),MA(C,20));

MA5:MA(C,5),LINETHICK2,COLORRED;
MA10:MA(C,10),LINETHICK2;
MA20:MA(C,20);

DRAWICON(S1,MA(C,5)*0.99,7);
DRAWICON(S2,MA(C,5),26);
DRAWICON(S3,MA(C,20),18);

在下图显示出来,左下角的黄色圈内,在MA5上穿MA10时以图标B显示,MA5再次上穿MA20以黄钻显示,最后MA10上穿MA20以3色小球显示,这里就构成了一个近似三角形。

但是,黄金眼的买点并没有指明,如果用MA5上穿MA10做买点,就变成了5-10的双均线策略,这就与黄金眼的初衷相背了。即使使用了MA5上穿MA10,它会在时间上非常的提前,但行情走势上也很可能是反抽一下然后继续下跌的,那么5-10金叉买入就会失败;如果继续上涨或当天涨幅就比较大就会形成5-20的金叉,但这里依然不是买点;最后MA10上穿MA20,这种情况下,MA20基本上平的或者向上运行,趋势就会变得明朗起来。

在这个指标里,相当于对第一个指标(5-10金叉)产生了2次的确认,因此会过滤掉MA5刚上穿就又掉下去这样的情况,减少出手次数来提高成功率。那么它跟直接使用MA10和MA20的金叉买入区别在哪里?

在黄金眼指标介绍里,有一种说法是形成黄金眼之后,股价后来回踩均线时将会是比较好的低吸位置。这个从上图可以得到证明,也就是黄金眼成立后,第5根K线是阴线下跌几乎回踩到MA20均线,如果在这里收盘价买入,的确后续是一波上涨。但是呢,很多时候连回踩的机会都没有,股价就直接拉起来了,所以等回踩这个条件又会让你踏空率增加。

从上面这些情况综合分析下来,黄金眼是一种形态,它是由三次均线金叉围成的,事后讲起来都是成功的,但实际上并没有确定的连续的逻辑,在第一个金叉就买入变成了5-10金叉,在第三个金叉再买就变成了10-20金叉,三个金叉形成了还要等回踩往往容易踏空,很多时候更多的是依靠盘感来操作,而且没有卖出的逻辑,它并不是一个明确的量化策略。

不论黄金眼是否是一个好的量化策略,我们在这里要学习和实践的是有先后关系的组合。在这里可以使用周期计数的方式来得到它们之间的先后关系。

N1:=BARSLAST(S1);
N2:=BARSLAST(S2);
N3:=BARSLAST(S3);

S4:= ((N1>=N2 AND N2>=N3) AND S3);

DRAWTEXT(S4,C,'-黄金眼-');

由上图可知,在10上穿20的时候,收盘价位置写上黄金眼,有时候股价已经很高,这个时候再买入基本上已经没有多少盈利空间了(右边),还有些时候虽然10上穿了20,但行情马上转头向下了,这个时候反而买在了阶段的最高点(左边圈),从这些图形的也能看到即使2次确认也并不一定是好的买点。

XH02_分批买入策略初探

首先,还是用AI助手去了解一下四买四卖理论:

四买四卖理论,又称为均线八大法则,是由美国投资大师格兰威尔提出的。这一理论利用股价与均线的关系来确定买卖依据,包含四个买点和四个卖点。以下是四买四卖的大概描述:

买点(Buy Signals):

  1. 一买:慢线(长期均线)从下降逐渐走平转为上升,而快线(短期均线)从慢线的下方突破慢线时,视为买入信号。
  2. 二买:快线下跌未破慢线,并重现升势,此时慢线继续上升,视为买入信号。
  3. 三买:快线虽跌破上升的慢线,但不久又调头向上,并运行于慢线的上方,视为买入信号。
  4. 四买:快线跌破慢线,并远离慢线时,很有可能产生一轮强劲反弹,视为买入信号,但需注意反弹后可能会继续下挫,因此不可长期持有。

卖点(Sell Signals):

  1. 一卖:慢线走势从上升逐渐走平转为下跌,而快线从慢线的上方向下跌破慢线时,视为卖出信号。
  2. 二卖:快线跌落于慢线之下,然后向慢线弹升,但未突破慢线即受阻回落,视为卖出信号。
  3. 三卖:快线虽然反弹突破慢线,但不久又跌到慢线之下,而此时慢线仍在下跌,视为卖出信号。
  4. 四卖:快线急速上涨远离上升的慢线时,投资风险激增,随时可能会出现回跌,视为卖出信号。

这些买卖点提供了市场趋势的参考,帮助投资者在不同的市场条件下做出决策。需要注意的是,这些法则并非绝对,实际应用时应结合其他分析工具和市场情况综合判断。

由这些理论我们得到的结论是实际上的交易并不需要按照backtrader初级回测那样一次买入必须对应一次卖出,可以在不同的阶段进行多次买入并根据实际情况调整进行多次卖出。

而这里就涉及到了分批买入和分仓管理,在没有backtrader回测工具的情况下,我们在股票软件中根据指标出现的信号可以连买,如果没有完善的仓位管理方案,就很容易被套上。

这里一定要重申一下,向下摊低成本的行为是危险的,它常常是彻底淘汰一位股民的罪魁祸首,虽然有些时候这种向下摊低成本做T会赚取到一些超额利润,但在没有完善的交易系统和对应交易策略以及严格止损的情况下,真的不能做!

于是,在有了分批买入的基础上,再来看黄金眼指标,我们则可以把三次金叉和成眼后的回踩分成4份,每出现1个信号买入1份。但同时一定要有对应的卖出策略,而卖出策略包含了止盈和止损,其中的止损最为重要。

在黄金眼指标中,5-10金叉则需要对应死叉卖出,5-20金叉买入的则对应死叉卖出,10-20金叉的同样对应死叉卖出,再次回踩买入的需要在买入价位先计算止损价位(这个止损可以是固定百分比止损,也可以是某个指标比如BOLL下轨或MA30跌破或者上一个低点--唐奇安通道等)止损可以用很多方案来制定,但至少必须要有止损。

上面的买入策略和卖出策略我们已经用文字逻辑描述出来了,但以现在我们在backtrader的实践水平来看,我们还做不了分策略的,更不要说分仓位的管理了,这个不能着急,认真学习和分析,后面几节慢慢解决这些难点。

D03_多指标组合

DSB01_三金叉

这里我们做一个均线5-10金叉,KDJ的KD金叉以及MACD的金叉的组合,但这里的金叉位置可以相差几个周期,也就是继续前面的有先后关系的组合。

同上面的几个组合指标,这些组合指标都只有买入的逻辑,却没有涉及卖出的逻辑,所以还是先在股票软件中把买入的逻辑给实现出来。

// MACD的公式
DIFF = EMA(CLOSE,SHORT) - EMA(CLOSE,LONG);
DEA  = EMA(DIFF,M);
MACD = 2*(DIFF-DEA);

// KDJ的公式
RSV=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100;
K=SMA(RSV,M1,1);
D=SMA(a,M2,1);
J=3*a-2*b;

// 各自金叉画图标
DRAWTEXT(CROSS(MA(C,5),MA(C,10)),80, "510");
DRAWTEXT(CROSS(K,D),20, "KD");
DRAWTEXT(CROSS(DIFF,DEA),50, "MACD");

// 记录金叉位置
N_KD= BARSLAST(CROSS(K,D));
N_MACD= BARSLAST(CROSS(DIFF,DEA));
N_M5 = BARSLAST(CROSS(MA(C,5),MA(C,10)));

// 判断三个金叉相差的周期
XH=70*(
   ABS(N_KD-N_MACD)<=5 AND
   ABS(N_MACD - N_M5)<=5 );
XH2=REF(XH,1);	

DRAWICON(XH!=XH2 AND XH2=0,L,1);

上面的公式中,用到了信号2,XH2=REF(XH,1)这一句代码,使用的原因是三个指标金叉在1或2天内发生后,离5天的区间还会有3~4天,这里就会让信号(XH)这个标志位持续几天都触发,这个是需要规避的。因此使用前一天的XH的值,做出一个上升沿的触发,就只会触发一次了。

由上图可知,三个金叉都在5天内发生,其大多数都取决于周期最长的那个也就是MACD的金叉,而且有一些情况是股价已经涨到几乎最高点了才发出买入信号。

我们在股票软件中采用成功率测试得到了三金叉以及单独MACD,KDJ,5-10金叉的测试值见下图

由图上数据可知,KDJ的指标最灵敏,发生信号达到36万次,5-10金叉较为灵敏发生信号11.7万次,MACD不太灵敏发生信号8.4万次,三者在5个周期内同时发生信号减少到只有6.5万次。这样看来三金叉只是减少了出手次数,但成功率与三者单独金叉差不多。

一方面,我们仍然没有关于三金叉卖出策略的设计,于是不能简单的放到backtrader中进行回测。另一方面,随意的几个常见指标组合并不是一定有好的效果,虽然多指标组合一定会让出手的次数降下来,但这种几乎相同属性的组合并不会增加成功率和增大盈亏比,这些将来我们做出动态止盈策略后再回测一下做个确认。

多指标组合可以自己设置好分批买入的策略,比如这个三金叉就可以在KDJ金叉买入1份,5-10金叉买入第2份,MACD金叉买入第3份。但是正如上面所写的,必须先设置好每个买点对应的卖点,金叉买入的对应死叉卖出,在没有更好更完善的策略之前是必须遵守的规矩。

DSB02_六脉神剑

前段时间某些财经频道或股票软件APP整出了所谓的六脉神剑指标,也有叫乾坤六道的。其本质就是6个指标的组合。它们在这个指标的广告中列出了六个指标,分别是MACD,KDJ,RSI,LWR,BBI和MTM。这六个指标我们在前面都实践过,都是常见指标。

{MACD}
DIF:=EMA(CLOSE,SHORT)-EMA(CLOSE,LONG);
DEA:=EMA(DIF,MID);
MACD:=(DIF-DEA)*2,COLORSTICK;
G1:= DIF>=DEA;

{KDJ}
RSV:=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100;
K:=SMA(RSV,M1,1);
D:=SMA(K,M2,1);
J:=3*K-2*D;
G2:=K>=D;

{RSI}
LC:=REF(CLOSE,1);
RSI1:=SMA(MAX(CLOSE-LC,0),N1,1)/SMA(ABS(CLOSE-LC),N1,1)*100;
RSI2:=SMA(MAX(CLOSE-LC,0),N2,1)/SMA(ABS(CLOSE-LC),N2,1)*100;
G3:=RSI1>=RSI2;

{LWR}
RSV2:= (HHV(HIGH,N)-CLOSE)/(HHV(HIGH,N)-LLV(LOW,N))*100;
LWR1:=SMA(RSV2,M1,1);
LWR2:=SMA(LWR1,M2,1);
G4:=LWR2>=LWR1;

{BBI}
BBI:=(MA(CLOSE,3)+MA(CLOSE,6)+MA(CLOSE,12)+MA(CLOSE,24))/4;
G5:=C>=BBI;

{MTM}
MTM:=CLOSE-REF(CLOSE,MIN(BARSCOUNT(C),N2));
MTMMA:=MA(MTM,N1);
G6:=MTM >=MTMMA;

那么这个6指标的组合指标有没有效果呢?当然是需要回测验证一下的,而且这套指标提供了比较明确的买入点和卖出点,这个在backtrader中也可以实现,它的买入点是6个指标都置位的时候,而卖出点是3个以上的指标都不满足的时候。

首先,根据我们之前的学习,LWR虽然名字是LWR威廉指标,但根据公式计算得到的值与KDJ的RSV恰好是100-RSV的关系,所以这两个指标的图形是镜像的,金叉死叉完全一致(见下图)。所以实质上只有5个指标。

在股票软件的图形观察,当六个指标同时置位时,有时能有持续的上涨行情如最右侧的一段,但有时候股价并不会上涨,还有很多的情况恰好是股价涨到了最高的位置,因为多个灵敏度不同的指标都相继触发了反而很可能是行情要休息一段了。

接着,我们把这个组合指标做到backtrader中来进行回测了。

class SixPulse(bt.Indicator):
    lines = ('sum1',)  # 定义输出线
    params = (
    ('p1',24),('p2',6),)

    def __init__(self):
        macd = bt.indicators.MACD(self.data)
        g1 = bt.If(macd.macd >= macd.signal, 1, 0)
        
        kdj1 = bt.indicators.Stochastic(self.data,period=9)
        g2 = bt.If(kdj1.percK >= kdj1.percD, 1, 0)
        
        rsi1 = bt.indicators.RSI(self.data, period=6)
        rsi2 = bt.indicators.RSI(self.data, period=12)
        g3 = bt.If(rsi1>=rsi2, 1, 0)
        
        b1 = bt.indicators.SMA(self.data, period=3)
        b2 = bt.indicators.SMA(self.data, period=6)
        b3 = bt.indicators.SMA(self.data, period=12)
        b4 = bt.indicators.SMA(self.data, period=24)
        bbi1 = (b1+b2+b3+b4)/4.0
        g4 = bt.If(self.data.close >= bbi1, 1, 0)
        
        mtm1 = bt.indicators.Momentum(self.data)
        mamtm = bt.indicators.SMA(mtm1, period=6)
        g5 = bt.If(mtm1>= mamtm, 1, 0)
        
        g_all = g1 + g2*2.0 + g3 + g4 + g5
        self.lines.sum1 = g_all

        super(SixPulse, self).__init__()

class test_sixpulse(BaseSt):
     params = (
         ('stra_name','六脉神剑1'),
         ('p1',6),  
         ('tradeCnt',1),
         ('sucessCnt',0),)            
               
     def __init__(self): 
         self.order = None
         sum1 = SixPulse(self.data)
         self.crsup = bt.indicators.CrossUp(sum1,5.5)
         self.crsdn = bt.indicators.CrossDown(sum1,3.1)
    

     def next(self):
         if self.order:  # 检查是否有指令等待执行
             return

         if not self.position:  # 没有持仓 才会进入 
             if self.crsup>0:  
                 self.order = self.buy()  # 执行买入
         else:
             if self.crsdn>0:  
                 self.order = self.sell()  # 执行卖出          

其中由于LWR与KDJ本质上完全相同,所以在六指标数量不变的基础上,直接把KDJ的数值乘上了2。这里仍然是把组合指标做成自定义指标SixPulse,在策略类中只是简单实例化一个SixPulse然后用上穿5.5为买入,下穿3.1为卖出。在某支股票上回测的数值如下:

根据回测的结果,可以看到某些买入和卖出点看起来很棒,例如 中间几个红勾(成功)的交易,但是在后半段的上升过程中,出现了连续7个失败的交易 ,单从这一个回测而言,多指标组合未必就会产生更好的收益。

接着对多支自选股进行了回测统计,从下表的数据上看,对于部分股票多指标组合会让交易变得更稳健一些,我们看到使用六脉神剑的往往没有太大的亏损,这个得益于要让多个指标触发买点并不容易,明显的下行趋势不会触发买入。这些亏损往往来源于下跌过程中的反抽反弹,多指标条件都满足时一段反弹的走势基本上已经结束并继续下跌。

另外,多指标组合容易卖飞,从国芳、海信、小商品这几个看,多指标组合的收益要比KAMA的收益少10%以上,这或许跟选择的指标都是短期的灵敏性比较高的(KDJ,LWR,MTM,RSI)而中周期的仅有MACD和BBI两个有关系,并且跟卖出的触发条件是三个指标不满足有关,把卖出的条件放宽的4个指标不满足某些股票就可能会有较好的收益,比如国芳可以提高到33.13%,小商品到9%,但有的反而更低了比如海信降低到了10.85%。

小结

经过本小结的学习和实践,我们已经会使用股票软件的逻辑函数制作组合指标了,但我们也发现很多的组合指标只是买入点,而对于卖出点几乎没有定义。在卖出策略不确定的情况下我们还不能在backtrader中进行回测,但我们已经开始考虑多种卖出策略的问题,并且也可以通过backtrader内置的逻辑函数进行自定义组合指标的制作。

有一些组合指标可能涉及到分批买入的问题,从这里我们也开始探讨分批买入以及分仓操作在backtrader的用法,这些都会在后面的章节中进行。

通过学习和实践,我们破除了某些组合指标是神指标的迷信,可以看到,不是任意的指标都是可以组合起来使用的,组合指标一定要考虑到各自的灵敏度,简单的多个指标叠加由于增加了买入条件,相对而言会使得买入点机会减少,更加稳健,但多个指标叠加也会把各自的问题也带过来,它的收益很可能低于单指标策略。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值