Python 的隐藏力量(3)
原文: https://www.backtrader.com/blog/posts/2016-11-25-hidden-powers-3/hidden-powers/
最后,但并非最不重要的一点是,在本系列中,关于如何在backtrader中使用 Python 的隐藏功能,一些神奇的变量是如何显示的。
self.datas和其他人来自哪里?
通常的可疑类(或其子类)Strategy、Indicator、Analyzer、Observer具有自动神奇地定义的属性,例如包含数据提要的数组。
数据馈送被添加到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的调用
- 
无需手动触发计算 
总结
本系列的最后一篇文章展示了如何使用类/实例创建截取使最终用户的生活更轻松的另一个示例:
- 
从需要的生态系统中添加对象并创建别名 
- 
自动注册类和触发计算 

