当前位置: 首页 > news >正文

量化交易backtrader实践(五)_策略综合篇(1)_股票软件指标回测

在第三章6到9节,我们学习和实践了大部分股票软件指标,且这些指标是backtrader内置指标实践中没有讲到过的。然后,在进行策略综合之前,我们先热个身,把一些可能比较有参考意义的股票软件内置指标在backtrader里给实现了。同时也开始考虑每个指标的特点,以及应该使用什么样的综合策略。

目前backtrader只接收开、高、低、收以及成交量这五个数据,因此一些跟涨跌家数相关的大势型指标,一些与流通股本相关的参数等都无法在backtrader中简单的实现,那些我们就先忽略了。

01_超买超卖型

CC_01_MFI指标与CJ03_VRSI指标

MFI指标

MFI指标是基于RSI指标在成交量上的应用,所以是否可以直接继承RSI的指标,并在类中添加成交量的计算?这个我们还必须进到RSI的源码中去查看。

class RelativeStrengthIndex(Indicator):alias = ('RSI', 'RSI_SMMA', 'RSI_Wilder',)lines = ('rsi',)params = (('period', 14),('movav', MovAv.Smoothed),('safediv', False),)def __init__(self):upday = UpDay(self.data, period=1)downday = DownDay(self.data, period=1)maup = self.p.movav(upday, period=self.p.period)madown = self.p.movav(downday, period=self.p.period)if not self.p.safediv:rs = maup / madownself.lines.rsi = 100.0 - 100.0 / (1.0 + rs)class UpDay(Indicator):lines = ('upday',)params = (('period', 1),)def __init__(self):self.lines.upday = Max(self.data - self.data(-self.p.period), 0.0)class DownDay(Indicator):lines = ('downday',)params = (('period', 1),)def __init__(self):self.lines.downday = Max(self.data(-self.p.period) - self.data, 0.0)

根据源码,首先计算UpDay和DownDay是判断收盘价与昨收价,若今收高于昨收(上涨)则把差值记录到upday中,否则把下跌的差值记录到downday中。这里出现了一个问题,就是默认写死了为self.data,也就是默认是收盘价,所以我们不能直接把upday和downday用在TYP的值计算里,也就不能直接继承它来计算MFI。

这里说明一下,我们从AI里获取的MFI的指标在backtrader中代码可能是有错误的,这时在next中打印MFI的值会出现全是NaN的情况,遇到这样的问题需要自己想办法分析和寻找方法解决。

class MFI2(Indicator):lines = ('mfi2', )  # 定义一个输出线,命名为'mfi'params = (('period',14),)def __init__(self):self.tp = (self.data.high + self.data.low + self.data.close) / 3.0 # 计算典型价格self.rmf = self.tp * self.data.volume    # 计算资金流量(Raw Money Flow)upday = bt.And(Max(self.tp - self.tp(-1),0),1)  # 正向因子dnday = bt.And(Max(self.tp(-1)-self.tp,0),1)    # 负向因子# 由于这里不需要C-REF(C,1)的差值,只需要记录1,0即可# 这里使用bt.And()函数将最大值与上1,即如果最大值不为0,就会输出1self.pmf = self.rmf*upday   # 计算正向和负向资金流量self.nmf = self.rmf*dndayposmfi = bt.indicators.SumN(self.pmf,period=14) #使用indicators.SumN()进行累加negmfi = bt.indicators.SumN(self.nmf,period=self.p.period) self.mfr = posmfi / negmfi   # 计算资金流动比率(Money Flow Ratio)self.lines.mfi2 = 100 -100 / (1 + self.mfr) # 计算MFI值

这里我们用到两个函数来解决过程中的2个问题,第1个问题是RSI要计算正向差值和负向差值,而MFI只需要计算是正向还是负向,然后乘上VOL * TYP的值,因此用了bt.And()函数,将正向的都放在upday中作为正向因子来解决它,当然我们也可以用bt.If()函数来进行。第2个问题是股票软件公式用的SUM(C,N)的函数,其实在backtrader中的indicators\basicops.py中有SumN的函数完全对应的。期间AI助手给出的例如cumcum()是无法正常使用的。

将MFI2的自定义指标放到最简单的策略类中进行构建和运行绘图,由于还没有添加买卖策略,只有主图和副图绘制显示,这里我们还添加了RSI的曲线与MFI进行比较,当然这里是为了确认我们的自定义指标输出的数量级基本是正确的,没有发生过程中的错误。

我们看到MFI与RSI的走势会比较相似,这一点在第6节实践股票软件中的MFI指标时已经确认过:

  • 量化交易backtrader实践(三)_指标与策略篇(6)_股票软件指标参考A

VRSI指标

