数据重播
原文: https://www.backtrader.com/blog/posts/2015-08-25-data-replay/data-replay/
时间一去不复返了,在一个完全成型的封闭酒吧中测试一个策略是好的,但它可能会更好。
这就是数据重播提供帮助的地方。如果:
- 该策略对时间范围为 X 的数据进行操作(例如:每日)
和
- 可获得较小时间段 Y(例如:1 分钟)的数据
数据重播的作用与名称的含义完全相同:
Replay a daily bar using the 1 minute data 
当然,这并不完全是市场发展的方式,但它远比孤立地看待每日完全成形和封闭的酒吧要好得多:
If the strategy operates in realtime during the formation of the daily bar,
the approximation of the formation of the bar gives a chance to replicate the
actual behavior of the strategy under real conditions 
将数据回放付诸实施遵循backtrader的常规使用模式
- 
加载数据源 
- 
将数据传递给 DataReplayer,这是另一个将在加载的数据馈送上工作的数据馈送
- 
将新的数据馈送传递给大脑 
- 
添加策略 
- 
并在禁用预载的情况下运行…*** 
笔记
重放数据时不支持预加载,因为每个条实际上都是实时构建的。
为了使用示例,将每周重播标准的 2006 年每日数据。这意味着:
- 
最终将有 52 家酒吧,每周一家 
- 
大脑将调用 prenext和next总共 255 次,这是每日酒吧的原始计数
诀窍:
- 
当形成一个周线时,策略的长度( len(self)将保持不变。
- 
每过一周,长度将增加一个 
下面是一些示例,但首先是加载数据并将其传递到重放层的测试脚本的示例……以及使用preload=False禁用预加载的run(强制)
 dataname=datapath)
    tframes = dict(
        daily=bt.TimeFrame.Days,
        weekly=bt.TimeFrame.Weeks,
        monthly=bt.TimeFrame.Months)
    # Handy dictionary for the argument timeframe conversion
    # Resample the data
    data_replayed = bt.DataReplayer(
        dataname=data,
        timeframe=tframes[args.timeframe],
        compression=args.compression)
    # First add the original data - smaller timeframe
    cerebro.adddata(data_replayed)
    # Run over everything
    cerebro.run(preload=False) 
示例-从每天重播到每周重播
脚本的调用:
$ ./data-replay.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-每日到每日压缩
当然,“重放”可以应用于相同的时间段,但需要压缩。
控制台:
$ ./data-replay.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/sample/2006-day-001.txt'
    data = btfeeds.BacktraderCSVData(
        dataname=datapath)
    tframes = dict(
        daily=bt.TimeFrame.Days,
        weekly=bt.TimeFrame.Weeks,
        monthly=bt.TimeFrame.Months)
    # Handy dictionary for the argument timeframe conversion
    # Resample the data
    data_replayed = bt.DataReplayer(
        dataname=data,
        timeframe=tframes[args.timeframe],
        compression=args.compression)
    # First add the original data - smaller timeframe
    cerebro.adddata(data_replayed)
    # Run over everything
    cerebro.run(preload=False)
    # 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() 



