时间已经过去,针对完全角成和封闭的柱线测试策略是好的,但它可能会更好。
这就是 Data Replay 的用武之地。如果:
- 该策略对时间范围 X 的数据进行操作(例如:每日)
和
- 更小时间范围 Y(例如:1 分钟)的数据可用
数据重放正如其名称所暗示的那样:
- 使用 1 分钟数据重播每日柱
这当然不完全是市场的发展方式,但它比孤立地查看每日完全角成和封闭的柱线要好得多:
如果策略在每日柱形的形成过程中实时运行,则柱形的近似值提供了在真实条件下拷贝策略的实际行为的机会
将数据重放付诸行动遵循backtrader
的常规使用模式
加载数据馈送
使用
replaydata
将数据传递给cerebro添加策略
笔记
重播数据时不支持预加载,因为每个条实际上都是实时构建的。它会在任何Cerebro
实例中自动禁用。
可以传递给replaydata
的参数:
timeframe
(默认:bt.TimeFrame.Days)有用的目标时间范围必须等于或大于源
compression
(默认值:1)将所选值“n”压缩为 1 bar
扩展参数(如果不是真的需要,请勿触摸):
bar2edge
(默认值: True )使用时间边界作为封闭柱的目标重播。例如,使用“ticks -> 5 seconds”,生成的 5 秒条将对齐到 xx:00、xx:05、xx:10 …
adjbartime
(默认值: False )使用边界处的时间来调整交付的重采样柱的时间,而不是最后看到的时间戳。如果重新采样到“5 秒”,则柱的时间将调整为例如 hh:mm:05,即使最后看到的时间戳是 hh:mm:04.33
注意:仅当“bar2edge”为True时才会调整时间。如果条未与边界对齐,则调整时间没有意义
rightedge
(默认值: True )使用时间边界的右边缘设置时间。
如果False并压缩到 5 秒,则在 hh:mm:00 和 hh:mm:04 之间重新采样的条形的时间将是 hh:mm:00(起始边界
如果为True ,则使用的时间边界将是 hh:mm:05(结束边界)
为了使用示例,将每周重播标准的 2006 年每日数据。意思是:
最终将有 52 个酒吧,每周一个
Cerebro将调用
prenext
和next
共 255 次,这是每日柱的原始计数
诀窍:
当周柱形成时,策略的长度 (
len(self)
) 将保持不变。每个新的一周,长度将增加一
下面是一些示例,但首先是测试脚本的调味汁,其中数据被加载并使用replaydata
......然后run
.
# Load the Data datapath = args.dataname or '../../datas/2006-day-001.txt' data = btfeeds.BacktraderCSVData(dataname=datapath) # Handy dictionary for the argument timeframe conversion tframes = dict( daily=bt.TimeFrame.Days, weekly=bt.TimeFrame.Weeks, monthly=bt.TimeFrame.Months) # First add the original data - smaller timeframe cerebro.replaydata(data, timeframe=tframes[args.timeframe], compression=args.compression)
示例 - 每天到每周重播
脚本的调用:
$ ./replay-example.py --timeframe weekly --compression 1
不幸的是,图表无法向我们展示后台发生的真实情况,所以让我们看一下控制台输出:
prenext len 1 - counter 1 prenext len 1 - counter 2 prenext len 1 - counter 3 prenext len 1 - counter 4 prenext len 1 - counter 5 prenext len 2 - counter 6 ... ... prenext len 9 - counter 44 prenext len 9 - counter 45 ---next len 10 - counter 46 ---next len 10 - counter 47 ---next len 10 - counter 48 ---next len 10 - counter 49 ---next len 10 - counter 50 ---next len 11 - counter 51 ---next len 11 - counter 52 ---next len 11 - counter 53 ... ... ---next len 51 - counter 248 ---next len 51 - counter 249 ---next len 51 - counter 250 ---next len 51 - counter 251 ---next len 51 - counter 252 ---next len 52 - counter 253 ---next len 52 - counter 254 ---next len 52 - counter 255
正如我们所见,内部self.counter
变量正在跟踪对prenext
或next
的每次调用。前者在应用的简单移动平均线产生一个值之前被调用。后者在简单移动平均线产生值时调用。
钥匙:
- 策略的长度 (len(self)) 每 5 个柱变化一次(一周中的 5 个交易日)
该策略有效地看到:
每周栏如何在 5 次拍摄中发展。
同样,这并不能复制市场的实际逐笔交易(甚至不是一分钟、一小时)的发展,但它比实际看到一根柱线要好。
视觉输出是每周图表的输出,这是系统再次测试的最终结果。
示例 2 - 每天到每天都有压缩
当然,“重播”可以应用于相同的时间范围,但需要进行压缩。
控制台:
$ ./replay-example.py --timeframe daily --compression 2 prenext len 1 - counter 1 prenext len 1 - counter 2 prenext len 2 - counter 3 prenext len 2 - counter 4 prenext len 3 - counter 5 prenext len 3 - counter 6 prenext len 4 - counter 7 ... ... ---next len 125 - counter 250 ---next len 126 - counter 251 ---next len 126 - counter 252 ---next len 127 - counter 253 ---next len 127 - counter 254 ---next len 128 - counter 255
这次我们得到了预期的一半,因为因素 2 要求压缩。
图表:
结论
重建市场发展是可能的。通常可以使用较小的时间范围数据集,并可用于离散地重放系统运行的时间范围。
测试脚本。
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 class SMAStrategy(bt.Strategy): params = ( ('period', 10), ('onlydaily', False), ) def __init__(self): self.sma = btind.SMA(self.data, period=self.p.period) def start(self): self.counter = 0 def prenext(self): self.counter += 1 print('prenext len %d - counter %d' % (len(self), self.counter)) def next(self): self.counter += 1 print('---next len %d - counter %d' % (len(self), self.counter)) def runstrat(): args = parse_args() # Create a cerebro entity cerebro = bt.Cerebro(stdstats=False) cerebro.addstrategy( SMAStrategy, # args for the strategy period=args.period, ) # Load the Data datapath = args.dataname or '../../datas/2006-day-001.txt' data = btfeeds.BacktraderCSVData(dataname=datapath) # Handy dictionary for the argument timeframe conversion tframes = dict( daily=bt.TimeFrame.Days, weekly=bt.TimeFrame.Weeks, monthly=bt.TimeFrame.Months) # First add the original data - smaller timeframe cerebro.replaydata(data, timeframe=tframes[args.timeframe], compression=args.compression) # Run over everything cerebro.run() # Plot the result cerebro.plot(style='bar') def parse_args(): parser = argparse.ArgumentParser( description='Pandas test script') parser.add_argument('--dataname', default='', required=False, help='File Data to Load') parser.add_argument('--timeframe', default='weekly', required=False, choices=['daily', 'weekly', 'monhtly'], help='Timeframe to resample to') parser.add_argument('--compression', default=1, required=False, type=int, help='Compress n bars into 1') parser.add_argument('--period', default=10, required=False, type=int, help='Period to apply to indicator') return parser.parse_args() if __name__ == '__main__': runstrat()