在解决了MFI的指标问题后,我们再来看一下VRSI指标,从指标公式上看,VRSI才是严格的成交量在RSI指标上的应用,它与RSI的不同,仅仅是从C-REF(C,1)变成了VOL-REF(VOL,1)。

但是,由于这个改变是在RSI指标过程中的改变,而并非输入或输出的再加工,所以我们仍然不能直接继承RSI指标来使用,仍然需要自定义指标

class VRSI_test(Indicator):lines = ('vrsi',)  # 定义一个输出线,命名为'vrsi'params = (('period',6),)plotinfo = dict(plotymargin=0.05, plotyhlines=[0, 100])def __init__(self):Vupday = Max(self.data.volume - self.data.volume(-1),0.0)Vdnday = Max(self.data.volume(-1) - self.data.volume,0.0)#Vmaup = bt.indicators.SMA(Vupday, period=self.p.period)Vmadn = bt.indicators.SMA(Vdnday, period=self.p.period)#rs = Vmaup/Vmadnself.lines.vrsi = 100.0-100.0/(1.0+rs)super(VRSI_test, self).__init__()

不过在自定义指标时,可以大部分借鉴RSI的代码,于是我们只需要把C-REF(C,1)改为V-REF(V,1)即可。从代码上可以很清楚的了解到VRSI这个指标只跟成交量的变化有关,量增为正,量减为负,周期内的量增平均值/量减平均值即量的相对强弱指标,数值越低表示缩量连续且缩量差值越大,数值越高则表示放量连续且放量数值越大。

再回过头来看MFI,MFI是TYP的值乘上VOL的值,它相当于典型股价的成交额,它即有了量的因素,又乘上了价的因素,属于量价合一的指标。而VRSI只有量的因素,RSI只有价的因素。不过反而单纯的RSI与VRSI才能组成一组比较严格的量价关系指标组合。

CC_02_BIAS指标

Backtrader中并没有内置的BIAS指标。BIAS指标,即乖离率指标,是一个超买超卖指标,其含义是收盘价与某一周期均线的乖离率,算法很简单:(close-ma)/ma。如果需要在Backtrader中使用BIAS指标,需要自定义实现。

class myBIAS(Indicator):lines = ('bias','bima')  # 定义输出线params = (('p1',20),('p2',6))plotinfo = dict(plotymargin=0.05, )def __init__(self):ma1 = bt.indicators.SMA(self.data.close, period=self.p.p1)bias = (self.data.close - ma1)/ma1 * 100.0self.lines.bias = biasself.lines.bima = bt.indicators.SMA(bias, period = self.p.p2)super(myBIAS, self).__init__()

02_均线型与成交量型

JX02_ACD升降线指标

在第三章第7节中讨论过ACD升降线指标公式,ACD即Accumulation Distribution Line,所谓的累积分布线。这个公式的特点是根据当前收盘价是否大于昨收(即当天上涨还是下跌)来选择用TrueHigh(Max(HIGH, REF(C,1)))还是用TrueLow(Min(LOW,REF(C,1))),从实际的情况下看,上涨取最低值,下跌取最高值。然后用收盘价CLOSE去减,就得到所谓的多空力量或买卖盘力量。

M:=20;
LC:=REF(CLOSE,1);
DIF:=CLOSE-IF(CLOSE>LC,MIN(LOW,LC),MAX(HIGH,LC));
ACD:SUM(IF(CLOSE=LC,0,DIF),0);
MAACD:EXPMEMA(ACD,M);

前面也讨论过,由于ACD的数值没有做归一化,它在不同股价时取值范围是不同的,所以单是ACD没有定量的策略,仅仅可以支持双均线的金叉/死叉策略。不过粗略地看ACD的稳健性与KAMA差不多,所以这里我们就把ACD的指标做到backtrader中来进行回测检验一下。

from backtrader.indicators import Min, Max
class myACD(Indicator):lines = ('acd','maacd')  # 定义输出线params = (('p1',20),)plotinfo = dict(plotymargin=0.05,)# plotyhlines=[-30, 30])def __init__(self):lc=self.data.close(-1)vmin = Min(self.data.low, lc)vmax = Max(self.data.high, lc)upday = Max(self.data.close - vmin, 0.0)dnday = Min(self.data.close - vmax, 0.0)cd = upday + dndayself.lines.acd = bt.indicators.CumulativeSum(cd)self.lines.maacd = bt.indicators.EMA(self.lines.acd, period=self.p.p1)super(myACD, self).__init__()

这里有一个问题要注意一下,单独使用Max()好像不会报错,但只要使用Min()的时候就会报错

NameError: name 'Min' is not defined

由于Max和Min都是backtrader的内置函数,需要从bt.indicators模块中导入

另外,__init__中的每一次赋值都是相当于给整列数据赋值,所以可以利用这一点,分别给正值项做一列、负值项做一列,最后两列相加即可。

