Cerebro

此类是backtrader的基石,因为它是以下方面的中心点:

  1. 收集所有输入(数据馈送) 、演员(策略)、观众(观察者)、评论家(分析者)和记录者(作家),确保节目随时继续进行。
  2. 执行回测/或实时数据馈送/交易
  3. 返回结果
  4. 允许使用绘图设施

收集输入

1、首先创建一个cerebro

cerebro = bt.Cerebro(**kwargs)

支持一些**kwargs控制执行,请参阅参考(稍后可以将相同的参数应用于run方法)

2、添加数据提要

最常见的模式是cerebro.adddata(data),其中已经实例化data了 数据馈送。例子:

data = bt.BacktraderCSVData(dataname='mypath.days', timeframe=bt.TimeFrame.Days)
cerebro.adddata(data)

重新采样重放数据是可能的,并且遵循相同的模式:

data = bt.BacktraderCSVData(dataname='mypath.min', timeframe=bt.TimeFrame.Minutes)
cerebro.resampledata(data, timeframe=bt.TimeFrame.Days)

data = bt.BacktraderCSVData(dataname='mypath.min', timeframe=bt.TimeFrame.Minutes)
cerebro.replaydatadata(data, timeframe=bt.TimeFrame.Days)

系统可以接受任意数量的数据馈送,包括将常规数据与重新采样和/或重放数据混合。当然,其中一些组合肯定毫无意义,并且为了能够组合数据而应用了一个限制:时间对齐。请参阅数据 – 多个时间范围、数据重采样 – 重采样和数据 – 重播部分。

3、添加Strategies

datas feeds已经是类的实例不同, cerebro它直接接受Strategy类和传递给它的参数。背后的基本原理:在优化场景中,该类将被实例化多次并传递不同的参数

即使没有运行优化,该模式仍然适用:

cerebro.addstrategy(MyStrategy, myparam1=value1, myparam2=value2)

优化时,必须将参数添加为可迭代对象。有关详细说明,请参阅 优化部分。基本模式:

cerebro.optstrategy(MyStrategy, myparam1=range(10, 20))

它将运行MyStrategy10 次,myparam1取值从 10 到 19(请记住 Python 中的范围是半开的,20不会达到)

4、其他元素

