Backtrader教程:操作平台

  |  

Line 反复运算器

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

策略和指针是 line 反复运算器。

line反复运算器概念试图描述以下内容:

  • Line反复运算器踢从line反复运算器,告诉他们反复运算

  • 然后, Line 反复运算器循环访问其自己声明的命名 lines 设置值

反复运算的关键,就像常规的Python迭代器一样,是:

  • 方法next

    它将在每次反复运算时调用。datasline反复运算器具有并用作逻辑/计算基础的数组已经被平台移动到下一个索引(数据重放除外)

    在满足line反复运算器的最小周期时调用。下面对此进行更多介绍。

但是由于它们不是常规反复运算器,因此存在两种其他方法:

  • prenext

    在满足line反复运算器“的最小期限之前调用。

  • nextstart

    在满足line反复运算器“的最小周期时正好调用一次

    默认行为是将调用next转接到,但如果需要,当然可以覆盖。

指针的额外方法

为了加快操作速度,指针支持批处理操作模式,该模式被称为 runonce。它不是严格需要的(一next 种方法就足够了),但它大大减少了时间。

runonce 方法规则使索引为 0 的 get/set 点失效,并依赖于对保存数据的基础数组的直接访问,并为每个状态传递正确的索引。

定义的方法遵循下一个族的命名:

  • once(self, start, end)

    在达到最小期限时调用。内部数字必须在开始和结束之间进行处理,从内部数字的开始开始为零

  • preonce(self, start, end)

    在达到最小期限之前调用。

  • oncestart(self, start, end)

    在满足最小期限时正好调用一次

    默认行为是将调用once转接到,但如果需要,当然可以覆盖。

最短期限

一张图片胜过千言万语,在这种情况下,也可能是一个例子。一个简单的移动Average能够解释它:

class SimpleMovingAverage(Indicator):
    lines = ('sma',)
    params = dict(period=20)

    def __init__(self):
        ...  # Not relevant for the explanation

    def prenext(self):
        print('prenext:: current period:', len(self))

    def nextstart(self):
        print('nextstart:: current period:', len(self))
        # emulate default behavior ... call next
        self.next()

    def next(self):
        print('next:: current period:', len(self))

实例化可能如下所示:

sma = btind.SimpleMovingAverage(self.data, period=25)