从backtrader的ACD图线与股票软件的进行比较,大致的曲线是近似的,但取值范围稍微有些不一样,暂时不知道不完全相同的原因在哪,但并不影响我们的进度。

在这里,添加简单的交叉策略进行回测,结果与我们之前的预估差不多,大部分的股票ACD交叉策略的确与KAMA类似,但也有少数差别很多的,例如西部、蓝色等。

如果仔细的进入单支股票的回测进行观察,就不难发现,有些股票在震荡段时ACD与MAACD之间一直是纠缠在一起,两者并没有出现明显的分离情况,那么在这一段里并没有进入交易的必要(椭圆圈内),只有当ACD与MAACD有了明显的分离时,才需要进行交易(见右侧3个黄箭头)。

但是对于原生的ACD而言,是没有办法对不同股价的票进行区分的,它在股票软件里图线显示是人进行观察而得出的结论,人为根据经验觉得某一段ACD两线没有分开则可以不交易。

所以,要正常的使用这个指标,就需要再进一步对原始指标进行一些更改,比如归一化使其能用于各个股票,再比如计算两条线的分离程度,当大于某一值的时候才满足买入条件等。到这里我还是懒惰了,只想赶紧进行下一条,这些进阶的内容就先搁置在这里,什么时候有兴趣了再折腾吧。

JX08_BBIBOLL指标

在第三章第7节的JX03中,我们讨论了BBI多空均线指标,当时我们查到的资料是BBI=Bull and Bear Index,如果以这样的名字命名的话,按理这就是我们国家的硬翻译了。但后来在BBIBOLL的介绍中,又发现了一种解释BBI = Breakout Bands Indicator,中文叫“突破带指标”。到底哪一个是对的呢?不过争论名称并没有什么意义,我们需要知道它怎么用才行。

在前面的章节里,我们研究过,BBI的指标的计算逻辑与UDL引力线指标是一模一样的,只是4个参数周期的取值不同而已。并且我们发现UDL可以近似的使用EMA9来替代,但BBI与EMA11仍有小部分的差距在里面。典型的BBI用法是收盘价站上BBI买入,下破BBI卖出,并且BBI本身有支撑和阻力的作用(触及不破反向),这样的策略也可以放在UDL引力线上应用,也就相当于直接可以用EMA9来做单均线策略,这些都是几个指标之间的替代和近似关系,暂时就讨论这么多,还是回到BBIBOLL的应用上来。

BBIBOLL多空布林线指标是一种结合了多空线(BBI)和布林线(BOLL)的技术分析工具,它用BBI做了中轨,这就与标准BOLL线的中轨使用简单移动平均线MA会有一些差别。

根据上图,主图为BBIBOLL的指标,副图1是标准BOLL指标,副图2是计算了两者的极限带宽度的曲线。可以看到,首先中轨BBI会比MA要更贴近于K线的运动,它不会明显的远离K线。其次,求标准差的时候,BOLL的标准差是STD(C,20)即求20周期内收盘价的标准差,而BBIBOLL的标准差为STD(BBIBOLL,11),为什么使用11,这个是不是跟我们前面拟合的BBI大约是EMA11有关也不能确定,但似乎还真有那么一点关系;所以BBIBOLL的周期11比BOLL的周期20要短,它的上下轨的变化就更明显。然后,标准布林是中轨加减2倍的标准差,BBIBOLL是中轨加减6倍的标准差,这也就决定了BBIBOLL的上下轨的幅度要选大于标准BOLL带。这个也可以在副图2的两者极限宽度看出来,桃红的BBIBOLL宽度大部分都在标准BOLL带宽度之上。从这一点来说,BBIBOLL的上下轨并不适合用来做买卖点,反而是上下轨的距离(带宽度)是用来做辅助判断的。

对于BBIBOLL指标,中轨是BBI,它是不会变的,可以更改的2个参数都是对于上下轨的幅度和宽度的调节,通过调节参数我们发现,当默认11的参数减少,则STD(BBI,N)的标准差样本数减少,上下轨的变化速度更快了。而要让STD(BBI,N)的值变小,就是其标准差(与BBI的偏差)变小,就意味着BBI本身是斜率变缓或者走平。此时我们再来理解一下这几句引文

高价区收盘价跌破BBI线,并且上下轨相距非常远时,为卖出信号。
低价区收盘价突破BBI线,并且上下轨相距非常近时,为买入信号。

轨道收敛:说明行情即将变盘,向上或向下突破。
轨道发散:表明将向上或向下扩大趋势。

上下轨相距远,则代表BBI斜率大,也就是这段时间股价单边幅度大,于是跌破BBI代表当前为下跌趋势,是卖出止损的最后机会;轨道收敛,则代表BBI斜率变小或走平,代表股价进入一个阻力区,那么突破BBI向上则相当于突破阻力区开启一波行情,可以认为是买点。

