• Backtrader中文笔记之CSV Data Feed Data


    Data - Multiple Timeframes

    Sometimes investing decisions are taken using different timeframes:

    有时候,投资策略采用不同的时间框架

    • Weekly to evaluate the trend

    • 每周的评估趋势
    • Daily to execute the entry

    • 每天执行录入

    Or 5 minutes vs 60 minutes.

    或者5分钟对比60分钟

    That implies that combining datas of multiple timeframes in backtrader is needed to support such combinations.

    这意味着需要在backtrader中组合多个时间段的数据来支持这种组合。

    Native support for it is already built-in. The end user must only follow these rules:

    它的平台支持已经是内置的。终端用户必须遵守以下规则:

    • The data with the smallest timeframe (and thus the larger number of bars) must be the 1st one to be added to the Cerebro instance

    • 具有最小时间框架的数据(因此条数更多)必须是第一个添加到Cerebro实例的数据
    • The datas must be properly date-time aligned for the platform to make any sense out of them

    Beyond that, the end-user is free to apply indicators as wished on the shorter/larger timeframes. Of course:

    数据必须正确地对齐日期-时间,以便平台能够理解它们

    除此之外,终端用户可以自由地在较短/较大的时间框架上应用指示符。当然,

    • Indicators applied to larger timeframes will produce less bars
    • 应用于较大时间框架的指标将产生较少的bars

    The platform will also have the following into account

    该平台还将考虑以下因素

    • The minimum period for larger timeframes
    • 大时间框架的最小周期

    Minimum period which will probably have the side effect of having to consume several orders of magnitude of the smaller timeframe bars before a Strategy added to Cerebro kicks into action.

    最小时间周期,这可能会有副作用,在大脑的策略开始行动之前,必须消耗几个数量级的小时间框架。

    The built-in cerebro.resample is going to be used to create a larger timeframe.

    内置cerebro.resample将用于创建更大的时间框架。

    Some examples below, but first the sauce of the test script.

    下面是一些示例,但首先是测试脚本。

        # Load the Data
        datapath = args.dataname or '../../datas/2006-day-001.txt'
        data = btfeeds.BacktraderCSVData(dataname=datapath)
        cerebro.adddata(data)  # First add the original data - smaller timeframe
    
        tframes = dict(daily=bt.TimeFrame.Days, weekly=bt.TimeFrame.Weeks,
                       monthly=bt.TimeFrame.Months)
    
        # Handy dictionary for the argument timeframe conversion
        # Resample the data
        if args.noresample:
            datapath = args.dataname2 or '../../datas/2006-week-001.txt'
            data2 = btfeeds.BacktraderCSVData(dataname=datapath)
            # And then the large timeframe
            cerebro.adddata(data2)
        else:
            cerebro.resampledata(data, timeframe=tframes[args.timeframe],
                                 compression=args.compression)
    
        # Run over everything
        cerebro.run()
    
        # Load the Data
        datapath = args.dataname or '../../datas/2006-day-001.txt'
        data = btfeeds.BacktraderCSVData(dataname=datapath)
        cerebro.adddata(data)  # First add the original data - smaller timeframe
    
        tframes = dict(daily=bt.TimeFrame.Days, weekly=bt.TimeFrame.Weeks,
                       monthly=bt.TimeFrame.Months)
    
        # Handy dictionary for the argument timeframe conversion
        # Resample the data
        if args.noresample:
            datapath = args.dataname2 or '../../datas/2006-week-001.txt'
            data2 = btfeeds.BacktraderCSVData(dataname=datapath)
            # And then the large timeframe
            cerebro.adddata(data2)
        else:
            cerebro.resampledata(data, timeframe=tframes[args.timeframe],
                                 compression=args.compression)
    
        # Run over everything
        cerebro.run()
    

    The steps:

    步骤

    • Load a data

    • 记在数据
    • Resample it according to the user specified arguments

      The script also allows for loading a 2nd data

    • 根据用户指定的参数重新取样

      该脚本还允许加载第二个数据
    • Add the data to cerebro

    • 将数据添加到cerebro
    • Add the resampled data (larger timeframe) to cerebro

    • 将重新采样的数据(更大的时间框架)添加到cerebro
    • run

    Example 1 - Daily and Weekly

    The invocation of the script:

    $ ./multitimeframe-example.py --timeframe weekly --compression 1
    

     

    Example 2 - Daily and Daily Compression (2 bars to 1)

    The invocation of the script:

    $ ./multitimeframe-example.py --timeframe daily --compression 2
    

     And the output chart:

    Example 3 - Strategy with SMA

    Although plotting is nice, the key issue here is showing how the larger timeframe influences the system, especially when it comes down to the starting point

    虽然绘制很好,但这里的关键问题是显示较大的时间框架如何影响系统,特别是当它到达起点时

    The script can take a --indicators to add a strategy which creates simple moving averages of period 10 on the smaller an larger timeframe datas.

    脚本可以采用—指标来添加一个策略,该策略在较小的时间段数据上创建10期的简单移动平均线。

    If only the smaller timeframe was taken into account:

    如果只考虑较小的时间框架:

    • next would be called first after 10 bars, which is the time the Simple Moving Average needs to produce a value

    • next将在10个bar之后首先调用,这是简单移动平均值产生值所需的时间

      NOTE: Remember that Strategy monitors created indicators and only calls next when all indicators have produced a value. The rationale is that the end user has added the indicators to use them in the logic and thus no logic should take place if the indicators have produced no values

    • 注意:记住,策略监视创建了指标,只有当所有指标都产生了值时才会调用next。其基本原理是,最终用户添加了指标以在逻辑中使用它们,因此,如果指标没有产生任何值,则不应产生逻辑

    But in this case the larger timeframe (weekly) delays the invocation of next until the Simple Moving Average oon the weekly data has produced a value, which takes … 10 weeks.

    但在这种情况下,较大的时间范围(每周)会延迟next的调用,直到每周数据的简单移动平均值产生值,这需要…10周

    The script overrides nextstart which is only called once and which defaults to calling next to show when it is first called.

    该脚本覆盖只调用一次的nextstart,它默认在第一次调用时调用next来显示。

    Invocation 1:

    Only the smaller timeframe, daily, gets a Simple Moving Average

    只选择小时间框架日线,取得平均线

    The command line and output

    $ ./multitimeframe-example.py --timeframe weekly --compression 1 --indicators --onlydaily
    --------------------------------------------------
    nextstart called with len 10
    --------------------------------------------------
    

     And the chart.

    Invocation 2:

    Both timeframes get a Simple Moving Average

    The command line:

    $ ./multitimeframe-example.py --timeframe weekly --compression 1 --indicators
    --------------------------------------------------
    nextstart called with len 50
    --------------------------------------------------
    --------------------------------------------------
    nextstart called with len 51
    --------------------------------------------------
    --------------------------------------------------
    nextstart called with len 52
    --------------------------------------------------
    --------------------------------------------------
    nextstart called with len 53
    --------------------------------------------------
    --------------------------------------------------
    nextstart called with len 54
    --------------------------------------------------
    

    Two things to notice here:

    这里需要注意两件事:

    • Instead of being called after 10 periods, the strategy is 1st called after 50 periods.

    • 策略不是在10个周期之后调用,而是在50个周期之后第一次调用。
    • It is so because the Simple Moving Average applied on the larger (weekly) timeframe produces a value after 10 weeks … and that is 10 weeks * 5 days / week … 50 days

    • 之所以如此,是因为应用于较大(周)时间框架的简单移动平均线在10周后会产生一个值,即10周* 5天/周…50天
    • nextstart gets called 5 times rather than only 1.

    • nextstart被调用5次,而不是只有1次。
    • This is a natural side effect of having mixed the timeframe and having (in this case only one) indicators applied to the larger timeframe.

    • 这是混合时间框架和应用于更大时间框架的指标(在本例中只有一个)的自然副作用。
    • The larger timeframe Simple Moving Average produces 5 times the same value whilst 5 daily bars are being consumed.

    • 更大的时间框架简单移动平均线产生5倍的相同的价值,而5条每天被消耗。
    • And because the start of the period is being controlled by the larger timeframe nextstart gets called 5 times.

    • 因为周期的开始是由更大的时间框架控制的,所以nextstart被调用5次。

    And the chart.

    经过测试就算第二个导入了周线数据,在画第二个周线数据的时候,还是会5次调用nextstart很不能理解。

    还有就是当开始画SMA之后--compression参数就失效了,实例代码中的图也有问题,我这里compression参数变大,大周期的周期就变大了,但案例中是变小

    Conclusion

    Multiple Timeframe Datas can be used in backtrader with no special objects or tweaking: just add the smaller timeframes first.

    多个时间段数据可以在backtrader中使用,不需要特殊的对象或调整:只需先添加较小的时间段。

    The test script.

    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_small_tf = btind.SMA(self.data, period=self.p.period)
            if not self.p.onlydaily:
                self.sma_large_tf = btind.SMA(self.data1, period=self.p.period)
    
        def nextstart(self):
            print('--------------------------------------------------')
            print('nextstart called with len', len(self))
            print('--------------------------------------------------')
    
            super(SMAStrategy, self).nextstart()
    
    
    def runstrat():
        args = parse_args()
    
        # Create a cerebro entity
        cerebro = bt.Cerebro(stdstats=False)
    
        # Add a strategy
        if not args.indicators:
            cerebro.addstrategy(bt.Strategy)
        else:
            cerebro.addstrategy(
                SMAStrategy,
    
                # args for the strategy
                period=args.period,
                onlydaily=args.onlydaily,
            )
    
        # Load the Data
        datapath = args.dataname or '../../datas/2006-day-001.txt'
        data = btfeeds.BacktraderCSVData(dataname=datapath)
        cerebro.adddata(data)  # First add the original data - smaller timeframe
    
        tframes = dict(daily=bt.TimeFrame.Days, weekly=bt.TimeFrame.Weeks,
                       monthly=bt.TimeFrame.Months)
    
        # Handy dictionary for the argument timeframe conversion
        # Resample the data
        if args.noresample:
            datapath = args.dataname2 or '../../datas/2006-week-001.txt'
            data2 = btfeeds.BacktraderCSVData(dataname=datapath)
            # And then the large timeframe
            cerebro.adddata(data2)
        else:
            cerebro.resampledata(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='Multitimeframe test')
    
        parser.add_argument('--dataname', default='', required=False,
                            help='File Data to Load')
    
        parser.add_argument('--dataname2', default='', required=False,
                            help='Larger timeframe file to load')
    
        parser.add_argument('--noresample', action='store_true',
                            help='Do not resample, rather load larger timeframe')
    
        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('--indicators', action='store_true',
                            help='Wether to apply Strategy with indicators')
    
        parser.add_argument('--onlydaily', action='store_true',
                            help='Indicator only to be applied to daily timeframe')
    
        parser.add_argument('--period', default=10, required=False, type=int,
                            help='Period to apply to indicator')
    
        return parser.parse_args()
    
    
    if __name__ == '__main__':
        runstrat()
    
  • 相关阅读:
    Uva11235
    Uva11300/BZOJ1045/BZOJ1465/BZOJ3292
    树形背包模板
    Miller-Rabin素性测试
    BZOJ1500 : [NOI2005]维修数列-fhq_Treap
    COGS2421 [HZOI 2016]简单的Treap
    用 fhq_Treap 实现可持久化平衡树
    hdu 1010(DFS) 骨头的诱惑
    hdu 1026(BFS+输出路径) 我要和怪兽决斗
    hdu 1072(BFS) 有炸弹
  • 原文地址:https://www.cnblogs.com/sidianok/p/13490713.html
Copyright © 2020-2023  润新知