简要说明:

  • 假设传递到移动平均线的数据是标准 data feed 其缺省周期是1data feed 产生一个没有初始延迟的柱。

  • 然后,“period=25” 实例化移动平均线将调用其方法,如下所示:

    • prenext 24 次

    • nextstart 1次(依次通话 next

    • next 再增加 n 次,直到 data feed 用尽

让我们来看看杀手级指针:一个 SimpleMovingAverage over 另一个 SimpleMovingAverage。实例化可能如下所示:

sma1 = btind.SimpleMovingAverage(self.data, period=25)

sma2 = btind.SimpleMovingAverage(sma1, period=20)

现在发生了什么:

  • 同上sma1

  • sma2 正在接收一个 data feed ,其最短期限为25,这是我们 sma1 ,因此

  • 这些sma2 方法的调用方式如下:

    • prenext 前 25 + 18 次,共 43 次

    • 25次让sma1 其产生1st 合理值

    • 18次累积额外sma1 价值

    • 总共 19 个值(25 次调用后为 1,之后为 18 次)

    • nextstart 然后1次(依次调用 next

    • next 再增加 n 次,直到 data feed 用尽

当系统已经处理了 44 根柱线时,平台正在调用next

最小周期已根据传入数据自动调整。

策略和指针遵循以下行为:

  • 仅当达到自动计算的最小周期时,才会 next 调用(除了对 nextstart) 的初始钩子调用

注意

相同的规则适用于preonceoncestart运行批处理操作模式,once

注意

可以操纵最小周期 行为,但不建议这样做。是否希望在策略或指针中使用该 setminperiod(minperiod) 方法

启动并运行

启动与运行至少涉及3个 Lines 对象:

  • Data feed

  • 策略(实际上是从策略派生的类)

  • Cerebro (西班牙文中的大脑)

Data Feeds

显然,这些对象提供的数据将通过应用计算(直接和/或指针)进行回溯测试

该平台提供了几个 data feeds

  • 几种 CSV 格式和一个通用 CSV 阅读器

  • 雅虎在线获取器

  • 支持接收熊猫数据帧和火焰对象

  • 与Interacive Brokers,Visual Chart和Oanda进行即时Data Feeds

该平台对 data feed 的内容(例如时间帧和压缩)不做任何假设。这些值与名称一起可以提供,用于提供信息和高级操作,例如 Data Feed 重新采样(例如,将5分钟的 Data Feed 转换为每日 Data Feed

设置雅虎财经 Data Feed的示例:

import backtrader as bt
import backtrader.feeds as btfeeds

...

datapath = 'path/to/your/yahoo/data.csv'

data = btfeeds.YahooFinanceCSVData(
    dataname=datapath,
    reversed=True)

显示 Yahoo 的可选reversed 参数,因为直接从 Yahoo 下载的 CSV 档以最晚的日期开头,而不是以最旧的日期开头。

如果您的数据跨越了较大的时间范围,则可以按如下方式限制实际加载的数据:

data = btfeeds.YahooFinanceCSVData(
    dataname=datapath,
    reversed=True
    fromdate=datetime.datetime(2014, 1, 1),
    todate=datetime.datetime(2014, 12, 31))

如果 data feed中存在,则起始日期和截止日期都将包括在内。

如前所述,可以添加压缩和名称:

data = btfeeds.YahooFinanceCSVData(
    dataname=datapath,
    reversed=True
    fromdate=datetime.datetime(2014, 1, 1),
    todate=datetime.datetime(2014, 12, 31)
    timeframe=bt.TimeFrame.Days,
    compression=1,
    name='Yahoo'
   )

如果绘制了数据,则将使用这些值。

策略(派生)类

注意

在继续之前,对于更简化的方法,如果不希望对策略进行子类化,请查看文档的“信号”部分。

使用该平台的任何人都的目标是回溯测试数据,这是在策略(派生类)内完成的。

有2种方法至少需要自定义:

  • __init__

  • next

在初始化期间,将创建数据和其他计算的指示器,以便为以后应用逻辑做好准备。

稍后调用下一个方法来为数据的每个条形应用逻辑。

注意

如果传递了不同时间帧的data feeds(因此传递了next不同的柱计数),则将为主数据调用方法(传递给cerebro的第一个,见下文),该方法必须是具有较小时间帧的数据

注意

如果使用数据重播功能,则在next 重放柱的开发时,将为同一柱线多次调用该方法。

基本策略派生类:

class MyStrategy(bt.Strategy):

    def __init__(self):

        self.sma = btind.SimpleMovingAverage(self.data, period=20)

    def next(self):

        if self.sma > self.data.close:
            self.buy()

        elif self.sma < self.data.close:
            self.sell()

策略还有其他可以覆盖的方法(或挂钩点):

class MyStrategy(bt.Strategy):

    def __init__(self):

        self.sma = btind.SimpleMovingAverage(self.data, period=20)

    def next(self):

        if self.sma > self.data.close:
            submitted_order = self.buy()

        elif self.sma < self.data.close:
            submitted_order = self.sell()

    def start(self):
        print('Backtesting is about to start')

    def stop(self):
        print('Backtesting is finished')

    def notify_order(self, order):
        print('An order new/changed/executed/canceled has been received')

startstop 方法应该是不言自明的。正如预期的那样,在打印函数中的文本之后,notify_order当策略需要通知时,将调用该方法。用例:

  • 请求买入或卖出(如下图所示)

    买入/卖出将返回提交给经纪商的订单。保留对此提交订单的引用由调用方决定。

    例如,它可用于确保在订单仍处于待处理状态时不会提交新订单。

  • 如果订单被接受/运行/取消/更改,经纪人将通过 notify 方法将状态更改(例如运行大小)通知回策略

快速入门指南在该方法中notify_order 提供了订单管理的完整功能示例。

其他策略类可以做更多任务作:

  • buy / sell / close

    使用基础经纪商和 sizer 向经纪商发送买入/卖出订单

    同样可以通过手动创建订单并将其传递给经纪人来完成。但该平台旨在使使用它的人变得容易。

    close 将获得当前的市场地位并立即 close

  • getposition (或属性“位置”)

    返回当前市场位置

  • setsizer/getsizer (或财产“sizer”)

    这些允许设置/获取标的权益 Sizer。可以对照 Sizers 检查相同的逻辑,这些为相同情况提供不同的赌注(固定大小,与资本成比例,指数)

    有很多文学作品,但Van K. Tharp有关于这个主题的优秀书籍。

策略是一个 Lines 对象和这些支持参数,这些参数是使用标准的 Python kwargs 参数收集的:

class MyStrategy(bt.Strategy):

    params = (('period', 20),)

    def __init__(self):

        self.sma = btind.SimpleMovingAverage(self.data, period=self.params.period)

    ...
    ...

请注意,不再SimpleMovingAverage 使用固定值 20 实例化 ,而是使用为策略定义的参数“period” 实例化。

Cerebro

一旦 Data Feeds 可用并且定义了战略, Cerebro 实例就是将所有内容集成在一起并运行操作。实例化一个很容易:

cerebro = bt.Cerebro()

如果不希望有任何特殊情况,则缺省会处理。

  • 创建缺省代理

  • 无佣金

  • Data Feeds 将被预加载

  • 默认运行模式为runonce(批处理操作),这是更快的

    所有指针必须支持runonce 全速模式。平台中包含的那些确实如此。

    自定义指针不需要实现 runonce 功能。Cerebro 将模拟它,这意味着那些与runonce不兼容的指针将运行得更慢。但是,大多数系统仍将以批处理模式运行。

由于 Data feed 已经可用,并且策略也(更早创建)将其放在一起并使其启动并运行的标准方法是:

cerebro.adddata(data)
cerebro.addstrategy(MyStrategy, period=25)
cerebro.run()

请注意以下几点:

  • 添加了 Data Feed “实例”

  • MyStrategy“类”与将传递给它的参数(kwargs)一起添加。

    MyStrategy的实例化将由后台 cerebro 完成,并且“addstrategy”中的任何kwargs都将传递给它。

用户可以根据需要添加任意数量的策略和 Data Feeds 。策略如何相互沟通以实现协调(如果愿意的话)不受平台的运行/限制。

当然, Cerebro 还提供了更多的可能性:

  • 确定预加载与操作模式:

    cerebro = bt.Cerebro(runonce=True, preload=True)
    

    这里有一个约束:runonce 需要预加载(如果没有,则无法运行批处理操作)当然,预加载 Data Feeds 不会强制 runonce

  • setbroker / getbroker (和经纪人财产)

    如果需要,可以设置自定义代理。也可以访问实际的代理实例

  • 标图。在正常情况下,就像这样简单:

    cerebro.run()
    cerebro.plot()
    

    plot 为自定义取一些参数

    • numfigs=1

      如果情节太密集,可能会分解为几个情节

    • plotter=None

      可以传递客户绘图仪实例,并且 cerebro 不会实例化默认绘图仪实例

    • **kwargs - 标准关键字参数

      这将传递给绘图仪。

    有关详细信息,请参阅绘图部分。

  • 策略优化。

    如上所述, Cerebro 获取一个 Strategy 派生类(不是实例)和关键字参数,这些参数将在实例化时传递给它,这将在调用“run”时发生。

    这是为了实现优化。同一个 Strategy 类将根据需要使用新参数实例化多次。如果实体已传递给 cerebro ...这是不可能的。

    优化请求如下:

    cerebro.optstrategy(MyStrategy, period=xrange(10, 20))
    

    该方法optstrategy 具有与相同的签名, addstrategy 但会运行额外的内务处理,以确保优化按预期运行。策略可能期望一个范围作为策略的正常参数,并且 addstrategy 不会对传递的参数做出任何假设。

    另一方面,optstrategy 将理解可反复运算是一组值,必须按顺序传递给 Strategy 类的每个实例化。

    请注意,传递的值范围不是单个值。在这个简单的情况下,将为此策略尝试 10 个值 10 -> 19(20 是上限)。

    如果使用额外的参数开发更复杂的策略,则可以将它们全部传递给选择策略。不得进行优化的参数可以直接传递,而无需最终用户创建一个仅可反复运算一个值的虚拟参数。例:

    cerebro.optstrategy(MyStrategy, period=xrange(10, 20), factor=3.5)
    

    optstrategy 方法看到因数,并在后台为具有单个元素的因数创建(所需的)可反复运算的虚拟(在示例 3.5 中)

    注意

    交互式Python shell和Windows下某些类型的冻结可运行档在Pythonmultiprocessing 模块中存在问题

    请阅读 Python 文档multiprocessing

推荐阅读

相关文章

Backtrader按日线交易

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

Backtrader教程:安装

要求和版本 backtrader 是独立的,没有外部依赖关系(除非要绘图) 基本要求是: Python 2.7 Python 3.2 / 3.3/ 3.4 / 3.5 pypy/pypy3 如果需要绘图,则其他要求: Matplotlib >= 1.4.

Backtrader期货补偿与现货补偿

版本1.9.32.116 增加了对社区中呈现的有趣用例 的支持 以期货开始交易,包括实物交割 让一个指针告诉你一些事情 如果需要, close 现货价格操作,有效地取消实物交割,无论是为了接收货物还是为了必须交付货物(并希望获利)来头寸。

Backtrader教程:操作平台

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

Backtrader教程:日志记录 - 编写器

将以下内容写出到流中: csv 流,

Backtrader教程:数据馈送 - 扩展(Extending DataFeed)

GitHub 中的问题实际上是在推动文档部分的完成,或者説明我了解我是否backtrader 具有我从一开始就设想的易用性和灵活性以及在此过程中做出的决定。 在本例中为问题 #9。

Backtrader跨越数字

《backtrader》的发布1.9.27.105纠正了一个疏忽。这是一个疏忽,因为拼图的所有部分都已到位,但启动并不是在所有角落都进行的。 该机制使用一个名为的属性_mindatas,因此让我们将其称为: mindatas。 社区问了这个问题,答案并不是很到位。

数据多时间帧

有时投资决策是使用不同的时间框架做出的: 每周评估趋势 每天执行条目 或者5分钟对60分钟。 这意味着需要将多个时间帧的数据组合在 backtrader 中以支援此类组合。 对它的本机支持已经内置。

Backtrader教程:分析仪 - PyFolio

注意 从(至少)2017-07-25pyfolio 开始,API已更改,不再 create_full_tear_sheet 具有 gross_lev 作为命名参数的参数。

Backtrader信贷利息

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