可以尝试把BBIBOLL的N周期由11减小(比如6),并综合考虑BOLL的策略进行综合,例如BOLL可以在下轨买入,但如果发现BOLL的WID以及WIDBBI都在增大时,代表下跌行情没有完成,则不能买入;需要等到WID低于0.15并且WIDBBI拐头下跌时,BOLL下轨才可以买入。又例如经典的布林策略可以添加突破中轨的策略,把它跟收盘站上BBI结合起来,作为一个分支策略的买点。但要注意一个问题,BBIBOLL收口即WIDBBI非常小的时候,站上BBI上涨的可能性比较大,但也会遇到站下BBI只是一个陷阱,之后股价疯狂下跌的情况。

关于BBIBOLL+BOLL的策略研究后续再重点讨论,这里先研究到这里,我们先把这个指标在backtrader中实现了。BBIBOLL是主图指标,需要加上subplot=False的。

class myBBIBOLL(Indicator):lines = ('bbi','upr','dwn')  # 定义输出线params = (('p1',11),('p2',6))plotinfo = dict(plotymargin=0.05, )plotinfo = dict(subplot=False)   def __init__(self):cv = self.data.closema1 = bt.indicators.SMA(cv,period=3)ma2 = bt.indicators.SMA(cv,period=6)ma3 = bt.indicators.SMA(cv,period=12)ma4 = bt.indicators.SMA(cv,period=24)bbi = (ma1+ma2+ma3+ma4)/4.0std1 = bt.indicators.StdDev(bbi,period = self.p.p1)mstd1 = self.p.p2 * std1self.l.upr = bbi+mstd1self.l.dwn = bbi-mstd1self.l.bbi = bbisuper(myBBIBOLL, self).__init__()

另外,我们再制作一个BBIBOLL线宽度的指标,由于这个指标是放副图的,还需要把上面的代码复制一下,但把plotinfo = dict(subplot=True)   写出来。完成后在策略中同时加载BBIBOLL和BBIBOLLWID两个指标,就可以分别在主图和副图上显示了。

CJ02_OBV能量潮指标

能量潮OBV是典型的成交量指标,它只与成交量相关,当上涨时取成交量正值,下跌时取成交量负值,然后进行累加。这是最简洁但又非常暴力的分析指标。

M:=30;
VA:=IF(CLOSE>REF(CLOSE,1),VOL,-VOL);
OBV:SUM(IF(CLOSE=REF(CLOSE,1),0,VA),0);
MAOBV:MA(OBV,M);

在backtrader中没有内置的OBV指标,前面我们在review内置指标时的确也很少看到与成交量相关的指标,这里需要把指标公式移植过来。这里我们使用bt.If()函数来得到成交量正,负的line的值。

class myOBV(Indicator):lines = ('obv','maobv',)  # 定义输出线params = (('p1',30),)plotinfo = dict(plotymargin=0.05, )def __init__(self):cv = self.data.close - self.data.close(-1)va = bt.If(cv>0, self.data.volume, -1*self.data.volume)obv = bt.indicators.CumulativeSum(va)maobv = bt.indicators.SMA(obv,period=self.p.p1)self.lines.obv = obvself.lines.maobv = maobvsuper(myOBV, self).__init__()

以上,就把OBV的指标在backtrader中实现了。

03_趋势型指标

趋势型指标中有几个是与成交量相关的,这些指标再叠加上多空力量差值或比值来显示上涨的力量或趋势。

QS02_CHO佳庆指标

在OBV中,以今收>昨收为判断条件,只要是上涨的成交量取正值(多头动能),只要是下跌的成交量取负值(空头动能)。

对于佳庆指标,则使用收盘价减最低价表示多方力量而使用最高价减收盘价表示空方力量。

N1:=10;
N2:=20;
M:=6;MID:=SUM(VOL*(2*CLOSE-HIGH-LOW)/(HIGH+LOW),0);
CHO:MA(MID,N1)-MA(MID,N2);
MACHO:MA(CHO,M);

移植到backtrader中的指标为

class myCHO(Indicator):lines = ('cho','macho',)  # 定义输出线params = (('p1',10),('p2',20),('p3',6),)def __init__(self):power1= 2*self.data.close - self.data.high - self.data.lowvpower = self.data.volume * power1 / (self.data.high + self.data.low)mid = bt.indicators.CumulativeSum(vpower)ma1 = bt.indicators.SMA(mid, period=self.p.p1)ma2 = bt.indicators.SMA(mid, period=self.p.p2)cho = ma1 - ma2macho= bt.indicators.SMA(cho, period=self.p.p3)self.lines.cho = choself.lines.macho = machosuper(myCHO, self).__init__()

QS05_EMV简易波动指标