还可以添加一些其他元素来增强回测体验。请参阅相应的部分。方法是:

    • addwriter
    • addanalyzer
    • addobserver(或addobservermulti

5、更换经纪人

Cerebro 将使用 中的默认代理backtrader,但这可以被覆盖:

broker = MyBroker()
cerebro.broker = broker  # property using getbroker/setbroker methods

6、接收通知

如果数据馈送和/或代理发送通知(或创建它们的商店提供者),它们将通过该 Cerebro.notify_store方法接收。可通过三 (3) 种方式处理这些通知

  • 通过调用向实例 添加回调。回调必须支持此签名:cerebroaddnotifycallback(callback)
callback(msg, *args, **kwargs)

actualmsg和received 是实现定义的(完全取决于data/broker/store*args ) ,但通常人们应该期望它们是可打印的,以允许接收和实验。**kwargs

  • 覆盖添加到实例notify_store的子类中的方法。Strategycerebro

签名:notify_store(self, msg, *args, **kwargs)

  • 子类Cerebro和覆盖notify_store(与 中的签名相同Strategy

这应该是最不受欢迎的方法。

执行回测

有一个方法可以做到,但它支持几个选项(也可以在实例化时指定)来决定如何运行:

result = cerebro.run(**kwargs)

请参阅下面的参考以了解哪些参数可用。

标准观察员

cerebro(除非另有说明)自动实例化三个 标准观察者

  • 跟踪和(投资组合)的经纪人观察者cashvalue
  • 交易观察员应该显示每笔交易的有效性
  • 应记录操作何时执行的买入/卖出观察者

如果希望更清洁的绘图只需禁用它们stdstats=False

返回结果

cerebro返回它在回测期间创建的策略的实例。这允许分析他们做了什么,因为策略中的所有元素都是可访问的:

result = cerebro.run(**kwargs)

result返回的格式run将根据是否使用优化而有所不同 (添加了策略optstrategy):

  • 添加的所有策略addstrategyresult将是list在回测期间运行的实例之一
  • 添加了 1 个或多个策略optstrategyresult将是一个listlist每个内部列表将包含每次优化运行后的策略

Tips:优化的默认行为已更改为仅返回系统中存在的分析器,以使跨计算机内核的消息传递更轻松。

如果希望完整的策略集作为返回值,请将参数设置optreturnFalse

允许使用绘图设施

作为一个额外的 ifmatplotlib安装,可以绘制策略。通常的模式是:

cerebro.plot()

请参阅下面的参考和绘图部分

回测逻辑

事物流程的简要概述:

  1. 传递任何商店通知
  2. 询问数据馈送以提供下一组报价/柱Versionchanged:在 1.9.0.99 版中更改:新行为

    通过查看日期时间来同步数据馈送,该日期时间将由可用的数据馈送提供。在新时期未交易的馈送仍提供旧数据点,而具有可用新数据的数据馈送提供这一点(连同指标的计算)

    旧行为oldsync=True(与Cerebro一起使用时保留)

    插入系统的第一个数据是并且系统datamaster将等待它传递一个滴答声

    其他数据馈送或多或少是datamaster 和:

    * 如果下一个要
       交付的报价比“数据管理员”交付的报价新(按日期时间),它将不会被交付
    
    * 由于多种原因,可能会在不交付新报价的情况下返回

    该逻辑旨在轻松同步多个数据馈送和具有不同时间范围的数据馈送

  3. 通知策略关于订单、交易和现金/价值的排队经纪人通知
  4. 告诉经纪人接受排队订单并使用新数据执行挂单
  5. 调用策略的next方法让策略评估新数据(并可能发出在代理中排队的订单)根据可能处于prenextnextstart在满足策略/指标的最短周期要求之前的阶段

    在内部,这些策略还将踢出observers、 indicatorsanalyzers 其他活动元素

  6. 告诉任何writers人将数据写入其目标

需要考虑的重要事项:

Tips: 在1上述步骤中,当数据馈送提供新的一组柱时,这些柱是关闭的。这意味着数据已经发生。

因此, step 中的策略发出的订单4无法使用 step 中的数据执行1

这意味着订单将以 的概念执行x + 1x执行订单的柱时刻在哪里x + 1,下一个是可能的订单执行的最早时刻

参考

class backtrader.Cerebro()

参数:

  • preload(默认True

是否data feeds为 Strategies 预加载不同的传递给 cerebro

  • runonce(默认True

以矢量化模式运行Indicators以加速整个系统。策略和观察者将始终基于事件运行

  • live(默认False

如果没有数据报告自己是实时的(通过数据的islive 方法但最终用户仍希望在live模式下运行,则可以将此参数设置为 true

这将同时停用preloadrunonce。它对内存节省方案没有影响。

以矢量化模式运行Indicators以加速整个系统。策略和观察者将始终基于事件运行

  • maxcpus(默认值:无 -> 所有可用内核)同时使用多少个内核进行优化
  • stdstats(默认True

如果将添加真正的默认观察员:经纪人(现金和价值)、交易和买入卖出

  • oldbuysell(默认False

如果stdstatsisTrue并且观察者正在自动添加,则此开关控制BuySell 观察者的主要行为

  • False:使用现代行为,其中买入/卖出信号分别绘制在低/高价下方/上方,以避免混乱图
  • True:使用已弃用的行为,在该行为中绘制买入/卖出信号,其中给定时间的订单执行的平均价格是。这当然会在 OHLC 条的顶部或在 Cloe 条上的 Line 上,从而难以识别情节。
  • oldtrades(默认False

如果stdstatsisTrue并且观察者正在自动添加,则此开关控制Trades 观察者的主要行为

  • False:使用现代行为,其中所有数据的交易都用不同的标记绘制
  • True:使用旧的交易观察者,它用相同的标记绘制交易,仅区分它们是正数还是负数
  • exactbars(默认False:)

使用默认值,存储在一行中的每个值都保存在内存中

可能的值:

* `True` 或 `1`:所有“行”对象将内存使用量减少到
  自动计算的最小周期。

  如果简单移动平均线的周期为 30,则基础数据
  将始终具有 30 个柱的运行缓冲区,以允许
  计算简单移动平均线

  * 此设置将停用 `preload` 和 `runonce` 

  * 使用此设置也会停用**绘图** 

* `-1`:数据释放和策略级别的指标/操作会将
  所有数据保存在内存中。

  例如:`RSI` 内部使用指标 `UpDay`
  进行计算。该子指标不会将所有数据保存在
  内存中

  * 这允许保持“绘图”和“预加载”处于活动状态。

  * `runonce` 将被停用

* `-2`:作为
  策略属性保存的数据馈送和指标将所有点保存在内存中。

  例如:`RSI` 内部使用指标 `UpDay`
  进行计算。该子指标不会将所有数据保存在
  内存中

  如果在 `__init__` 中定义了类似于
  `a = self.data.close - self.data.high` 的内容,则 `a`
  不会将所有数据保存在内存中

  * 这允许保持“绘图”和“预加载”处于活动状态。

  * `runonce` 将被停用
  • objcache(默认False

实现线对象缓存并减少它们数量的实验选项。UltimateOscillator 示例:

bp = self.data.close - TrueLow(self.data)
tr = TrueRange(self.data)  # -> creates another TrueLow(self.data)

如果这是True第二个内部 TrueLow(self.data)匹配TrueRange 计算中的签名bp。它将被重复使用。

可能会发生拐角情况,其中这会使线对象偏离其最小周期并破坏事物并因此被禁用。

  • writer(默认False

如果设置为True默认 WriterFile 将被创建,它将打印到标准输出。它将被添加到策略中(除了用户代码添加的任何其他编写器)

  • tradehistory(默认False

如果设置为True,它将在所有策略的每笔交易中激活更新事件记录。这也可以使用策略方法在每个策略的基础上完成set_tradehistory

  • optdatas(默认True

如果True优化(并且系统可以preload使用 runonce),数据预加载将在主进程中只进行一次,以节省时间和资源。

测试显示在几秒钟内20%从示例执行到8366

  • optreturn(默认True

如果True优化结果不是完整Strategy 对象(以及所有数据指标观察者……),而是具有以下属性的对象(与中相同Strategy):

* `params` (or `p`) the strategy had for the execution

* `analyzers` the strategy has executed

 

在大多数情况下,只有分析器和哪些参数是评估策略性能所需的东西。如果需要对(例如) 指标的生成值进行详细分析,请将其关闭

测试显示13% - 15%执行时间有所改善。结合总增益增加到优化运行中optdatas的总加速 。32%

  • oldsync(默认False

从版本 1.9.0.99 开始,多个数据(相同或不同时间范围)的同步已更改为允许不同长度的数据。

如果希望使用 data0 作为系统主控的旧行为,请将此参数设置为 true

  • tz(默认None

为策略添加全球时区。论据tz可以是

* `None`:在这种情况下,策略显示的日期时间将采用
  UTC,这始终是标准行为

* `pytz` 实例。它将用于将 UTC 时间转换
  为所选时区

* `string`。将尝试实例化 `pytz` 实例。

* `整数`。
  对于策略,使用与 `self.datas` 迭代中相应的 `data`相同的时区(`0` 将使用来自 `data0` 的时区)

 

  • cheat_on_open(默认False:)

next_open调用策略方法。这发生在next经纪人有机会评估订单之前和之前。指标尚未重新计算。这允许发布一个考虑前一天指标但使用open价格计算股权的订单

对于 cheat_on_open 订单执行,还需要调用cerebro.broker.set_coo(True)或实例化一个经纪人 BackBroker(coo=True)(其中coo代表 cheat-on-open)或将broker_coo参数设置为True. 除非在下面禁用,否则 Cerebro 会自动执行此操作。

  • broker_coo(默认True:)

这将自动调用set_coo代理的方法True来激活cheat_on_open执行。cheat_on_open只有在也是时才会这样做True

  • quicknotify(默认False:)

经纪人通知在下一个价格交付之前交付 。对于回溯测试,这没有任何影响,但是对于实时经纪人,可以在柱线交付之前很久就发出通知。设置为True通知将尽快发送(请参阅qcheck实时提要)

设置False为兼容性。可以改为True

addstorecb(回调)

添加回调以获取将由 notify_store 方法处理的消息

回调的签名必须支持以下内容:

  • callback(msg, *args, **kwargs)

actualmsg和received 是实现定义的(完全取决于data/broker/store*args ) ,但通常人们应该期望它们是可打印的,以允许接收和实验。**kwargs

notify_store(msg, *args, **kwargs)

cerebro 中接收商店通知

该方法可以在Cerebro子类中被覆盖

actualmsg和received 是实现定义的(完全取决于data/broker/store*args ) ,但通常人们应该期望它们是可打印的,以允许接收和实验。**kwargs

adddatacb(回调)

添加回调以获取将由 notify_data 方法处理的消息

回调的签名必须支持以下内容:

  • callback(data, status, *args, **kwargs)

实际*args**kwargs接收是实现定义的(完全取决于data/broker/store),但通常人们应该期望它们是可打印的,以允许接收和实验。

notify_data(data, status, *args, **kwargs)

cerebro 中接收数据通知

该方法可以在Cerebro子类中被覆盖

实际*args**kwargs接收是实现定义的(完全取决于data/broker/store),但通常人们应该期望它们是可打印的,以允许接收和实验。

adddata(data, name=None)

Data Feed实例添加到组合中。

如果name不是 None ,它将被放入data._name其中用于装饰/绘图目的。

resampledata(dataname, name=None, **kwargs)

添加一个Data Feed由系统重新采样

如果name不是 None ,它将被放入data._name其中用于装饰/绘图目的。

重采样过滤器支持的任何其他 kwarg(如timeframecompressiontodate都将透明传递

replaydata(dataname, name=None, **kwargs)

添加一个Data Feed由系统重播

如果name不是 None ,它将被放入data._name其中用于装饰/绘图目的。

重播过滤器支持的任何其他 kwargs (如timeframecompressiontodate都将透明传递

chaindata(*args, **kwargs)

将多个数据馈送链接到一个

如果name作为命名参数传递并且不是 None 它将被放入data._name其中用于装饰/绘图目的。

如果None,则将使用第一个数据的名称

rolloverdata(*args, **kwargs)

将多个数据馈送链接到一个

如果name作为命名参数传递并且不是 None 它将被放入data._name其中用于装饰/绘图目的。

如果None,则将使用第一个数据的名称

任何其他 kwargs 都将传递给 RollOver 类

addstrategy(strategy, *args, **kwargs)

Strategy为单程运行添加一个类。实例化将在一段时间内发生run

args 和 kwargs 将在实例化期间传递给策略。

返回可以引用添加其他对象(如 sizer)的索引

optstrategy(strategy, *args, **kwargs)

将一个Strategy类添加到组合中以进行优化。实例化将在一段时间内发生run

args 和 kwargs 必须是包含要检查的值的可迭代对象。

示例:如果 Strategy 接受参数period,则出于优化目的,调用optstrategy如下所示:

  • cerebro.optstrategy(MyStrategy, period=(15, 25))

这将对值 15 和 25 执行优化。而

  • cerebro.optstrategy(MyStrategy, period=range(15, 25))

将以 15 -> 25 的值执行 MyStrategy period(不包括 25,因为范围在 Python 中是半开放的)

如果传递了参数但不应优化,则调用如下所示:

  • cerebro.optstrategy(MyStrategy, period=(15,))

请注意,period它仍然作为可迭代的 … 仅 1 个元素传递

backtrader无论如何都会尝试识别以下情况:

  • cerebro.optstrategy(MyStrategy, period=15)

如果可能,将创建一个内部伪迭代

optcallback(cb)

回调添加到回调列表中,当每个策略运行时将使用优化调用

签名:cb(策略)

addindicator(indcls, *args, **kwargs)

添加一个Indicator类。实例化将 run在传递的策略中及时完成

addobserver(obscls, *args, **kwargs)

添加一个Observer类。实例化将在 run时间完成

addobservermulti(obscls, *args, **kwargs)

添加一个Observer类。实例化将在 run时间完成

系统中的每个“数据”都会添加一次。用例是观察单个数据的买卖观察者。

一个反例是 CashValue,它观察系统范围的值

addanalyzer(ancls, *args, **kwargs)

添加一个Analyzer类。实例化将在 run时间完成

addwriter(wrtcls, *args, **kwargs)

添加一个Writer类。实例化将 run在 cerebro 的时间完成

run(**kwargs)

执行回测的核心方法。任何传递给它的东西都会影响被实例化kwargs的标准参数的值。Cerebro

如果cerebro没有数据,该方法将立即退出。

它有不同的返回值:

  • 对于无优化:包含添加的策略类实例的列表addstrategy
  • 优化:一个列表列表,其中包含添加的 Strategy 类的实例addstrategy

runstop()

如果从策略内部或其他任何地方调用,包括其他线程,执行将尽快停止。

setbroker(broker)

设置此策略的特定broker实例,替换从 cerebro 继承的实例。

getbroker()

返回代理实例。

这也可以作为property名称使用broker

plot(plotter=None, numfigs=1, iplot=True, start=None, end=None, width=16, height=9, dpi=300, tight=True, use=None, **kwargs)

绘制大脑内部的策略

如果plotter为 None,则创建默认Plot实例并 kwargs在实例化期间将其传递给它。

numfigs如果需要,将绘图拆分为指定数量的图表,以降低图表密度

iplot: 如果True并在一个notebook图表中运行,将内联显示

use:将其设置为所需的 matplotlib 后端的名称。它将优先于iplot

start: 策略的日期时间线数组的索引或 指示绘图开始datetime.datedatetime.datetime实例

end: 策略的日期时间线数组的索引或 指示绘图结束datetime.datedatetime.datetime实例

width:以英寸保存的图形

height:以英寸保存的图形

dpi:保存图形的每英寸点数的质量

tight: 只保存实际内容,不保存图框

addizer(sizercls, *args, **kwargs)

添加一个Sizer类(和 args),它是添加到 cerebro 的任何策略的默认大小调整器

addizer_byidx(idx, sizercls, *args, **kwargs)

Sizer通过 idx添加一个类。此 idx 是与 . 返回的引用兼容的引用addstrategy。只有引用的策略 idx才会收到这个大小

add_signal(sigtype, sigcls, *sigargs, **sigkwargs)

向系统添加一个信号,该信号稍后将添加到 SignalStrategy

signal_concurrent(onoff)

如果将信号添加到系统并且concurrent值设置为 True,则允许并发订单

signal_accumulate(onoff)

如果信号被添加到系统并且accumulate值设置为 True,当已经进入市场时进入市场,将被允许增加头寸

信号策略(stratcls,*args,**kwargs)

添加一个可以接受信号的 SignalStrategy 子类

添加日历(cal)

向系统添加全球交易日历。个别数据馈送可能有单独的日历,这些日历会覆盖全局日历

cal可以是TradingCalendar字符串的实例或pandas_market_calendars. 一个字符串将被实例化为一个PandasMarketCalendar(需要 pandas_market_calendar在系统中安装模块。

如果通过 TradingCalendarBase 的子类(不是实例),它将被实例化

addtz(tz)

这也可以通过参数来完成tz

为策略添加全球时区。论据tz可以是

  • None:在这种情况下,策略显示的日期时间将采用 UTC,这一直是标准行为
  • pytz实例。它将用于将 UTC 时间转换为所选时区
  • stringpytz将尝试实例化实例。
  • integer. 对于策略,使用与可迭代中对应data的时区相同的时区(将使用来自的时区)self.datas0data0

add_timer(when, offset=datetime.timedelta(0), repeat=datetime.timedelta(0), weekdays=[], weekcarry=False, monthdays=[], monthcarry=True, allow=None, tzdata=None, strats=False, cheat=False, *args, **kwargs)

安排一个计时器来调用notify_timer

  • 参数 ) – 可以
    • datetime.time实例(见下文tzdata
    • bt.timer.SESSION_START引用会话开始
    • bt.timer.SESSION_END引用会话结束
    • offset这必须是一个datetime.timedelta实例

    用于偏移值whenSESSION_START它与和结合使用具有有意义的用途,以指示在会话开始后SESSION_END调用计时器之类的事情。15 minutes

    • repeat这必须是一个datetime.timedelta实例指示在第一次通话后,是否将在同一会话中以预定的repeat增量安排进一步的通话

      一旦计时器超过会话结束,它将重置为原始值when

    • weekdays: 一个排序的迭代器,带有整数,指示在哪些天(iso 代码,星期一是 1,星期日是 7)可以实际调用计时器如果未指定,计时器将在所有日子都处于活动状态
    • weekcarry(默认值:)False。如果True没有看到工作日(例如:交易假期),计时器将在第二天执行(即使在新的一周)
    • monthdays:一个排序的迭代器,带有整数,指示必须在每月的哪几天执行计时器。例如总是在每月的第15天如果未指定,计时器将在所有日子都处于活动状态
    • monthcarry(默认值:)True。如果没有看到这一天(周末、交易假日),则计时器将在下一个可用日期执行。
    • allow(默认值:)None。一个回调,它接收一个 datetime.date` 实例,True如果计时器允许该日期,则返回,否则返回False
    • tzdata可以是None(默认)、pytz 实例或data feed实例。None:when以面值解释(这意味着将其视为 UTC 处理,即使它不是)

      pytz实例:when将被解释为在时区实例指定的本地时间中指定。

      data feed实例:将被解释为在数据馈送实例when的参数指定的本地时间中指定。tz

      笔记

      如果whenisSESSION_STARTSESSION_END并且tzdata is None,系统中的第一个数据 馈送(aka self.data0)将用作查找会话时间的参考。

    • strats(默认False:)也调用notify_timer策略
    • cheat(默认False)如果True在经纪人有机会评估订单之前调用计时器。这打开了基于开盘价发出订单的机会,例如在会话开始之前
    • *args: 任何额外的参数都将传递给notify_timer
    • **kwargs: 任何额外的 kwargs 将被传递给notify_timer

返回值:

  • 创建的计时器

notify_timer(timer, when, *args, **kwargs)

收到定时器通知,timer返回的定时器在哪里add_timerwhen是调用时间。args 并且kwargs是传递给add_timer

实际when时间可以晚一些,但系统可能之前无法调用定时器。该值是定时器值,不是系统时间。

add_order_history(orders, notify=True)

添加订单历史记录以直接在经纪人中执行以进行绩效评估

  • orders: 是一个可迭代对象(例如:列表、元组、迭代器、生成器),其中每个元素也是具有以下子元素的可迭代对象(有长度)(可能有 2 种格式)[datetime, size, price]或者[datetime, size, price, data]

    笔记

    它必须按日期时间升序排序(或生成排序元素)

    • datetime是 pythondate/datetime实例或格式为 YYYY-MM-DD[THH:MM:SS[.us]] 的字符串,其中括号中的元素是可选的
    • size是一个整数(正数买入,负数卖出
    • price是浮点数/整数
    • data如果存在可以采用以下任何值
      • – 第一个数据馈送将用作目标
      • 整数– 将使用具有该索引的数据(在 Cerebro中的插入顺序)
      • 字符串– 具有该名称的数据,例如分配有 cerebro.addata(data, name=value),将是目标
  • notify(默认:)如果True在系统中插入的第一个策略将被通知根据每个订单的信息创建的人工订单orders