混合时间框架的指标#
版本1.3.0.92 增加了从不同时间框架混合数据(来自数据源和/或指标)的可能性。
背景: 指标是智能但愚蠢的对象。
它们是智能的,因为它们可以进行复杂的计算。
它们是愚蠢的,因为它们在进行计算时不了解数据的来源。
因此:
如果提供值的数据源具有不同的时间框架,在
Cerebro
引擎内有不同的长度,则指标将无法正常工作。
以下是一个计算示例,其中 data0
的时间框架为天,而 data1
的时间框架为 月
:
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个值。在这22个 closes 期间, s1
还没有值,并且尝试从底层数组中获取它将会失败。
Lines 对象支持
(ago)
操作符( Python 的__call__
特殊方法),用于产生自身的延迟版本:close1 = self.data.close(-1)
在此示例中,当通过 [0]
访问对象 close1
时,它始终包含由 close
提供的前一个值( -1
)。借助这种语法可以适应不同的时间范围。让我们重新编写上述的 pivotpoint
片段:
pivotpoint = btind.PivotPoint(self.data1)
sellsignal = self.data0.close < pivotpoint.s1()
注意到 ()
在没有参数的情况下执行(背景中提供了 None
)。以下是正在发生的事情:
pivotpoint.s1()
返回一个内部的LinesCoupler
对象,该对象遵循较大范围的节奏。该耦合器用最新的实际s1
值(默认值为NaN
)填充自身但是要使魔法起作用,还需要一些额外的东西。Cerebro
必须使用以下方式创建:
`python
cerebro = bt.Cerebro(runonce=False)
`
或者使用以下方式执行:
`python
cerebro.run(runonce=False)
`
在这种模式下,指标和延迟评估的自动“line”对象会逐步执行,而不是在紧密循环中执行。这使得整个操作变慢,但却使其成为了可能。
底部的示例脚本现在可以正常运行:
`bash
$ ./mixing-timeframes.py
`
输出如下:
`plaintext
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.. thumbnail:: indicators-mixing-timeframes.png
完整的耦合语法#
对于包含多条线的 lines 对象(例如像 PivotPoint
这样的 Indicators ):
obj(clockref=None, line=-1)
clockref
如果clockref
是None
,则周围的对象(在这个示例中是Strategy
)将作为引用,用于将较大的时间框架(例如:Months
)调整到较小/更快的时间框架(例如:Days
)如果需要,可以使用其他引用
line
如果使用默认的
-1
,那么所有的 lines 都会被耦合。如果使用其他整数(例如,
0
或1
),那么只有一条线会被耦合并通过索引(从obj.lines[x]
)获取如果传入一个字符串,将会通过名称获取该线。
在示例中,也可以这样做:
coupled_s1 = pp(line=’s1’)
对于只有一条线的 lines 对象(例如来自指标 PivotPoint
的线 s1
): - 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
显示帮助信息并退出
- --data DATA
要读取的数据(默认:../../datas/2005-2006-day-001.txt)
- --multi
将指标的所有线连接起来(默认:False)
- --plot
绘制结果(默认: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()