You are here:  Home » 量化交易与机器学习 » backtrader » 指示灯开发 – backtrader中文教程

指示灯Development

If任何东西(除了一个或多个获胜策略),必须不断开发,这个东西是平台内的自定义Indicator.

Such发展,据笔者,easy.

The以下需要:

  • 从指标派生的类(直接或从一个已经存在的子类)
  • 定义lines它将hold

    An指示器必须至少有1行。如果从现有的派生,线(多个)可能已经被defined

  • Optionally限定能改变behavior
  • Optionally提供的参数/定制一些其能够明智的元件的所述indicators
  • Provide的绘制在__init__完全定义的操作与结合(分配)到指示器否则的线(S)提供next和(任选地)oncemethods

    If的指示符可以被完全逻辑/算术运算期间定义初始化,结果被分配到该行:done

    是它不是这种情况,至少一个next必须被提供,其中所述指示器必须在计算的索引0

    Optimization一个值分配给线(S)的runonce模式(间歇操作)可以通过提供可以实现一个oncemethod.

Important注:Idempotence

Indicators产生用于他们收到每个条的输出。没有假设必须是有多少次同样的酒吧将被发送制造。操作必须这背后idempotent.

The理由:

  • 相同的杆(索引明智)可以与改变的值被发送多次(即改变值是收盘价)

这使得能够,例如,“重放”每日会话,但使用盘中数据这可以由5分钟bars.

It还可以允许平台从现场feed.

A哑得值(但功能)indicator

So可以它是:

class DummyInd(bt.Indicator):
    lines = ("dummyline",)

    params = (("value", 5),)

    def __init__(self):
        self.lines.dummyline = bt.Max(0.0, self.params.value)

完成!该指标将输出总是相同的值:要么0.0或self.params.value如果它正好是大于0.0.

The同一指标,但使用下一个方法:

class DummyInd(bt.Indicator):
    lines = ("dummyline",)

    params = (("value", 5),)

    def next(self):
        self.lines.dummyline[0] = max(0.0, self.params.value)

完成!同样behavior.

Note

Notice如何在__init__版本bt.Max是用来分配给线条对象self.lines.dummyline.

bt.Max返回一个lines即自动迭代为对象传递给indicator.

Hadmax被代替,转让本来毫无意义的,因为不是一条线,指标将有与成员变量的固定value.

Duringnext工作与浮点值直接完成和标准的max内置可used

Let此次召回的是self.lines.dummyline是长的符号,它可以缩短为:

  • self.l.dummyline

甚至:

  • self.dummyline

后者是唯一可能的,如果代码没有用构件遮挡这个attribute.

The 3rd和最后一个版本提供了额外的once方法来优化计算:

class DummyInd(bt.Indicator):
    lines = ("dummyline",)

    params = (("value", 5),)

    def next(self):
        self.lines.dummyline[0] = max(0.0, self.params.value)

    def once(self, start, end):
       dummy_array = self.lines.dummyline.array

       for i in xrange(start, end):
           dummy_array[i] = max(0.0, self.params.value)

很多更有效,但发展once方法强行超越划伤表面。其实胆量也一直看着into.

The__init__版本是在任何情况下最好的:

  • 一切都局限在initialization
  • nextonce(均进行了优化,因为bt.Max已经拥有它们)与没有必要与指数和/或自动播放提供formulas

Be它需要发展,指示灯也会可以覆盖方法关联到nextonce

  • prenextnexstart
  • preonceoncestart

手动/自动最小Period

If尽可能平台将计算,但手动操作可能needed.

Here是可能实现的Simple Moving Average

class SimpleMovingAverage1(Indicator):
    lines = ("sma",)
    params = (("period", 20),)

    def next(self):
        datasum = math.fsum(self.data.get(size=self.p.period))
        self.lines.sma[0] = datasum / self.p.period

虽然看上去声音,平台不知道是什么最小周期是即使参数被命名为“时期”(这个名字可能是误导性的,一些指标收到多个“周期” s具有不同用途)

在这种情况下next会已经呼吁1st酒吧和寄托都会爆炸,因为得到不能返回所需的self.p.period.

之前解决情况的东西,必须考虑到:

  • 提要传递给指标数据可能已经携带了最低period

