指標可以在平台的兩個地方使用:
內部策略
其他指標內部
指標在行動
指標總是在策略中的
__init__期間實例化next使用/檢查指標值(或其派生值)
有一個重要的公理需要考慮:
- 在
__init__期間聲明的任何Indicator(或其派生值)都將在調用next之前預先計算。
讓我們來看看操作模式的差異。
__init__與next
事情如下:
在
__init__期間任何涉及線對象的操作都會生成另一個線對象在
next期間任何涉及行對象的操作都會產生常規的 Python 類型,例如浮點數和布爾值。
在__init__期間
__init__期間的操作示例:
hilo_diff = self.data.high - self.data.low
變量hilo_diff包含對lines對象的引用,該對像在調用next之前預先計算,可以使用標準數組表示法[]訪問
它顯然包含數據饋送的每個條形圖的最高價和最低價之間的差異。
這也適用於混合簡單的線條(如 self.data數據饋送中的那些)和復雜的線條如指標:
sma = bt.SimpleMovingAverage(self.data.close) close_sma_diff = self.data.close - sma
現在close_sma_diff再次包含一個線對象。
使用邏輯運算符:
close_over_sma = self.data.close > sma
現在生成的lines對象將包含一個布爾數組。
next期間
操作示例(邏輯運算符):
close_over_sma = self.data.close > self.sma
使用等效數組(基於索引 0 的符號):
close_over_sma = self.data.close[0] > self.sma[0]
在這種情況下, close_over_sma產生一個布爾值,它是比較兩個浮點值的結果,由[0]運算符返回的值應用於self.data. close和self.sma
__init__與next為什麼
邏輯簡化(以及易用性)是關鍵。計算和大部分相關邏輯可以在__init__期間聲明,在next期間將實際操作邏輯保持在最低限度。
實際上還有一個附帶的好處:速度(由於開頭解釋的預先計算)
在__init__期間生成買入信號的完整示例:
class MyStrategy(bt.Strategy):
def __init__(self):
sma1 = btind.SimpleMovingAverage(self.data)
ema1 = btind.ExponentialMovingAverage()
close_over_sma = self.data.close > sma1
close_over_ema = self.data.close > ema1
sma_ema_diff = sma1 - ema1
buy_sig = bt.And(close_over_sma, close_over_ema, sma_ema_diff > 0)
def next(self):
if buy_sig:
self.buy()
筆記
Python 的and運算符不能被覆蓋,迫使平台定義自己的And 。這同樣適用於其他結構,如Or和If
很明顯, __init__期間的“聲明式”方法將next (實際策略工作發生的地方)的膨脹降至最低。
(別忘了還有一個加速因素)
筆記
當邏輯變得非常複雜並涉及多個操作時,通常將其封裝在Indicator中會更好。
一些筆記
在上面的示例中,與其他平台相比, backtrader簡化了兩件事:
聲明的
Indicators既沒有獲得父參數(如創建它們的策略,也沒有調用任何類型的“註冊”方法/函數。儘管如此,該策略將啟動
Indicators的計算以及由於操作生成的任何線對象(如sma - ema)ExponentialMovingAverage在沒有self.data的情況下被實例化這是故意的。如果沒有
data傳遞,則父級的第一個數據(在這種情況下是正在創建的策略)將在後台自動傳遞
指標繪圖
首先也是最重要的:
聲明的
Indicators會自動繪製(如果調用cerebro .plot)操作中的線條對像不會被繪製(如
close_over_sma = self.data. close > self.sma)如果需要,有一個輔助
LinePlotterIndicator可以使用以下方法繪製此類操作:close_over_sma = self.data.close > self.sma LinePlotterIndicator(close_over_sma, name='Close_over_SMA')
name參數為該指標持有的單行提供名稱。
控制繪圖
在開髮Indicator期間,可以添加plotinfo聲明。它可以是元組的元組(2 個元素)、 dict或OrderedDict 。看起來像:
class MyIndicator(bt.Indicator):
....
plotinfo = dict(subplot=False)
....
稍後可以按如下方式訪問(和設置)該值(如果需要):
myind = MyIndicator(self.data, someparam=value) myind.plotinfo.subplot = True
該值甚至可以在實例化期間設置:
myind = MyIndicator(self.data, someparams=value, subplot=True)
subplot= True將傳遞給指標的(在幕後)實例化成員變量plotinfo 。
plotinfo提供以下參數來控制繪圖行為:
plot(默認值:True)是否要繪製指標
subplot(默認值:True)是否在不同的窗口中繪製指標。對於移動平均線等指標,默認值更改為
Falseplotname(默認值:'')設置要在繪圖上顯示的繪圖名稱。空值意味著將使用指標的規範名稱 (
class.__name__)。這有一些限制,因為 Python 標識符不能使用例如算術運算符。像 DI+ 這樣的指標將聲明如下:
class DIPlus(bt.Indicator): plotinfo=dict(plotname='DI+')讓劇情“更精彩”
plotabove(默認值:False)指標通常繪製在他們操作的數據下方(那些
subplot= True)。將此設置為True將使指標繪製在數據上方。plotlinelabels(默認值:False)用於“指標”上的“指標”。如果計算 RSI 的 SimpleMovingAverage,繪圖通常會顯示相應繪製線的名稱“SimpleMovingAverage”。這是“指標”的名稱,而不是實際繪製的線。
這種默認行為是有意義的,因為用戶通常希望看到使用 RSI 創建了 SimpleMovingAverage。
如果該值設置為
True,則將使用 SimpleMovingAverage中行的實際名稱。plotymargin(默認值:0.0)在指標頂部和底部留下的保證金量 (
0.15-> 15%)。有時matplotlib繪圖離軸的頂部/底部太遠,可能希望留出餘量plotyticks(默認值:[])用於控制繪製的 y 刻度刻度
如果傳遞了一個空列表,則會自動計算“y ticks”。對於像隨機指標這樣的東西,將其設置為眾所周知的行業標準可能是有意義的,例如:
[20.0, 50.0, 80.0]一些指標提供了實際用於操縱 y 刻度的參數,例如
upperband和lowerbandplothlines(默認值:[])用於控制沿指標軸繪製水平線。
如果傳遞一個空列表,則不會繪製水平線。
對於像隨機指標這樣的東西,為眾所周知的行業標準畫線可能是有意義的,例如:
[20.0, 80.0]一些指標提供實際用於操縱水平線的參數,
upperband和lowerbandplotyhlines(默認值:[])用於使用單個參數同時控制 plotyticks 和 plothlines。
plotforce(默認值:False)如果由於某種原因您認為某個指標應該在繪圖而它沒有在繪圖……作為最後的手段,將其設置為
True。