Skip to content

Python 的隐藏力量(3)

原文: https://www.backtrader.com/blog/posts/2016-11-25-hidden-powers-3/hidden-powers/

最后,但并非最不重要的一点是,在本系列中,关于如何在backtrader中使用 Python 的隐藏功能,一些神奇的变量是如何显示的。

self.datas和其他人来自哪里?

通常的可疑类(或其子类)StrategyIndicatorAnalyzerObserver具有自动神奇地定义的属性,例如包含数据提要的数组。

数据馈送被添加到cerebro实例中,如下所示:

from datetime import datetime
import backtrader as bt

cerebro = bt.Cerebro()
data = bt.YahooFinanceData(dataname=my_ticker, fromdate=datetime(2016, 1, 1))
cerebro.adddata(data)

... 

close高于简单移动平均线时,我们的获胜策略将持续很长时间。我们将使用信号来缩短示例:

class MyStrategy(bt.SignalStrategy):
    params = (('period', 30),)

    def __init__(self):
        mysig = self.data.close > bt.indicators.SMA(period=self.p.period)
        self.signal_add(bt.signal.SIGNAL_LONG, mysig) 

将其添加到混合中,如下所示:

cerebro.addstrategy(MyStrategy) 

任何读者都会注意到:

  • __init__不带参数,无论是否命名

  • 没有super调用,因此不会直接要求基类进行初始化

  • mysig的定义引用了self.data,可能与cerebro中增加的YahooFinanceData实例有关

    的确如此!

实际上还有其他一些属性,在示例中没有看到。例如:

  • self.datas:包含添加到cerebro的所有数据源的数组

  • self.dataX:其中X是一个数字,反映数据添加到大脑的顺序(data0将是上面添加的数据)

  • self.data:指向self.data0。因为大多数示例和策略只针对单个数据,所以为了方便起见,只需使用 ahortcut

更多信息可在文档中找到:

这些属性是如何创建的?

在本系列的第 2文章中,可以看到类创建机制和实例创建机制被截获。后者是用来做这件事的。

  • cerebro通过adstrategy接收

  • 它将在需要时实例化它,并将自身添加为属性

  • 策略的new类方法在Strategy实例的创建过程中被拦截,并检查cerebro中有哪些数据源

    它确实创建了上面提到的数组别名

该机制应用于backtrader生态系统中的许多其他对象,以简化最终用户的操作。像这样的:

  • 例如,不需要不断创建包含名为datas的参数的函数原型,也不需要将其分配给self.datas

    因为它是在后台自动完成的

这种拦截的另一个例子

让我们定义一个获胜指标,并将其添加到获胜策略中。我们将重新包装关闭 SMA理念:

class MyIndicator(bt.Indicator):
    params = (('period', 30),)
    lines = ('signal',)

    def __init__(self):
        self.lines.signal = self.data - bt.indicators.SMA 

现在将其添加到常规战略中:

class MyStrategy(bt.Strategy):
    params = (('period', 30),)

    def __init__(self):
        self.mysig = MyIndicator(period=self.p.period)

    def next(self):
        if self.mysig:
            pass  # do something like buy ... 

从上面的代码可以明显看出MyIndicator中正在进行计算:

self.lines.signal = self.data - bt.indicators.SMA 

但似乎什么地方也做不到。如本系列的 1st文章所示,该操作生成一个对象,该对象被分配给self.lines.signal,发生如下情况:

  • 此对象还拦截其创建过程

  • 它扫描堆栈以了解正在创建的上下文,在本例中是在MyIndicators实例中

  • 初始化完成后,加入MyIndicator的内部结构

  • 稍后计算MyIndicator时,它将依次计算self.lines.signal引用的对象内的操作

好,但是谁来计算MyIndicator

遵循完全相同的过程:

  • MyIndicator在创建过程中扫描堆栈并找到MyStrategy

  • 并添加到MyStrategy的结构中

  • 就在调用next之前,MyIndicator被要求重新计算自身,这反过来又告诉self.lines.signal重新计算自身

该过程可以有多个间接层。

对用户来说最好的东西是:

  • 创建某些内容时,无需添加类似于register_operation的调用

  • 无需手动触发计算

总结

本系列的最后一篇文章展示了如何使用类/实例创建截取使最终用户的生活更轻松的另一个示例:

  • 从需要的生态系统中添加对象并创建别名

  • 自动注册类和触发计算


我们一直在努力

apachecn/AiLearning

【布客】中文翻译组