量化交易学习(三十三)backtrader文档——指标的使用
今天这篇是backtrader文档的学习笔记。主要介绍了指标的概念。
官方文档链接:https://www.backtrader.com/docu/induse/
使用指标
指标可以在平台的两个地方使用:
- 策略内部
- 其他指标内部
指标的行为
- 指标始终在策略类的__init__中实例化
- 指标值(或其派生值)在next方法中被使用/查看
有一个重要的公理需要注意:
- 任何在__init__期间声明的 Indicator(或其派生类)都将在调用next方法之前预先计算。
init VS next
具体细节如下:
- 在__init__方法中任何涉及线对象的操作都会生成另一个线对象
- 在next方法中任何涉及line对象的操作都会产生常规的 Python 类型,如浮点数和布尔值。
在__init__期间
在__init__期间运算示例:
1 | hilo_diff = self.data.high - self.data.low |
变量hilo_diff保存对线对象的引用,该对象在next调用之前预先计算,并且可以使用标准数组表示法通过[]来访问。
显然,它确实包含数据源的每个bar的最高点和最低点之差。
当混合简单的线对象(如 self.data 数据源中的行)和复杂的线对象(如指标)时也适用:
1 | sma = bt.SimpleMovingAverage(self.data.close) |
现在close_sma_diff也包含了一个线对象。
使用逻辑运算符:
1 | close_over_sma = self .close > sma |
现在生成的线条对象将包含一个布尔数组。
在next期间
运算示例(逻辑运算符):
1 | close_over_sma = self.data.close > self.sma |
使用等效数组(基于索引 0 的表示法):
1 | close_over_sma = self.data.close[0] > self.sma[0] |
在这个例子中,close_over_sma产生一个布尔值,它是两个浮点值比较的结果,该值是由[0]操作符应用于self.data.close和self.sma返回的值
__init__与next方法为什么这样实现
逻辑简化(以及易用性)是关键。计算及大多数相关逻辑可以在__init__期间声明,从而在next中精简实际操作逻辑的代码。
实际上还有一个附带的好处:速度(在开头解释过,可以在使用前预先计算)
一个完整的示例,在以__init__期间生成买入信号:
1 | class MyStrategy(bt.Strategy): |
注意:因为Python 的and运算符无法被覆盖,backtrader定义了自己的And. 这同样适用于其他逻辑运算符,如Or和If
显然,在__init__期间的“声明式”方法可以将next方法(实际策略工作发生的地方)中的代码膨胀保持在最低限度。
注意:当逻辑变得非常复杂并涉及多个运算时,通常最好将其封装在Indicator.
一些笔记
在上面的示例中,与其他平台相比,backtrader把两件事做了简化:
- 声明Indicators既不获取父参数(如创建它们的策略),也不调用任何类型的“注册”方法/函数。
策略将启动Indicators的计算以及由于运算而生成的任何线对象(例如sma - ema)
- ExponentialMovingAverage被实例化时不需要self.data参数
这是故意这样写的。如果没有传递data参数,则父级的第一个数据(在本例中是正在创建的策略)将在后台自动传递。
指标绘图
首先也是最重要的:
-
声明的Indicators将自动绘制(如果在主程序中调用了 cerebro.plot的话)
-
进行运算的线对象不会被绘制(例如close_over_sma = self.data.close > self.sma)
如果需要,有一个辅助类LinePlotterIndicator可以通过以下方法绘制此类运算结果:
1 | close_over_sma = self.data.close > self.sma |
name参数为该指标所持有的单个线提供名称。
控制绘图
在Indicator开发过程中可以添加plotinfo声明。它可以是元组的元组(2 个元素)、dict或OrderedDict。看起来像:
1 | class MyIndicator(bt.Indicator): |
稍后可以按如下方式访问(和设置)该值(如果需要):
1 | myind = MyIndicator(self.data, someparam=value) |
该值甚至可以在实例化期间设置:
1 | myind = MyIndicator(self.data, someparams=value, subplot=True) |
subplot=True将(在幕后)被传递给指标的实例化成员变量plotinfo。
plotinfo提供以下参数来控制绘图行为:
- plot(默认:True)是否绘制指标
- subplot(默认:True)
是否在不同的窗口中绘制指标。对于移动平均线等指标,默认值为False
- plotname(默认:‘’)
设置要在绘图上显示的绘图名称。为空值意味着将使用指标的规范名称 (class.name )。这有一些限制,因为 Python 标识符不能使用算术运算符等。
像 DI+ 这样的指标将声明如下:
1 | class DIPlus(bt.Indicator): |
能让作出来的图“更好看”
- plotabove(默认:False)
指标通常绘制在它们所操作的数据下方(带有subplot=True的)。将其设置为True将使指标绘制在数据上方。
- plotlinelabels(默认:False)
意思是“指标”上的“指标”。如果有人计算 RSI 的 SimpleMovingAverage,作出的图通常会显示相应绘制线的名称“SimpleMovingAverage”。这是“指标”的名称,而不是绘制的实际线条的名称。
此默认行为是有意义的,因为用户通常希望看到已使用 RSI 创建了 SimpleMovingAverage。
如果该值设置为True则将使用 SimpleMovingAverage 内部的实际线名称。
- plotymargin(默认:0.0)
指标顶部和底部留出的边缘大小 ( 0.15 表示 15%)。有时,matplotlib绘图距离轴的顶部/底部太远,可能需要留出边距
- plotyticks(默认:[])
用于控制绘制的y轴的刻度
如果传递空列表,将自动计算“y 刻度”。对于像随机指标这样的指标,将其设置为众所周知的行业标准可能是有意义的,例如:[20.0, 50.0, 80.0]
一些指标提供类似 upperband 和 lowerband 这样的参数,这些参数实际上用于操纵 y 刻度
- plothlines(默认:[])
用于控制沿指示器轴绘制水平线。
如果传递空列表,则不会绘制水平线。
对于像随机指标这样的指标,根据众所周知的行业标准绘制界限可能是有意义的,例如:[20.0, 80.0]
一些指标提供类似 upperband 和 lowerband 的参数,这些参数实际上用于操纵水平线
- plotyhlines(默认:[])
用于使用单个参数同时控制绘图刻度和绘图线。
- plotforce(默认:False)
如果出于某种原因,您认为某个指标应该绘制,但它没有绘制……将此设置为True是最后的手段。
这一篇就到这里啦。欢迎大家点赞、转发、私信。还没有关注我的朋友可以关注 江达小记