Skip to content

脑波

原文: https://www.backtrader.com/docu/cerebro/

本课程是backtrader的基石,因为它是以下内容的中心点:

  1. 收集所有输入(数据源),演员(策略),观众(观察员),评论家(分析员)和资料员(编剧),确保该剧在任何时候都能继续进行。

  2. 执行回溯测试/或实时数据馈送/交易

  3. 返回结果

  4. 允许使用绘图设备

收集投入

  1. 首先创建一个cerebro

    py cerebro = bt.Cerebro(**kwargs)

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

  2. 添加数据源

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

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

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

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

    或:

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

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

  3. 添加Strategies

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

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

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

    优化时,必须将参数作为可比项添加。详细说明请参见优化部分。基本模式:

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

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

  4. 其他要素

    还可以添加一些其他元素来增强回溯测试体验。请参见相关章节。这些方法是:

    • addwriter

    • addanalyzer

    • addobserver(或addobservermulti

  5. 更换经纪人

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

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

  6. 接收通知

    如果数据源和/或代理发送通知(或创建通知的存储提供商),则将通过Cerebro.notify_store方法接收通知。使用这些通知有三(3)种方法

    • 通过addnotifycallback(callback)调用向cerebro实例添加回调。回调必须支持此签名:

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

    实际接收的msg*args**kwargs是实现定义的(完全取决于数据/代理/存储),但一般情况下,人们应该期望它们是可打印的,以允许接收和实验。

    • 重写Strategy子类中添加到cerebro实例的notify_store方法。

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

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

    这应该是最不可取的方法

执行回溯测试

只有一个方法可以执行此操作,但它支持多个选项(在实例化时也可以指定这些选项)来决定如何运行:

result = cerebro.run(**kwargs) 

请参阅下面的示例,了解哪些参数可用。

标准观察员

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

  • 跟踪cashvalue(投资组合)的经纪人观察员

  • 一个交易观察者,该观察者应显示每笔交易的有效性

  • 一个买入/卖出的观察者,该观察者应记录何时执行操作

如果需要更干净的绘图,只需使用stdstats=False禁用它们即可

返回结果

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

result = cerebro.run(**kwargs) 

run返回的result格式会根据是否使用优化而有所不同(在策略中增加了optstrategy

  • 所有策略都添加了addstrategy

    result将是回溯测试期间运行的实例的list

  • 使用optstrategy添加了 1 个或多个策略

    result将是listlist部分。每个内部列表将包含每次优化运行后的策略

笔记

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

如果希望将整套策略作为返回值,则将参数optreturn设置为False

允许使用绘图设备

如果安装了额外的 anmatplotlib,则可以绘制策略。通常的模式是:

cerebro.plot() 

参考和剖面图见下文

回溯测试逻辑

事物流动的简要概述:

  1. 发送任何门店通知

  2. 要求数据源提供下一组刻度/条形图

    版本变更:在 1.9.0.99 版本中变更:新行为

    通过查看日期时间同步数据馈送,可用数据馈送将提供该日期时间。在新时期未交易的数据源仍然提供旧数据点,而有新数据可用的数据源提供此数据点(以及指标的计算)

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

    插入系统的 1st数据为datamaster,系统将等待其发出滴答声

    其他数据馈送或多或少是datamaster的从属数据,并且:

    ``py * If the next tick to deliver is newer (datetime-wise) than the one delivered by thedatamaster` it will not be delivered

    • May return without delivering a new tick for a number of reasons ```

    该逻辑设计用于轻松同步多个数据源和具有不同时间段的数据源

  3. 通知策略有关订单、交易和现金/价值的排队经纪人通知

  4. 告诉代理接受排队的订单,并使用新数据执行挂起的订单

  5. 调用 strategies'next方法,让策略评估新数据(并可能发出在代理中排队的订单)

    根据阶段的不同,在满足策略/指标的最短期限要求之前,可能是prenextnextstart

    在内部,这些策略也会打击observersindicatorsanalyzers等积极因素

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

重要的是要考虑到:

笔记

在上面的步骤1中,当数据馈送传递新的一组棒时,这些棒被关闭。这意味着数据已经发生了。

因此,步骤4中的策略发出的指令不能使用步骤1中的数据执行

这意味着订单将以x + 1的概念执行。其中,x是执行订单的酒吧时刻,x + 1是下一个,这是可能执行订单的最早时刻

参考

类 backtrader.Cerebro()

参数:

  • preload(默认为True

是否为策略预加载传递给大脑的不同data feeds

  • runonce(默认为True

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

  • live(默认为False

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

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

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

  • maxcpus(默认值:无->所有可用内核)

    同时使用多少个内核进行优化

  • stdstats(默认为True

如果是真的,将添加默认观察者:经纪人(现金和价值)、交易和买卖

  • oldbuysell(默认为False

如果stdstatsTrue且观察者被自动添加,则此开关控制BuySell观察者的主要行为

  • False:使用现代行为,买入/卖出信号分别绘制在低/高价格下方/上方,以避免弄乱图形

  • True:使用不推荐的行为,在该行为中,在给定时刻执行订单的平均价格为的位置绘制买入/卖出信号。这当然会在 OHLC 条的顶部或 Cloe 条上的一条线上,难以识别绘图。

  • oldtrades(默认为False

如果stdstatsTrue且观察者被自动添加,则此开关控制Trades观察者的主要行为

  • False:使用现代行为,所有数据的交易都用不同的标记绘制

  • True:使用旧的交易观察器,该观察器使用相同的标记绘制交易,仅当它们为正或负时进行区分

  • exactbars(默认为False

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

可能值:

* `True` or `1`: all “lines” objects reduce memory usage to the
  automatically calculated minimum period.

  If a Simple Moving Average has a period of 30, the underlying data
  will have always a running buffer of 30 bars to allow the
  calculation of the Simple Moving Average

  * This setting will deactivate `preload` and `runonce`

  * Using this setting also deactivates **plotting**

* `-1`: datafreeds and indicators/operations at strategy level will
  keep all data in memory.

  For example: a `RSI` internally uses the indicator `UpDay` to
  make calculations. This subindicator will not keep all data in
  memory

  * This allows to keep `plotting` and `preloading` active.

  * `runonce` will be deactivated

* `-2`: data feeds and indicators kept as attributes of the
  strategy will keep all points in memory.

  For example: a `RSI` internally uses the indicator `UpDay` to
  make calculations. This subindicator will not keep all data in
  memory

  If in the `__init__` something like
  `a = self.data.close - self.data.high` is defined, then `a`
  will not keep all data in memory

  * This allows to keep `plotting` and `preloading` active.

  * `runonce` will be deactivated 
  • objcache(默认为False

实验性选项,用于实现线对象缓存并减少线对象的数量。来自 Ultimate 振荡器的示例:

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

如果这是True,则TrueRange内的 2ndTrueLow(self.data)bp计算中的签名匹配。它将被重新使用。

在角点情况下,可能会使线条对象偏离其最小周期,并打断某些内容,因此将其禁用。

  • writer(默认为False

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

  • tradehistory(默认为False

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

  • optdatas(默认为True

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

测试显示,从83秒内的样本执行到66秒,大约有20%的加速

  • 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`: in this case the datetime displayed by strategies will be
  in UTC, which has been always the standard behavior

* `pytz` instance. It will be used as such to convert UTC times to
  the chosen timezone

* `string`. Instantiating a `pytz` instance will be attempted.

* `integer`. Use, for the strategy, the same timezone as the
  corresponding `data` in the `self.datas` iterable (`0` would
  use the timezone from `data0`) 
  • cheat_on_open(默认为False

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

对于未平仓订单执行欺诈,还需要调用cerebro.broker.set_coo(True)或使用BackBroker(coo=True)即时通知经纪人(其中coo代表未平仓欺诈)或将broker_coo参数设置为True。除非下面禁用,否则大脑将自动执行此操作。

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

实际接收的msg*args**kwargs是实现定义的(完全取决于数据/代理/存储),但一般情况下,人们应该期望它们是可打印的,以允许接收和实验。

通知门店(消息,args,*kwargs)

在 Cerbero 中接收存储通知

此方法可以在Cerebro子类中重写

实际接收的msg*args**kwargs是实现定义的(完全取决于数据/代理/存储),但一般情况下,人们应该期望它们是可打印的,以允许接收和实验。

adddatacb(回调)

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

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

  • 回调(数据、状态、args、*kwargs)

实际接收到的*args**kwargs是实现定义的(完全取决于数据/代理/存储,但通常情况下,人们应该期望它们是可打印的,以允许接收和实验。

通知 _ 数据(数据、状态、args、*kwargs)

在 Cerbero 中接收数据通知

此方法可以在Cerebro子类中重写

实际接收到的*args**kwargs是实现定义的(完全取决于数据/代理/存储,但通常情况下,人们应该期望它们是可打印的,以允许接收和实验。

adddata(数据,名称=无)

向混合中添加一个Data Feed实例。

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

重采样数据(dataname,name=None,**kwargs)

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

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

由重采样过滤器支持的任何其他 KWARG,如timeframecompressiontodate将透明通过

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

添加一个Data Feed供系统重播

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

回放过滤器支持的任何其他 KWARG,如timeframecompressiontodate,都将透明地通过

链数据(args,*kwargs)

将多个数据源链接为一个

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

如果为None,则使用 1st数据的名称

rolloverdata(args,*kwargs)

将多个数据源链接为一个

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

如果为None,则使用 1st数据的名称

任何其他 KWARG 都将传递给滚动类

添加策略(策略,args,*kwargs)

Strategy类添加到单遍运行的混合中。实例化将在run时间内发生。

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

返回可以引用添加的其他对象(如大小调整器)的索引

选择策略(策略,args,*kwargs)

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

arg 和 kwarg 必须是保存要检查的值的 iterables。

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

  • 大脑选择策略(我的策略,周期=(15,25))

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

  • 大脑选择策略(我的策略,周期=范围(15,25))

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

如果传递了一个参数,但未对其进行优化,则调用如下所示:

  • 大脑选择策略(我的策略,周期=(15,)

请注意,period仍然作为一个 iterable…传递,只有 1 个元素

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

  • 大脑选择策略(我的策略,周期=15)

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

optcallback(cb)

回调添加到回调列表中,当每个策略都已运行时,将通过优化调用该回调列表

签名:cb(战略)

附加指示器(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时间完成

运行(**kwargs)

执行回溯测试的核心方法。传递给它的任何kwargs都将影响已使用实例化的标准参数Cerebro的值。

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

它有不同的返回值:

  • 非优化:策略类实例列表中增加addstrategy

  • 优化:一个列表列表,包含添加了addstrategy的策略类实例

runstop()

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

经纪人(经纪人)

为该策略设置一个特定的broker实例,替换从 Cerbero 继承的实例。

getbroker()

返回代理实例。

这也可以通过名称为brokerproperty来获得

绘图(绘图仪=无,numfigs=1,iplot=真,开始=无,结束=无,宽度=16,高度=9,dpi=300,紧密=真,使用=无,**kwargs)

在大脑中绘制策略

如果plotter为 None,则创建默认Plot实例,并在实例化过程中将kwargs传递给该实例。

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

iplot:如果Truenotebook中运行,则图表将在线显示

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

start:策略的日期时间行数组的索引或datetime.datedatetime.datetime实例,表示情节的开始

end:策略日期时间行数组的索引或datetime.datedatetime.datetime实例,表示情节结束

width:已保存图形的英寸数

height:已保存图形的英寸数

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

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

addsizer(sizercls,args,*kwargs)

添加一个Sizer类(和 args),这是添加到 Cerbero 的任何策略的默认大小设置

addsizer_byidx(idx,sizercls,args,*kwargs)

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

添加信号(sigtype、sigcls、sigargs、*sigkwargs)

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

信号 _ 并发(onoff)

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

信号累积(开启关闭)

如果向系统添加信号且accumulate值设置为真,则允许在已经进入市场时进入市场,以增加头寸

信号 _ 策略(stratcls、ARG、*kwargs)

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

添加日历(cal)

将全球交易日历添加到系统中。单个数据源可能有单独的日历,覆盖全局日历

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

如果传递了 TradingCalendarBase 的子类(而不是实例),它将被实例化

addtz(tz)

这也可以通过参数tz实现

为策略添加全局时区。论点tz可以是

  • None:在这种情况下,策略显示的日期时间将以 UTC 为单位,这一直是标准行为

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

  • string。将尝试实例化一个pytz实例。

  • integer。对于策略,使用与self.datas表中对应的data相同的时区(0将使用data0中的时区)

添加计时器(当,offset=datetime.timedelta(0),repeat=datetime.timedelta(0),平日=[],周载波=False,月载波=[],月载波=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实例

    用于偏移值when。它与SESSION_STARTSESSION_END结合使用,有意义地表示在会话开始后调用15 minutes计时器之类的事情。

    • repeat必须是datetime.timedelta实例

      指示在 1st呼叫后,是否会在同一会话中以预定的repeat增量安排更多呼叫

      一旦计时器在会话结束后被重置为when的原始值

    • weekdays:一个排序的iterable,带有整数,表示可以实际调用计时器的日期(iso 代码,周一是 1,周日是 7)

      如果未指定,计时器将在所有日期都处于活动状态

    • weekcarry(默认为False)。如果True和工作日不可见(例如:交易假日),计时器将在第二天执行(即使在新的一周内)

    • monthdays:一个排序的iterable,整数表示计时器必须在月份的哪几天执行。例如,始终在当月的第15

      如果未指定,计时器将在所有日期都处于活动状态

    • monthcarry(默认为True)。如果看不到该日(周末、交易日),计时器将在下一个可用日执行。

    • allow(默认为None)。接收 datetime.date实例并返回True的回调,如果允许计时器使用该日期,则返回False`

    • tzdata可以是None(默认)、一个pytz实例或一个data feed实例。

      Nonewhen按面值解释(这意味着即使不是 UTC,也要像对待 UTC 一样处理)

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

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

      笔记

      如果whenSESSION_STARTSESSION_ENDtzdataNone,则系统中的 1st数据馈送(又名self.data0)将作为查询会话时间的参考。

    • strats(默认值:False)同时调用策略的notify_timer

    • cheat(默认False)如果True计时器将在经纪人有机会评估订单之前调用。这样就有机会根据开盘价发出订单,例如在会议开始之前

    • *args:任何额外参数都将传递给notify_timer

    • **kwargs:任何额外的 KWARG 将传递给notify_timer

返回值:

  • 创建的计时器

通知计时器(计时器,时间,args,*kwargs)

接收定时器通知,timeradd_timer返回的定时器,when为呼叫时间。argskwargs是传递给add_timer的任何附加参数

实际的when时间可以晚一点,但系统之前可能无法调用计时器。该值为计时器值,不代表系统时间。

添加订单历史记录(订单,通知=True)

添加要在代理中直接执行的订单的历史记录以进行性能评估

  • orders:是一个 iterable(例如:list、tuple、iterator、generator),其中每个元素也将是一个 iterable(具有长度),具有以下子元素(可能有两种格式)

    [datetime, size, price][datetime, size, price, data]

    笔记

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

    哪里:

    • datetime是 pythondate/datetime实例或格式为 YYYY-MM-DD[THH:MM:SS[.us]]的字符串,括号中的元素是可选的

    • size为整数(正对买入,负对卖出

    • price是浮点/整数

    • data如果存在,可采用以下任一值

      • -1st数据馈送将用作目标

      • 整数-将使用具有该索引的数据(在大脑中的插入顺序)

      • 字符串-具有该名称的数据(例如分配有cerebro.addata(data, name=value)的数据)将成为目标

  • notify(默认为

    如果True系统中插入的 1st策略将根据orders中每个订单的信息通知创建的人工订单

笔记

描述中隐含的是需要添加作为订单目标的数据提要。例如,这是跟踪例如返回的分析器所需要的


我们一直在努力

apachecn/AiLearning

【布客】中文翻译组