Contents

Backtrader

平台概念Platform Concepts

  • parameters
  • lines
    • basic
    • delayed indexing
    • coupling
  • index
  • slice

运行平台

Line Iterators

To engage into operations, the plaftorm uses the notion of line iterators. They have been loosely modeled after Python’s iterators but have actually nothing to do with them. Strategies and Indicators are line iterators. 策略和指标是line迭代器。

线性迭代器的概念试图描述如下内容:

  • 一个line迭代器会触发从属line迭代器,告诉它们进行迭代。
  • 一个line迭代器然后会在其声明的命名lines迭代并设置值。

迭代的关键就像普通的Python迭代器一样:

  • next方法 这个方法将在每次迭代时被调用。线性迭代器拥有的 datas 数组已经被平台移动到下一个索引(除非数据重放)。

还有两种其他的方法: prenext: 当线性迭代器的最小周期满足时调用。 nextstart: 在线性迭代器的最小周期满足时,精确地调用一次。

针对Indicators的其他方法

为了加速操作,指标支持一种批量操作模式,称为runonce。它并不是严格必要的(一个next方法就足够),但它极大地减少了时间。

runonce方法的规则取消了带索引0的get/set,依赖于直接访问底层数组,传递每个状态的正确索引。

启动与运行

启动与运行至少包括3个Lines对象

  • 数据源 Data feed
  • 策略 Strategy
  • 核心 Cerebro

数据源

看文档吧

策略

策略是为了完成回溯测试,至少有两个方法需要自定义:

  • __init__
  • next

startstop方法应该不言自明。notify_order方法在策略需要通知时被调用。使用场景:

  • buy / sell / close 使用底层代理人和定量器来发送代理人的buy/sell订单

相同的工作可以通过手动创建订单并将它发送给代理人。但是这个平台是为了更轻松的使用它。

close将会得到现在的市场头寸并立即关闭它。

  • getposition函数或者position属性

返回目前的市场头寸情况。

-setsizer/getsizer或者sizer属性

这些方法允许设置/获取底层的定量器(Sizer)。可以使用相同的逻辑检查不同的定量器,它们为相同的情况提供不同的持仓量(固定大小、与资本成比例、指数增长)。

策略是Lines对象和支持的参数。这些由python标准的kwargs参数收集。

核心 Cerebro

一旦数据源可得和定义了策略,一个cerebro示例就可以组合起所有的内容并执行操作。实例化很容易:

cerebro = bt.Cerebro()

如无特殊,会默认如下:

  • 创建一个默认的代理人
  • 不收取佣金
  • 数据源会预加载
  • 默认的执行模式为更快的runonce(批量操作)

所有的indicators为了全速必须支持runonce模式。平台中包含所有内容。

自动一点儿indicators不必实现runonce功能。cerebro将会模拟它,这也意味着那些非runonce兼容的指标会运行的慢一点。但是系统大部分会一批量模式运行。

由于数据源已经可用疾病且策略也已经可用,把他们放在一起并开始运行的标准方式为:

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

注意以下事情:

  • 数据源"示例"已添加
  • 策略"类"与参数(kwargs)添加

MyStrategy的示例会在cerebro在后台完成,并且在"addstrategy"中的参数也会传递过去。

当从需要添加很多的策略和数据时,平台不会强制或限制策略之间的通信。

cerebro提供了其他的可能性:

  • 决定预加载和操作模式
cerebro = bt.Cerebro(runonce=True, preload=True)

有一个一致性:runonce需要预加载,如果不预加载,批量操作则不能运行。预加载数据源不会强制runonce

  • setbroker/getbroker 以及代理人性质 一个自定义的代理人可以根据自己的要求进行设置。也可以访问实际的代理实例。
  • 画图。在常规情况下会非常简单:
cerebro.run()
cerebro.plot()

plot可以自定义采取一些参数

  • numfigs=1

如果画图太密集可以分为几个图

  • plotter=None

可以传递一个客户画图实例,cerebro不会实例化默认实例

  • **kwargs

可以传递给plotter

  • 策略优化

cerebro会的到一个策略类的派生类(非实例),并且在run时会实例化并传递参数。

这样做是为了能够最优化。相同的策略类能够使用新的参数初始化多次。 最优化操作可如下:

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

optstrategy方法与addstrategy有相同的签名,但是做了更多的内存处理来报正最优化按照预期运行。一个策略可能预期一个范围作为正常的参数,并且addstrategy将对传递的参数不做任何假设。

另一方面,optstrategy将会理解一个可迭代是一群值的集合,这将按照顺序来传递到每个策略类的实例中。

主要对傲并非一个值,而是一个范围的值被传递。在这个简单的例子中,10个数值10->19(20是上限)将会在这个策略中尝试。

如果一个更加复杂的策略以及其他的参数产生,他们将会传递到optstrategy。不必经过最优化的参数可以直接传递,终端用户不必穿凿一个虚拟可迭代数值。实例:

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

