backtrader的最初目标之一是:

  • 能够快速制作指标原型以测试新想法

它不一定是一个完美的指标,但能够快速轻松地开发它们确实会有所帮助。为了确认设计是正确的,反向交易者标准武器库中的第一个指标指数移动平均线(又名EMA),根据定义,它是:递归的。

让我们开发一个快速ExponentialMovingAverage指标。

递归指标,如

  • 它使用先前的值来计算当前值

例如,您可以在Wikipedia – Exponential Moving Average中查看数学

如果您有足够的勇气阅读全部内容,您会发现该周期用于计算指数平滑。我们会使用它。

为了解决计算第一个值的难题,业界 决定使用先前period值的简单平均值。

作为杠杆,我们将使用bt.indicators.PeriodN

  • 已经定义了一个period参数
  • 通知框架period最终用户的实际使用情况

然后让我们开发我们的EMA

import backtrader as bt

class EMA(bt.indicators.PeriodN):
    params = {'period': 30}  # even if defined, we can redefine the default value
    lines = ('ema',)  # our output line

    def __init__(self):
        self.alpha = 2.0 / (1.0 + self.p.period)  # period -> exp smoothing factor

    def nextstart(self):  # calculate here the seed value
        self.lines.ema[0] = sum(self.data.get(size=self.p.period)) / self.p.period

    def next(self):
        ema1 = self.lines.ema[-1]  # previous EMA value
        self.lines.ema[0] = ema1 * (1.0 - self.alpha) + self.data[0] * self.alpha

做起来几乎比说的容易。关键是在 中提供种子值 nextstart,其中

  • 当达到指标的最短预热期时,将调用一次。

    与之相反,next对于传递到系统中的每个新数据值都将调用

的默认实现只是将大多数指标(例如简单移动平均线nextstart)委托给的工作 是正确的。但在这种情况下,覆盖和提供种子值是关键。next

沿着数据绘制

作为移动平均线,如果指标绘制在与其计算平均值的数据相同的轴上,那就太好了。因为我们继承PeriodN了绘图的默认值是(参见文档):

subplot=True

这当然意味着subplot将为我们的指标创建一个(图表上的另一个轴)。这很容易被覆盖。

import backtrader as bt

class EMA(bt.indicators.PeriodN):
    plot = dict(subplot=False)