EMV也是将价格和成交量的变化结合而成的指标,这里的成交量会使用平均值除以成交量,而价格的趋势采用的(H+L)/2的平均价格减去上一个周期的平均价格,然后除以平均价格得到了百分比,所以EMV对于所有的股票其数量级都是一致的,这一点比OBV以及CHO都要通用性强一些。

N:=14;
M:=9;VOLUME:=MA(VOL,N)/VOL;
MID:=100*(HIGH+LOW-REF(HIGH+LOW,1))/(HIGH+LOW);
EMV:MA(MID*VOLUME*(HIGH-LOW)/MA(HIGH-LOW,N),N);
MAEMV:MA(EMV,M);

这里我们就直接在backtrader中实现这个指标

class myEMV(Indicator):lines = ('emv','maemv',)  # 定义输出线params = (('p1',14),('p2',9),)def __init__(self):vol1 = bt.indicators.SMA(self.data.volume,period=self.p.p1)/self.data.volumemid1 = self.data.high+self.data.lowmid = 100* (mid1 - mid1(-1))/ mid1ma2 = bt.indicators.SMA(self.data.high-self.data.low, period=self.p.p1)emv1 = bt.indicators.SMA(mid*vol1*(self.data.high-self.data.low)/ma2, period=self.p.p1)maemv = bt.indicators.SMA(emv1, period=self.p.p2)self.lines.emv = emv1self.lines.maemv = maemvsuper(myEMV, self).__init__()class EMV_test_1(BaseSt):params = (('stra_name','EMV_test_1'),('p1',14),  ('tradeCnt',1),('sucessCnt',0),)            def __init__(self): self.order = Noneemv = myEMV(self.data)self.crs = bt.indicators.CrossOver(emv.l.emv, emv.l.maemv)def next(self):if self.order:  # 检查是否有指令等待执行returnif not self.position:  # 没有持仓 才会进入 if self.crs>0:  self.order = self.buy()  # 执行买入else:if self.crs<0:  self.order = self.sell()  # 执行卖出          run_main_plot_ex2 (df_list,EMV_test_1,0)----------------------
策略为 EMV_test_1 , 期末总资金 105796.95  盈利为 5796.95 总共交易次数为 36 ,交易成功率为 36.1%

QS07_VPT量价曲线指标

跟上面的CHO,EMV差不多,VPT也是基于量和价关系的技术分析指标,价格的关系也很简单,就是日涨跌幅,涨为正跌为负,然后乘上成交量,并做N周期的累加,这个其实比前面两个更简单,因为CHO是计算的多方力量的差值,而EMV计算的是平均价格的涨跌。

N:=51;
M:=6;VPT:SUM(VOL*(CLOSE-REF(CLOSE,1))/REF(CLOSE,1),N);
MAVPT:MA(VPT,M);

这里就直接在backtrader中把它实现。

class myVPT(Indicator):lines = ('vpt','mavpt',)  # 定义输出线params = (('p1',51),('p2',6),)def __init__(self):cpct = (self.data.close - self.data.close(-1))/self.data.close(-1)power1 = cpct*self.data.volumevpt = bt.indicators.SumN(power1, period=self.p.p1)mavpt = bt.indicators.SMA(vpt, period=self.p.p2)self.lines.vpt = vptself.lines.mavpt = mavptsuper(myVPT, self).__init__()class VPT_test_1(BaseSt):略run_main_plot_ex2 (df_list,VPT_test_1,0)----------------------------
策略为 VPT_test_1 , 期末总资金 98249.04  盈利为 -1750.96 总共交易次数为 47 ,交易成功率为 34.0%

QS08_WVAD威廉变异离散量指标

WVAD也是计算了成交量与价格两个部分,在价格方面使用的是收盘价减开盘价除以当天的振幅的计算方式,对应的是阳线为正,阴线为负,再乘上成交量就会将成交量变为有正有负的数值,这种思路跟上面的VPT是类似的,只是用到的价格计算的因子不一样。

N:=24;
M:=6;WVAD:SUM((CLOSE-OPEN)/(HIGH-LOW)*VOL,N)/10000;
MAWVAD:MA(WVAD,M);

仍然是直接在backtrader中把它实现出来。

class myWVAD(Indicator):lines = ('wvad','mawvad',)  # 定义输出线params = (('p1',24),('p2',6),)def __init__(self):cpct = (self.data.close - self.data.open)/(self.data.high-self.data.low)power1 = cpct*self.data.volumewvad = bt.indicators.SumN(power1, period=self.p.p1)/10000.0mawvad = bt.indicators.SMA(wvad, period=self.p.p2)self.lines.wvad = wvadself.lines.mawvad = mawvadsuper(myWVAD, self).__init__()class WVAD_test_1(BaseSt):params = (('stra_name','WVAD_test_1'),('p1',24),  ('tradeCnt',1),('sucessCnt',0),)            def __init__(self): self.order = Nonewvad = myWVAD(self.data)self.crs = bt.indicators.CrossOver(wvad.l.wvad, wvad.l.mawvad)def next(self):if self.order:  # 检查是否有指令等待执行returnif not self.position:  # 没有持仓 才会进入 if self.crs>0:  self.order = self.buy()  # 执行买入else:if self.crs<0:  self.order = self.sell()  # 执行卖出          run_main_plot_ex2 (df_list,WVAD_test_1,0)----------------------------
策略为 WVAD_test_1 , 期末总资金 106770.76  盈利为 6770.76 总共交易次数为 53 ,交易成功率为 45.3%

