Last,但並非最不重要的一點是,在這個系列中,關於如何在 backtrader 中使用Python的隱藏功能是一些神奇變數是如何出現的。
self.datas
其他人從哪裡來?
通常的可疑類(或其子類)Strategy
Indicator
, 、 Analyzer
、 Observer
具有自動魔法定義的屬性,例如包含 data feeds的陣列。
Data Feeds 將添加到實例中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
調用,因此不會直接要求基類執行其 init -
引用的
self.data
定義mysig
可能與YahooFinanceData
添加到cerebro
確實如此!
實際上還有其他屬性,這些屬性在那裡,在示例中看不到。例如:
-
self.datas
:包含添加到的所有 data feeds 的陣列cerebro
-
self.dataX
:其中X
是一個數位,它反映了數據添加到 cerebro 的順序(data0
將是上面添加的數據) -
self.data
:指向self.data0
。為了方便起見,這隻是一個佇列,因為大多數示例和策略僅針對單個數據
可以在文件中找到更多內容:
如何創建這些屬性?
在本系列的第 2 篇文章中,發現類創建機制和實例創建機制被截獲。後者用於執行此操作。
-
cerebro
通過以下方式接收類adstrategy
-
它將在需要時實例化它,並將自身添加為屬性
-
策略
new
的類方法在創建Strategy
實例期間被截獲,並檢查哪些 data feeds 在cerebro
它確實創建了上面提到的陣列和別名
此機制應用於 backtrader 生態系統中的許多其他物件,以便簡化最終使用者必須執行的操作。因此:
-
例如,無需不斷創建包含命名
datas
參數的函數原型,也無需將其分配給self.datas
因為它是在後台自動神奇地完成的
這種攔截的另一個例子
讓我們定義一個獲勝指標,並將其添加到獲勝策略中。我們將重新包裝 close 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
但它似乎無處可做。如本系列的第 1 篇文章所示,該操作會生成一個物件,該物件被 self.lines.signal
分配給併發生以下情況:
-
此物件還會截獲其創建過程
-
它掃描堆疊以瞭解正在創建的上下文,在本例中為
MyIndicators
-
在初始化完成後,它會將自己添加到
MyIndicator
-
稍後在計算時
MyIndicator
,它將依次計算由self.lines.signal
不錯,但誰計算MyIndicator
遵循完全相同的過程:
-
MyIndicator
在創建過程中掃描堆疊並找到MyStrategy
-
並將自己添加到結構中
MyStrategy
-
在調用之前
next
,MyIndicator
被要求重新計算自身,這反過來又告訴self.lines.signal
重新計算自己
該過程可以具有多層間接尋址。
對用戶來說最好的事情:
-
無需像創建某些內容時那樣
register_operation
添加調用 -
無需手動觸發計算
總結
本系列中 last 文章展示了如何使用類/實例創建攔截來簡化最終使用者生活的另一個示例::
-
從生態系統中添加需要的物件並創建別名
-
自動註冊類和觸發計算