Backtrader教程:数据馈送 - 多个时间帧

  |  

有时投资决策是使用不同的时间框架做出的:

  • 每周评估趋势

  • 每天运行条目

或者5分钟对60分钟。

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

对它的本机支持已经内置。最终用户只能遵循以下规则:

  • 具有最小时间帧(因此柱数较大的数据)必须是要添加到Cerebro实例中的第1个数据

  • 数据必须正确对齐日期时间,以便平台从中产生任何意义

除此之外,最终用户可以自由地在较短/较长的时间范围内按预期应用指针。答案是肯定的:

  • 应用于较大时间帧的指针将产生较少的柱线

该平台还将考虑以下因素

  • 较大时间帧的最小周期

最小周期,这可能会产生副作用,即在将策略添加到 Cerebro 开始行动之前,必须消耗几个数量级的较小时间帧柱。

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

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

    # 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()

步骤:

  • 加载数据

  • 根据用户指定的参数对其进行重新采样

    该脚本还允许加载第 2 个 数据

  • 将数据添加到 cerebro

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

示例 1 - 每日和每周

文稿的调用:

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

和输出图表:

范例 2 - 每日和每日压缩(2 个 bar 到 1)

文稿的调用:

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

和输出图表:

范例 3 - 使用 SMA 的策略

虽然绘图很好,但这里的关键问题是显示更大的时间框架如何影响系统,特别是当它归结为起点时。

该脚本可以添加--indicators 一个策略,该策略在较小和较大的时间帧数据上创建 周期为10 的简单移动平均线。

如果只考虑较小的时间范围:

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

    注意:请记住,Strategy 监控已创建的指针,并且仅在所有指针都生成值时才调用 next 。基本原理是最终用户已添加指针以在逻辑中使用它们,因此,如果指针未生成任何值,则不应发生任何逻辑。

但是在这种情况下,较大的时间帧(每周)延迟调用next ,直到每周数据产生一个值的简单移动平均线,这需要...10周。

该脚本将nextstart 覆盖仅调用一次且缺省为调用 next 以显示首次调用时的脚本。

调用 1:

只有较小的时间帧,每天,得到一个简单的移动平均线

命令 line 和输出

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

和图表。

调用 2:

两个时间帧都得到一个简单的移动平均线

命令 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
--------------------------------------------------

这里要注意两件事:

  • 该策略不是在10 个周期后调用,而是在50个周期后调用1st

    之所以如此,是因为应用于较大(每周)时间帧的简单移动平均线在10周后产生一个值......那就是10 weeks * 5 days / week … 50 days

  • nextstart 被调用 5 次,而不仅仅是 1 次。

    这是混合时间帧并将指针(在本例中只有一个)应用于较大时间帧的自然副作用。

    较大的时间帧简单移动平均线产生相同值的 5 倍,而 5 个日柱线被消耗。

    而且由于周期的开始被较大的时间帧nextstart 控制,因此被调用了5次。

和图表。

结论

多个时间帧数据可以在没有特殊对象或调整的情况下使用backtrader :只需先添加较小的时间帧即可。

测试脚本。

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()

推荐阅读

相关文章

Backtrader按日线交易

似乎在世界某个地方有一种权益(Interest)可以总结如下: 使用每日柱线引入订单,但使用开盘价 这来自工单#105订单执行逻辑与当前数据和#101动态投注计算中的对话 backtrader 尝试尽可能保持现实,并且在处理每日柱线时适用以下前提: 当每日柱被评估时,柱线已经结束 这是有道理的,

Backtrader佣金计划

backtrader 的诞生是出于必要。我自己的...有一种感觉,我控制着自己的回溯测试平台,可以尝试新的想法。但是,在这样做并且从一开始就完全 open 采购它时,很明显它必须有一种方法来满足他人的需求和愿望。 作为未来的交易者,我本可以选择基于点的计算和每轮佣金的固定价格,但这将是一个错误。

Backtrader教程:经纪人 - 开仓作弊

“发布”1.9.44.116 添加了对 Cheat-On-Open的支持。这似乎是那些全力以赴的人的需求功能,他们在酒吧 close 后进行了计算,但希望与 open 价格相匹配。 当开盘价跳空(上涨或下跌,取决于是否buysell有效)并且现金不足以进行全面运营时,这样的用例就会失败。这将强制代理拒绝该操作。

Backtrader教程:指针 - 开发

如果必须开发任何东西(除了一个或多个获胜策略之外),那么这个东西就是一个自定义指针。 根据作者的说法,平台内的这种开发很容易。 需要满足以下条件: 从指针派生的类(直接或从现有的子类派生) 定义它将保持lines 指针必须至少具有 1 line。

Backtrader教程:操作平台

Line 反复运算器 为了参与操作,plaftorm使用 line 反复运算器的概念。它们已经松散地模仿了Python的反复运算器,但实际上与它们无关。 策略和指针是 line 反复运算器。

BacktraderPyFolio 集成

注意 2017年2月 pyfolio API 已更改,不再 create_full_tear_sheet 具有 gross_lev 作为命名参数的参数。

Backtrader回溯

在一些关于改进的ShapeRatio的提示之后, backtrader 已将此分析仪添加到其武器库中。 文献位于: 从对数回报的好处开始,并遵循在SharpeRatio方程的分母中具有标准偏差的副作用,本文档开发了该分析仪的公式和期望。

Backtrader教程:Cerebro - 优化 - 改进

backtrader版本1.8.12.99改进了在多处理过程中管理data feeds和结果的方式。

Backtrader信贷利息

在某些情况下,真实经纪人的现金金额可能会减少,因为资产操作包括利率。例子: 卖空股票 交易所买卖基金包括多头和空头 这意味着不仅交易构成了系统的盈利能力,因为信贷上的利息在帐户上佔有一席之地。 为了涵盖这种情况, backtrader 包括(从发佈1.8.8.96开始)功能来考虑这一点。

Backtrader动量策略

在另一篇伟大的文章中,泰迪·科克(Teddy Koker)再次展示了算法交易策略的发展之路: 研究优先应用 pandas 回溯测试,然后使用 backtrader 荣誉!!! 该帖子可以在以下位置找到: 泰迪·科克(Teddy Koker)给我留言,问我是否可以评论 backtrader的用法。