04_小结

把股票软件的指标移植到backtrader中来,一般采用2种方式。第一种会很简单,是直接在backtrader内置指标的基础上进行的小更改,那么我们可以直接继承这个指标的类,然后再进行简单的计算就可以了。第二种就是通过自定义指标类的方式进行,其实上面的几个指标都是采用这种方式进行的。

在自定义指标类中,对于指标的计算的逻辑实现也非常的自由,一般而言直接可以在__init__()中就把指标创建好,如果的确有困难也可以在next中来逐项实现。在__init__()中,每一个参与计算的都是一列(line)数据,相当于pandas表中的列。

在股票软件中一些常见的函数,其实在backtrader中也几乎都有对应的函数,

股票软件backtrader
IF( condition, s1, s2)

bt.IF(condition, S1,S2)

bt.And(Max(C,0),1)

SUM(C, N)       bt.indicators.SumN(self.data, period=N)
SUM(C, 0) 从头开始累加bt.indicators.CumulativeSum(self.data)
MA(C,5)        bt.indicators.SMA(self.data,period=5) 

只要我们清楚了这些函数,就会发现把股票软件中已经存在的指标公式移植过来并不是一件困难的事。

不过,backtrader默认接收的数据项只有开、高、低、收和成交量,而前面我们基本上也只从akshare或tushare.pro中获取这几个数据,其他的数据项被忽略的。但无论如何,股票软件本身可以获取的数据项是非常多的,比较WINNER函数获取某价格的获利比例等,另外比较典型的是涨跌家数比等,如果我们想在backtrader中使用这些数据,那就需要特殊的操作了,这个在后面的章节里再详细讨论。

经过到目前为止的这些实践,我们已经了解了许多backtrader内置的指标,股票软件内置的指标以及能够把一些股票软件内置的指标移植到backtrader中来进行回测,并且相应的根据backtrader的交易系统又在股票软件的指标上添加了更高级的功能,比如计算某个策略的收益率,比如对于连续的多个买点和卖点给予屏蔽等。在当前的基础上,我们对指标的认识有了较大的提高,接下来我们就尝试着进行复杂、综合策略的实践了。

相关文章:

量化交易backtrader实践(五)_策略综合篇(1)_股票软件指标回测

在第三章6到9节&#xff0c;我们学习和实践了大部分股票软件指标&#xff0c;且这些指标是backtrader内置指标实践中没有讲到过的。然后&#xff0c;在进行策略综合之前&#xff0c;我们先热个身&#xff0c;把一些可能比较有参考意义的股票软件内置指标在backtrader里给实现了…...

4.STM32通信接口之SPI通信(含源码)---软件SPI与W25Q64存储模块通信实战《精讲》

经过研究SPI协议和W25Q64&#xff0c;逐步了解了SPI的通信过程&#xff0c;接下来&#xff0c;就要进行战场实战了&#xff01;跟进Whappy步伐&#xff01; 目标&#xff1a;主要实现基于软件的SPI的STM32对W25Q64存储写入和读取操作&#xff01; 开胃介绍&#xff08;代码基本…...

MINDAGENT:游戏交互中的新兴性设计

一、摘要 1.问题/研究背景 LLM具有在多智能体系统中执行复杂调度的能力&#xff0c;并可以协调这些代理以完成需要广泛合作的复杂任务。 但是&#xff0c;目前还没有一个标准的游戏场景和相关的测试指标来评估 LLM 在游戏中的表现以及与人类玩家的合作能力。 2.研究目标/动…...

【工具变量】上市公司企业所在地城市等级直辖市、副省级城市、省会城市 计划单列市(2005-2022年)

一、包含指标&#xff1a; 股票代码 股票代码 股票简称 年份 所属城市 直辖市&#xff1a;企业所在地是否属于直辖市。1是&#xff0c;0否。 副省级城市&#xff1a;企业所在地是否属于副省级城市。1是&#xff0c;0否。 省会城市&a…...

C# 动态类型 Dynamic