The样品SimpleMovingAverage可在例如完成:

  • 常规数据feed

    This具有1的默认周期的最小值(只是等待该1st栏进入系统)

  • 另一个移动平均线……而这反过来已经拥有了period

    如果是20,并再次在我们的样本均线也已20,我们结束了40 bars

    Actually的最小周期内计算说39 ……因为只要第一移动平均制作了条此计数用于下一个移动平均,它创建的重叠条,从而39 needed.

  • Other指标/其也携带periods

Alleviating的情况是如下进行的对象:

class SimpleMovingAverage1(Indicator):
    lines = ("sma",)
    params = (("period", 20),)

    def __init__(self):
        self.addminperiod(self.params.period)

    def next(self):
        datasum = math.fsum(self.data.get(size=self.p.period))
        self.lines.sma[0] = datasum / self.p.period

addminperiod方法告诉系统要考虑到额外的period通过这个指标需要酒吧任何最短期限有可能是在existence.

Sometimes这是绝对需要的,如果所有的计算都做了

完成:这已经传达其周期需要到system.MACDA快

from backtrader.indicators import EMA

class MACD(Indicator):
    lines = ("macd", "signal", "histo",)
    params = (("period_me1", 12), ("period_me2", 26), ("period_signal", 9),)

    def __init__(self):
        me1 = EMA(self.data, period=self.p.period_me1)
        me2 = EMA(self.data, period=self.p.period_me2)
        self.l.macd = me1 - me2
        self.l.signal = EMA(self.l.macd, period=self.p.period_signal)
        self.l.histo = self.l.macd - self.l.signal

实现与直方图的对象!没有必要去想的最小值periods.

  • EMA代表Exponential Moving Average(一个平台,内置别名)

    这一个(已经在平台)已经规定,它需要什么

  • 指示符“MACD”和“信号”的命名线在被分配“ – ME2 ME1”这反过来它已经携带声明(幕后)periods
    • macd需要从操作的时间段对象取最大值从ME1和ME2的周期(这两者都是具有不同周期的指数移动平均)
    • 信号直接将指数移动平均的在此期间MACD。这EMA还考虑到已经存在的MACD期和的样品(period_signal)所需要的量,以计算itself
    • histo取最大值的两个操作数的“信号 – MACD”。一旦两个准备好可以HISTO也产生value

A全定制indicator

Let的开发出“表示:”如果移动平均一个简单的自定义指标(可以用一个参数来修改)是给定的数据以上:

import backtrader as bt
import backtrader.indicators as btind

class OverUnderMovAv(bt.Indicator):
    lines = ("overunder",)
    params = dict(period=20, movav=btind.MovAv.Simple)

    def __init__(self):
        movav = self.p.movav(self.data, period=self.p.period)
        self.l.overunder = bt.Cmp(movav, self.data)

完成!该指标将具有“1”的值,如果平均值是上述数据和“-1”如果below.

Be所述数据的常规数据馈送1和-1s将产生与比较紧密price.

Although更多中可以看到的Plotting部并具有表现和在绘制世界公民不错,可以加几件事情:

import backtrader as bt
import backtrader.indicators as btind

class OverUnderMovAv(bt.Indicator):
    lines = ("overunder",)
    params = dict(period=20, movav=bt.ind.MovAv.Simple)

    plotinfo = dict(
        # Add extra margins above and below the 1s and -1s
        plotymargin=0.15,

        # Plot a reference horizontal line at 1.0 and -1.0
        plothlines=[1.0, -1.0],

        # Simplify the y scale to 1.0 and -1.0
        plotyticks=[1.0, -1.0])

    # Plot the line "overunder" (the only one) with dash style
    # ls stands for linestyle and is directly passed to matplotlib
    plotlines = dict(overunder=dict(ls="--"))

    def _plotlabel(self):
        # This method returns a list of labels that will be displayed
        # behind the name of the indicator on the plot

        # The period must always be there
        plabels = [self.p.period]

        # Put only the moving average if it"s not the default one
        plabels += [self.p.movav] * self.p.notdefault("movav")

        return plabels

    def __init__(self):
        movav = self.p.movav(self.data, period=self.p.period)
        self.l.overunder = bt.Cmp(movav, self.data)

评论被关闭。