版本 1.3.0.92提供了混合來自不同時間範圍的數據(來自數據饋送和/或指標)的可能性。
背景:指標是智能的啞對象。
他們很聰明,因為他們可以進行複雜的計算。
他們是愚蠢的,因為他們在不知道哪些來源為計算提供數據的情況下進行操作
像這樣:
- 如果提供值的數據源在
Cerebro引擎內具有不同的時間範圍、不同的長度,則指標將中斷。
計算示例,其中data0的時間範圍為天,而data1的時間範圍為months :
pivotpoint = btind.PivotPoint(self.data1) sellsignal = self.data0.close < pivotpoint.s1
當收盤價低於s1線(第一支撐)時,這裡尋求賣出信號
筆記
根據定義, PivotPoint在更大的時間範圍內工作
這將在過去出現以下錯誤:
return self.array[self.idx + ago] IndexError: array index out of range
並且有一個很好的理由: self.data. close提供從第一個時刻PivotPoint (以及因此s1線)只會在整整一個月過去後提供值,這大致相當於self.data0. close 。在這 22 次關閉期間,還沒有s1的值,並且嘗試從底層數組中獲取它失敗。
Lines對象支持(ago)運算符(Python 中的__call__特殊方法)以提供其自身的延遲版本:
close1 = self.data.close(-1)
在這個例子中,對象close1 (當通過[0]訪問時)總是包含由close傳遞的前一個值( -1 )。該語法已被重用以適應適應時間範圍。讓我們重寫上面的pivotpoint片段:
pivotpoint = btind.PivotPoint(self.data1) sellsignal = self.data0.close < pivotpoint.s1()
查看()如何在沒有參數的情況下執行(在後台提供None )。以下情況正在發生:
-
pivotpoint.s1()正在返回一個內部LinesCoupler對象,該對象遵循更大範圍的節奏。該耦合器使用來自真實s1的最新交付值填充自身(從默認值NaN開始)
但是需要一些額外的東西才能使魔法發揮作用。必須使用以下內容創建Cerebro :
cerebro = bt.Cerebro(runonce=False)
或執行:
cerebro.run(runonce=False)
在這種模式下,指標和後期評估的自動線對像是逐步執行的,而不是緊密循環。這使得整個操作變慢,但它使得它成為可能
底部的示例腳本被打破,現在運行:
$ ./mixing-timeframes.py
帶輸出:
0021,0021,0001,2005-01-31,2984.75,2935.96,0.00 0022,0022,0001,2005-02-01,3008.85,2935.96,0.00 ... 0073,0073,0003,2005-04-15,3013.89,3010.76,0.00 0074,0074,0003,2005-04-18,2947.79,3010.76,1.00 ...
在第 74行,第一個close < s1實例發生。
該腳本還提供了對其他可能性的洞察:耦合指標的所有行。之前我們有:
self.sellsignal = self.data0.close < pp.s1()
作為替代方案:
pp1 = pp() self.sellsignal = self.data0.close < pp1.s1
現在整個PivotPoint指標已耦合,可以訪問其任何行(即p 、 r1 、 r2 、 s1 、 s2 )。該腳本只對s1感興趣,並且可以直接訪問。:
$ ./mixing-timeframes.py --multi
輸出:
0021,0021,0001,2005-01-31,2984.75,2935.96,0.00 0022,0022,0001,2005-02-01,3008.85,2935.96,0.00 ... 0073,0073,0003,2005-04-15,3013.89,3010.76,0.00 0074,0074,0003,2005-04-18,2947.79,3010.76,1.00 ...
這裡沒有驚喜。和以前一樣。甚至可以繪製“耦合”對象:
$ ./mixing-timeframes.py --multi --plot
全耦合語法
對於具有多條線的線對象(例如像PivotPoint這樣的指標):
obj(clockref=None, line =-1)-
clockref如果clockref是None,則周圍的對象(在示例中為Strategy)將作為參考以適應較大的時間範圍(例如:Months)以適應更小/更快的時間範圍(例如:Days)
如果需要,可以使用另一個參考
line* If the default `-1` is given, all *lines* are coupled. * If another integer (for example, `0` or `1`) a single line will be coupled and fetched by index (from `obj.lines[x]`) * If a string is passed, the line will be fetched by name. In the sample, the following could have been done: ```python coupled_s1 = pp(line='s1') ```
-
對於具有單條線的線對象(例如來自指標PivotPoint的線s1 ):
-
obj(clockref=None)(參見上面的clockref)
結論
集成在常規()語法中,來自不同時間範圍的數據饋送可以混合在指標中,始終考慮到需要實例化或使用cerebro runonce= False創建 cerebro。
腳本代碼和用法
在backtrader的來源中作為示例提供。用法:
$ ./mixing-timeframes.py --help usage: mixing-timeframes.py [-h] [--data DATA] [--multi] [--plot] Sample for pivot point and cross plotting optional arguments: -h, --help show this help message and exit --data DATA Data to be read in (default: ../../datas/2005-2006-day-001.txt) --multi Couple all lines of the indicator (default: False) --plot Plot the result (default: False)
編碼:
from __future__ import (absolute_import, division, print_function,
unicode_literals)
import argparse
import backtrader as bt
import backtrader.feeds as btfeeds
import backtrader.indicators as btind
import backtrader.utils.flushfile
class St(bt.Strategy):
params = dict(multi=True)
def __init__(self):
self.pp = pp = btind.PivotPoint(self.data1)
pp.plotinfo.plot = False # deactivate plotting
if self.p.multi:
pp1 = pp() # couple the entire indicators
self.sellsignal = self.data0.close < pp1.s1
else:
self.sellsignal = self.data0.close < pp.s1()
def next(self):
txt = ','.join(
['%04d' % len(self),
'%04d' % len(self.data0),
'%04d' % len(self.data1),
self.data.datetime.date(0).isoformat(),
'%.2f' % self.data0.close[0],
'%.2f' % self.pp.s1[0],
'%.2f' % self.sellsignal[0]])
print(txt)
def runstrat():
args = parse_args()
cerebro = bt.Cerebro()
data = btfeeds.BacktraderCSVData(dataname=args.data)
cerebro.adddata(data)
cerebro.resampledata(data, timeframe=bt.TimeFrame.Months)
cerebro.addstrategy(St, multi=args.multi)
cerebro.run(stdstats=False, runonce=False)
if args.plot:
cerebro.plot(style='bar')
def parse_args():
parser = argparse.ArgumentParser(
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
description='Sample for pivot point and cross plotting')
parser.add_argument('--data', required=False,
default='../../datas/2005-2006-day-001.txt',
help='Data to be read in')
parser.add_argument('--multi', required=False, action='store_true',
help='Couple all lines of the indicator')
parser.add_argument('--plot', required=False, action='store_true',
help=('Plot the result'))
return parser.parse_args()
if __name__ == '__main__':
runstrat()