文章目录 前言1. 什么是 Dynamic&#xff1f;2. 声明 Dynamic 变量3. Dynamic 的运行时类型检查4. 动态类型与反射的对比5. 使用 Dynamic 进行动态方法调用6. Dynamic 与 原生类型的兼容性7. 动态与 LINQ 的结合8. 结合 DLR 特性9. 动态类型的性能考虑10. 何时使用 Dynamic&…...

Css动画:旋转相册动画效果实现

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;Css篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来Css篇专栏内容:Css动画:旋转相册动画效果实现 前言 随着Web技术的发展&#xff0c;网页不再局限于静态展示&#…...

Unity 基于Collider 组件在3D 物体表面放置3D 物体

实现 从鼠标点击的屏幕位置发送射线&#xff0c;以射线监测点击到的物体&#xff0c;根据点击物体的法线向量调整放置物体的位置及朝向。 Ray ray Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(ray, out RaycastHit hit, 100)) {obj.transform.…...

Hbase整合Mapreduce案例1 hdfs数据上传至hbase中——wordcount

目录 整合结构准备java API 编写pom.xmlMain.javaMap.javaReduce 运行 整合结构 准备 上传hdfs data.txt数据 data.txt I am wunaiieq QAQ 123456 Who I am In todays interconnected world the role of technology cannot be overstated It has revolutionized the way we …...

PyQt 中的无限循环后台任务

在 PyQt 中实现一个后台无限循环任务&#xff0c;需要确保不会阻塞主线程&#xff0c;否则会导致 GUI 无响应。常用的方法是利用 线程&#xff08;QThread&#xff09; 或 任务&#xff08;QRunnable 和 QThreadPool&#xff09; 来运行后台任务。以下是一些实现方式和关键点&a…...

5G CPE核心器件-基带处理器(三)

5G CPE 核心器件 -5G基带芯片 基带芯片简介基带芯片组成与结构技术特点与发展趋势5G基带芯片是5G CPE中最核心的组件,负责接入5G网络,并进行上下行数据业务传输。移动通信从1G发展到5G,终端形态产生了极大的变化,在集成度、功耗、性能等方面都取得巨大的提升。 基带芯片简…...

鸿蒙next版开发:拍照实现方案(ArkTS)

文章目录 拍照功能开发步骤1. 导入相关接口2. 创建会话3. 配置会话4. 触发拍照5. 监听拍照输出流状态 结语 在HarmonyOS 5.0中&#xff0c;ArkTS提供了一套完整的API来管理相机功能&#xff0c;特别是拍照功能。本文将详细介绍如何在ArkTS中实现拍照功能&#xff0c;并提供代码…...

C++面试突破---C/C++基础

1.C特点 1. C在C语言基础上引入了面对对象的机制&#xff0c;同时也兼容C语言。 2. C有三大特性&#xff08;1&#xff09;封装。&#xff08;2&#xff09;继承。&#xff08;3&#xff09;多态&#xff1b; 3. C语言编写出的程序结构清晰、易于扩充&#xff0c;程序可读性好。…...

项目搭建+修改

