Skip to content

使用指标

原文: https://www.backtrader.com/docu/induse/

指示器可在平台的两个位置使用:

  • 内部战略

  • 内部其他指标

行动中的指标

  1. 指标总是在策略__init__期间实例化

  2. next期间使用/检查指标值(或其衍生值)

有一个重要的公理需要考虑:

  • __init__期间声明的任何Indicator(或其派生值)将在调用next之前进行预计算。

让我们来看看不同的操作模式。

__init__vsnext

事情是这样的:

  • __init__期间涉及对象的任何操作都会生成另一个对象

  • next期间,任何涉及对象的操作都会生成常规 Python 类型,如 float 和 bools。

__init__期间

__init__期间的操作示例:

hilo_diff = self.data.high - self.data.low 

变量hilo_diff保存对对象的引用,该对象在调用next之前已预先计算,可以使用标准数组符号[]访问

它显然包含了每个数据条的高电平和低电平之间的差异。

当混合使用简单的(如 self.data 提要中的行)和复杂的行(如指示器:

sma = bt.SimpleMovingAverage(self.data.close)
close_sma_diff = self.data.close - sma 

现在close_sma_diff再次包含一个对象。

使用逻辑运算符:

close_over_sma = self.data.close > sma 

现在生成的对象将包含一个布尔数组。

next期间

操作示例(逻辑运算符):

close_over_sma = self.data.close > self.sma 

使用等效数组(基于索引 0 的表示法):

close_over_sma = self.data.close[0] > self.sma[0] 

在这种情况下,close_over_sma产生一个布尔值,它是比较两个浮点值的结果,[0]运算符返回的值应用于self.data.closeself.sma

__init__next为什么

逻辑简化(及其易用性)是关键。可以在__init__期间声明计算和大部分相关逻辑,并在next期间将实际操作逻辑保持在最小值。

实际上还有一个副作用:速度(由于前面解释的预计算)

__init__期间生成购买信号的完整示例:

class MyStrategy(bt.Strategy):

    def __init__(self):

        sma1 = btind.SimpleMovingAverage(self.data)
        ema1 = btind.ExponentialMovingAverage()

        close_over_sma = self.data.close > sma1
        close_over_ema = self.data.close > ema1
        sma_ema_diff = sma1 - ema1

        buy_sig = bt.And(close_over_sma, close_over_ema, sma_ema_diff > 0)

    def next(self):

        if buy_sig:
            self.buy() 

笔记

Python 的and操作符不能被重写,迫使平台定义自己的And。这同样适用于其他构造,如OrIf

显然,在__init__期间的“声明式”方法将next(实际策略工作发生的地方)的膨胀保持在最低限度。

(别忘了还有一个加速因素)

笔记

当逻辑变得非常复杂并涉及多个操作时,通常最好将其封装在Indicator中。

一些注释

在上述示例中,与其他平台相比,backtrader中简化了两件事:

  • 声明的Indicators既没有得到参数(如创建它们的策略),也没有调用任何类型的“寄存器”方法/函数。

    尽管如此,该策略仍会触发对Indicators和任何对象(如sma - ema等)的计算

  • ExponentialMovingAverage正在实例化,没有self.data

    这是故意的。如果没有通过data,则(本例中为正在创建的策略)的 1st数据将在后台自动传递

指示标绘

首先,也是最重要的:

  • 已声明的Indicators自动绘制(如果调用了脑波图)

  • 操作中的对象不会被打印(如close_over_sma = self.data.close > self.sma

    有一个辅助LinePlotterIndicator,如果需要,可通过以下方法绘制此类操作:

    py close_over_sma = self.data.close > self.sma LinePlotterIndicator(close_over_sma, name='Close_over_SMA')

    name参数为该指示器持有的行命名。

控制标绘

Indicator的开发过程中,可以添加plotinfo声明。它可以是元组的元组(2 个元素)、一个dict或一个OrderedDict。它看起来像:

class MyIndicator(bt.Indicator):

    ....
    plotinfo = dict(subplot=False)
    .... 

以后可以按如下方式访问(和设置)该值(如果需要):

myind = MyIndicator(self.data, someparam=value)
myind.plotinfo.subplot = True 

该值甚至可以在实例化期间设置:

myind = MyIndicator(self.data, someparams=value, subplot=True) 

subplot=True将被传递到指示器的(幕后)指定成员变量plotinfo

plotinfo提供以下参数来控制打印行为:

  • plot(默认为True

    是否绘制指示器

  • subplot(默认为True

    是否在其他窗口中绘制指示器。对于移动平均线等指标,默认值更改为False

  • plotname(默认为''

    设置要在打印上显示的打印名称。空值表示将使用指示符的规范名称(class.__name__。这有一些限制,因为 Python 标识符不能使用例如算术运算符。

    类似 DI+的指标将声明如下:

    py class DIPlus(bt.Indicator): plotinfo=dict(plotname='DI+')

    让情节“更美好”

  • plotabove(默认为False

    指标通常在其操作数据下方绘制(带有subplot=True的指标)。将此设置为True将使指示器标绘在数据上方。

  • plotlinelabels(默认为False

    用于“指标”上的“指标”。如果计算 RSI 的 SimpleMovingAverage,则绘图通常会显示相应绘图线的名称“SimpleMovingAverage”。这是“指示器”的名称,而不是正在绘制的实际线。

    这种默认行为是有意义的,因为用户通常希望看到 SimpleMovingAverage 是使用 RSI 创建的。

    如果该值设置为True,则将使用 SimpleMovingAverage 内的行的实际名称。

  • plotymargin(默认为0.0

    指标顶部和底部留下的保证金金额(0.15->15%)。有时matplotlib图太过靠近轴的顶部/底部,可能需要留一个边距

  • plotyticks(默认为[]

    用于控制绘制的 y 比例记号

    如果传递的是空列表,“y 记号”将自动计算。对于随机变量,将其设置为众所周知的行业标准(如:[20.0, 50.0, 80.0]可能是有意义的

    一些指示器提供了upperbandlowerband等参数,这些参数实际上用于操纵 y 记号

  • plothlines(默认为[]

    用于控制沿指示器轴绘制水平线。

    如果传递空列表,则不会绘制水平线。

    对于像随机变量这样的东西,为众所周知的行业标准划一条线可能是有意义的,比如:[20.0, 80.0]

    一些指示器提供了upperbandlowerband等参数,实际用于操纵水平线

  • plotyhlines(默认为[]

    用于使用单个参数同时控制 PlotyTrack 和 Plothline。

  • plotforce(默认为False

    如果出于某种原因,您认为某个指示器应该正在绘制,但它没有绘制……将其设置为True作为最后手段。


我们一直在努力

apachecn/AiLearning

【布客】中文翻译组