这个optstrategy方法在后台查看因子并且创建虚拟迭代变量。这个因子只有一个值,此例中为3.5

Cerebro

This class is the cornerstone of backtrader because it serves as a central point for: cerebro类是backtrader的基石:

  • 收集所有的输入(Data Feeds),演员(Stratgegies),观众(Observers),批评家(Analyzers)以及记录员(Writers)来保证在任何时候都能演出。
  • 执行回溯或者实时数据的反馈与交易
  • 返回结果
  • 允许访问绘图设施

Gathering input

  1. 创建cerebro:
cerebro = bt.Cerebro(**kwargs)

一些**kwargs来控制执行是支持的。具体查看后面的run方法。

  1. 添加数据源 最常见的模式是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)

系统可以接受任意数量的数据源,包括混合的常规数据的重采样和重放回数据。当然其中一些的组合是毫无意义的冰屑一个严格的应用来组合数据:time aligment.查看数据-多时间轴,数据重采样重放回数据回放等节。

  1. 添加策略Strategies 不像datas feeds,他已经是一个类的实例,cerebro直接使用Strategy并且传递参数给它。背后的理由:在优化场景中,该类会被实例化多次并传递不同的参数。

基石没有优化,该模式仍会应用:

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

optimizing优化参数已经被添加作为可迭代后。查看Optimizition节查看具体解释。基本的使用:

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

这将会运行MyStrategy10次,并且参数myparam1将会分别取值10-19。

  1. 其他元素 可以添加一些其他的元素到回溯过程中。查看appropriate节来查看,这些方法有:
  • addwriter
  • addanalyzer
  • addobserver or addobservermulti
  1. 更改代理人broker Cerebro使用默认的broker,但是可以重写:
broker = MyBroker()
cerebro.broker = broker #属性使用getbroker/setbroker方法
  1. 接收通知 如果data feeds或者broker发送了通知或者创建通知的存储提供者,他们将会从Cerebro.notify_store,有三种方法来处理这些通知
  • 通过addnotifycallback(callback)添加一个callbackcerebro实例。这个回馈支持下面的签名:
callback(msg, *args, **kwargs)

实际接收到的 msg*args**kwargs 是由实现定义的(完全取决于数据源/经纪商/存储提供者),但通常应期望它们是可打印的,以便于接收和实验。

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

The signature: notify_store(self, msg, *args, **kwargs)

  • 继承Cerebro并重写notify_store方法(与Strategy中的方法签名相同)。这应该是最不推荐的方法。

执行回溯测试

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

result = cerebro.run(**kwargs)

以下的参考资料查看哪些参数可用。

标准观察员

cerebro自动实例化三种标准观察员

  • 代理人Broker观察员追踪cashvalue
  • 交易Trades观察员应该站是每一笔交易的有效性。
  • 买卖Buy/Sell观察员应该在操作执行时应该被记录。

如果希望一个更清晰的plotting需要禁用他们stdstats=False

返回结果

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

result = cerebro.run(**kwargs)

The format of result returned by run will vary depending on whether optimization is used (a strategy was added with optstrategy): run函数运行后返回结果的格式根据是否使用了optimization而定。

  • 添加了addstrategy的所有策略
    result将会使回溯过程中的list实例
  • 添加了optstrategy的>=1个策略 result将会是元素为listlist。内部的每个list都包含从每个优化运行后的策略。
    如果希望返回完成的策略集,设置参数optreturnFalse

允许访问绘图设施

另外,如果matplotlib已安装,则可以绘制策略。通常的模式是:

cerebro.plot()

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

回溯测试逻辑

事物流程的简要概述:

  1. 发送任何存储通知。
  2. 要求数据源来发送下一组价格变动和柱线。 数据源通过查看由可用数据源提供的下一个日期时间来同步。那些在新周期中没有交易的数据源仍旧提供旧的数据点,而由新数据可用的数据源则提供这些数据以及指标的计算。

第一个插入系统的数据为datamaster并且系统将会等待它发送一个刻度。

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

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

 * May return without delivering a new tick for a number of reasons

该逻辑旨在轻松地同步多个数据源以及不同时间范围的数据源。

  1. 通知策略有关订单,交易以及现金/价值的排队代理人的通知。
  2. 告诉代理人接收排队的订单以及使用新数据执行待处理订单
  3. 调用策略的next方法来让策略评估新的数据(以及可能发布订单,这些订单会被加入到经纪商的队列中) 根据阶段的不同,可能是在策略/指标的最小周期要求达到之前调用 prenext 或 nextstart。

在内部,策略还会触发observers, indicators, analyzers和其他活跃的元素。 6. 告诉任意writers来对目标写入数据。

重点: 在step1,当data feeds传递了新的数据时,这些数据会被关闭。这意味着这些数据已经发生了。

因此,在步骤4中orders无法执行步骤一的数据。 这意味着订单将以 x + 1 的概念执行。这里的 x 是订单执行时的柱线时刻,x + 1 是下一个柱线时刻,这是订单可能被执行的最早时间。