一 : 在列表成功回调函数,追加数据中,添加修改的按钮 for (let x of res) {//追加数据$("#table").append(<tr><td><input type"checkbox" class"ck" value"\${x.uid}"></td><td>\${x.uid}</td>…...

每日算法一练:剑指offer——树篇(4)

1.计算二叉树的深度 某公司架构以二叉树形式记录&#xff0c;请返回该公司的层级数。 示例 1&#xff1a; 输入&#xff1a;root [1, 2, 2, 3, null, null, 5, 4, null, null, 4] 输出: 4 解释: 上面示例中的二叉树的最大深度是 4&#xff0c;沿着路径 1 -> 2 -> 3 -&…...

Nginx静态资源配置

基本配置原则 明确资源目录&#xff1a;为不同类型的静态资源指定不同的路径&#xff0c;这样可以避免路径冲突&#xff0c;并且便于管理。正确设置文件权限&#xff1a;确保 Nginx 具有读取静态资源的权限。缓存优化&#xff1a;为静态资源设置缓存头&#xff08;如 expires&…...

困扰解决:mfc140u.dll丢失的解决方法,多种有效解决方法全解析

当电脑提示“mfc140u.dll丢失”时&#xff0c;这可能会导致某些程序无法正常运行&#xff0c;给用户带来不便。不过&#xff0c;有多种方法可以尝试解决这个问题。这篇文章将以“mfc140u.dll丢失的解决方法”为主题&#xff0c;教大家有效解决mfc140u.dll丢失。 判断是否是“mf…...

D3.js 初探

文章目录 D3.js 简单介绍选择集与方法数据绑定方法选择集添加DOM元素以及删除元素理解update enter 以及 exit关于比例尺layout 布局force layout 坐标轴元素添加动态效果demo1: 绘制简单柱状图 #D3.js 初探 最近在做一个Data Visualization 的项目&#xff0c;由于对最终呈现的…...

linux常用指令 | 适合初学者

linux常用指令 1.ls: 列出当前&#xff0c;目录中的文件和子目录 ls 2.pwd: 显示当前工作目录的路径 pwd3.cd切换工作目录 cd /path/to/director4.mkdir:创建新目录 mkdir directory_name5.rmdir:删除空目录 rmdir directory_name6.rm: 删除文件或目录 rm file_name r…...

用 NotePad++ 运行 Java 程序

安装包 网盘链接 下载得到的安装包: 安装步骤 双击安装包开始安装. 安装完成: 配置编码 用 NotePad 写 Java 程序时, 需要设置编码. 在 设置, 首选项, 新建 中进行设置, 可以对每一个新建的文件起作用. 之前写的文件不起作用. 在文件名处右键, 可以快速打开 CMD 窗口, 且路…...

在 Linux 环境下搭建 OpenLab Web 网站并实现 HTTPS 和访问控制

实验要求 综合练习&#xff1a;请给openlab搭建web网站 ​ 网站需求&#xff1a; ​ 1.基于域名[www.openlab.com](http://www.openlab.com)可以访问网站内容为 welcome to openlab!!! ​ 2.给该公司创建三个子界面分别显示学生信息&#xff0c;教学资料和缴费网站&#xff0c…...

微信小程序wx.showShareMenu配置全局分享功能

在app.js文件中配置如下即可&#xff1a; onLaunch() {//开启分享功能this.overShare()},/*** 开启朋友圈分享功能* 监听路由切换/自动执行*/overShare() {wx.onAppRoute((res) > {// console.log(route, res)let pages getCurrentPages()let view pages[pages.length - …...

机器学习面试八股总结

下面是本人在面试中整理的资料和文字&#xff0c;主要针对机器学习面试八股做浅显的总结&#xff0c;大部分来源于ChatGPT&#xff0c;中间有借鉴一些博主的优质文章&#xff0c;已经在各文中指出原文。有任何问题&#xff0c;欢迎随时不吝指正。 文章系列图像使用动漫 《星游…...

南京邮电大学《2024年812自动控制原理真题》 (完整版)

本文内容&#xff0c;全部选自自动化考研联盟的&#xff1a;《南京邮电大学812自控考研资料》的真题篇。后续会持续更新更多学校&#xff0c;更多年份的真题&#xff0c;记得关注哦~ 目录 2024年真题 Part1&#xff1a;2024年完整版真题 2024年真题...

大数据新视界 -- Hive 数据湖集成与数据治理(下)(26 / 30)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…...

Android EventBus最全面试题及参考答案

目录 什么是 EventBus&#xff1f; 请解释 EventBus 是什么&#xff0c;以及它的工作原理。 简述 EventBus 的工作原理。 EventBus 的主要组成部分有哪些&#xff1f; EventBus 是如何实现发布订阅模式的&#xff1f; EventBus 与观察者模式有什么区别&#xff1f; Even…...

C++ 游戏开发:开启游戏世界的编程之旅(1)

在游戏开发领域&#xff0c;C 一直占据着极为重要的地位。它以高效的性能、对底层硬件的良好控制能力以及丰富的库支持&#xff0c;成为众多大型游戏开发项目的首选编程语言。今天&#xff0c;就让我们一同开启 C 游戏开发的探索之旅。 一、C 游戏开发基础 &#xff08;一&am…...

SpringBoot mq快速上手

1.依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId> </dependency> 2.示例代码 基础信息配置 package com.example.demo.config;import org.springframework.amqp.co…...

图像处理网络中的模型水印

论文信息&#xff1a;Jie Zhang、Han Fang、Weiming Zhang、Wenbo Zhou、Hao Cui、Hao Cui、Nenghai Yu&#xff1a;Model Watermarking for Image Processing Networks 本文首次提出了图像处理网络中深度水印问题&#xff0c;将知识产权问题引入图像处理模型 提出了第一个深…...

Halcon 瑕疵检测原理及应用

摘要&#xff1a; 本文详细阐述了 Halcon 在瑕疵检测领域的原理、相关技术以及广泛的应用场景。首先介绍了 Halcon 软件的基本概况及其在机器视觉领域的重要地位&#xff0c;接着深入剖析了瑕疵检测所涉及的图像采集、预处理、特征提取与分析以及分类与判定等核心原理&#xff…...

JAVA 架构师面试 100套含答案:JVM+spring+ 分布式 + 并发编程》...

今年的行情&#xff0c;让招聘面试变得雪上加霜。已经有不少大厂&#xff0c;如腾讯、字节跳动的招聘名额明显减少&#xff0c;面试门槛却一再拔高&#xff0c;如果不用心准备&#xff0c;很可能就被面试官怼得哑口无言&#xff0c;甚至失去了难得的机会。 现如今&#xff0c;…...