Python隐藏的力量(3) – backtrader中文教程
最后但并非最不重要的一点是,在这个关于 Python 的隐藏功能如何在 backtrader中使用的系列中,一些神奇的变量是如何出现的。
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) ...
当收盘价高于简单移动平均线时,我们的示例获胜策略将做多。 我们将使用 Signals 使示例更短:
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
可能与YahooFinanceData
添加到的实例有关cerebro
确实如此!
实际上还有其他属性,但在示例中没有看到。例如:
self.datas
: 一个数组,包含添加到 的所有数据提要cerebro
self.dataX
:其中X
是一个数字,它反映了将数据添加到 cerebro 的顺序(data0
将是上面添加的数据)self.data
: 指向self.data0
. 只是为了方便起见,因为大多数示例和策略仅针对单个数据
更多可以在文档中找到:
这些属性是如何创建的?
在本系列的第 2篇文章中,看到了类创建机制和实例创建机制被拦截。后者用于执行此操作。
cerebro
通过接收课程adstrategy
- 它会在需要时实例化它并将自身添加为属性
- 策略的
new
classmethod 在创建Strategy
实例的过程中被拦截,并检查哪些数据源可用cerebro
它确实创建了上面提到的数组和别名
此机制适用于反向交易者生态系统中的许多其他对象,以简化最终用户必须执行的操作。像这样:
- 例如,无需不断创建包含名为的参数的函数原型,
datas
也无需将其分配给self.datas
因为它是在后台自动完成的
这种拦截的另一个例子
让我们定义一个获胜指标并将其添加到获胜策略中。我们将重新包装关闭 SMA的想法:
class MyIndicator(bt.Indicator): params = (('period', 30),) lines = ('signal',) def __init__(self): self.lines.signal = self.data - bt.indicators.SMA
从上面的代码显然有一个计算发生在 MyIndicator
:
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 ...
但它似乎无处可做。正如本系列的第 1 篇文章中所见,该操作生成一个object,该 object 被分配给self.lines.signal
并发生以下情况:
- 这个对象也拦截了它的创建过程
- 它扫描堆栈以了解正在创建的上下文,在本例中是在
MyIndicators
- 并且在其初始化完成后,将自身加入到内部结构中
MyIndicator
- 稍后当
MyIndicator
被计算时,它会依次计算被引用的对象内部的操作self.lines.signal
好,但谁计算MyIndicator
遵循完全相同的过程:
MyIndicator
在创建期间扫描堆栈并找到MyStrategy
- 并将自身添加到结构中
MyStrategy
- 就在
next
调用之前,MyIndicator
要求重新计算自身,而后者又告诉self.lines.signal
重新计算自身
该过程可以有多个间接层。
对用户来说最好的东西:
- 无需像
register_operation
创建某些东西时那样添加调用 - 无需手动触发计算
结束语
本系列的最后一篇文章展示了如何使用类/实例创建拦截来使最终用户的生活更轻松的另一个示例:
- 在需要它们的地方添加生态系统中的对象并创建别名
- 自动注册课程和触发计算
评论被关闭。