1.3.0.92版本带来了混合来自不同时间帧的数据(来自 data feeds 和/或指针)的可能性。
到版本:https://github.com/mementum/backtrader/发布/标签/1.3.0.92
背景:指示器是智能哑对象。
-
他们很聪明,因为他们可以进行复杂的计算。
-
他们是愚蠢的,因为他们不知道哪些来源为计算提供数据。
因此:
- 如果提供这些值的数据源具有不同的时间帧,引擎内部
Cerebro的长度也不同,则指针将中断。
计算范例,其中data0 的时间范围为天, data1 时间范围为 months:
pivotpoint = btind.PivotPoint(self.data1) sellsignal = self.data0.close < pivotpoint.s1
这里,当close低于s1line(1st支撑位)时,寻求卖出信号
注意
PivotPoint 根据定义,在更大的时间范围内工作
这将在过去出现以下错误:
return self.array[self.idx + ago] IndexError: array index out of range
并且有充分的理由:self.data.close从第1个瞬间开始提供值,但是PivotPoint(因此s1line)只会在整整一个月过去一次时才提供值,这大致相当于22个值self.data0.close。在此 22 关闭期间,尚无 值s1,并且尝试从基础数组中获取它失败。
Lines 对象支持() 运算符(__call__ Python中的特殊方法)来提供自身的延迟版本:
close1 = self.data.close(-1)
在此示例中,对象close1(当通过 [0]访问时)始终包含 由 close传递的先前值 (-1)。该语法已被重用以适应适应时间范围。让我们重写上面的pivotpoint片段:
pivotpoint = btind.PivotPoint(self.data1) sellsignal = self.data0.close < pivotpoint.s1()
()了解如何在没有参数的情况下运行 (在后台提供 aNone)。正在发生以下情况:
pivotpoint.s1() 返回一个内部 LinesCoupler 对象,该对象遵循较大范围的严格程度。该耦合器用实数 s1 中最新传递的值填充自身(从默认值 NaN开始)
但是需要一些额外的东西来使魔术起作用。Cerebro 必须使用以下命令创建:
cerebro = bt.Cerebro(runonce=False)
或通过以下方式运行:
cerebro.run(runonce=False)
在此模式下,指针和后期评估的自动 lines 对象是逐步运行的,而不是在紧密循环中运行的。这使得整个操作变慢,但它使它成为可能
底部的示例脚本正在上面断开,现在运行:
$ ./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 时,第 1 个 实例 close < s1 的 take palce。
该脚本还提供了对其他可能性的见解:耦合指针的所有 lines 。在我们之前:
self.sellsignal = self.data0.close < pp.s1()
作为替代方案:
pp1 = pp() self.sellsignal = self.data0.close < pp1.s1
现在整个PivotPoint指针已经耦合,并且可以访问其任何lines(即p, , r1, r2s1, ) 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
完整耦合语法
对于具有多个lineslines对象(例如,指针如下PivotPoint):
-
obj(clockref=None, line=-1)clockref如果clockref是None,则周围的对象(在示例aStrategy中)将是使较大的时间帧(例如: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: ``` coupled_s1 = pp(line='s1') ```
对于具有单个line的lines对象(例如,指针中的PivotPointlines1):
obj(clockref=None)(见上文clockref)
结论
集成在常规() 语法中,来自不同时间帧的数据可以混合在指针中,同时始终考虑 cerebro 需要使用 runonce=False实例化或创建的数据。
脚本代码和用法
可作为样品在源。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()