量化交易学习(三十八)backtrader文档——绘图(1)

今天这篇是backtrader文档的学习笔记。主要介绍了绘图。

官方文档链接:https://www.backtrader.com/docu/plotting/plotting/

绘图

尽管回测是一个基于数学计算的自动化过程,但通常情况下,人们很想可视化正在发生的事情。无论是使用通过回测运行的现有算法,还是查看随数据不断更新,计算出的指标(内置或自定义)的值的变化。

因为一切都有人在背后操作,所以绘制数据源、指标、操作、现金和投资组合价值演变的图表可以帮助人们更好地理解正在发生的事情,人们会根据图表上的信息丢弃/修改/创造想法。

这就是为什么backtrader使用matplotlib来提供内置图表工具。

如何绘制

任何回测都可以通过调用下面这个方法来绘制:

1
cerebro.plot()

当然,这通常是最后一个执行的命令,就像这个简单的代码一样,它使用来自反向交易源的示例数据之一。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from __future__ import (absolute_import, division, print_function,
unicode_literals)

import backtrader as bt


class St(bt.Strategy):
def __init__(self):
self.sma = bt.indicators.SimpleMovingAverage(self.data)


data = bt.feeds.BacktraderCSVData(dataname='../../datas/2005-2006-day-001.txt')

cerebro = bt.Cerebro()
cerebro.adddata(data)
cerebro.addstrategy(St)
cerebro.run()
cerebro.plot()

这会产生下面的图表。

5d2e948abea61022617f8729312320c9.png

该图表包括 3 个观察者,在个例子中没有进行任何交易,所以图表没有太大意义。

  • CashValue观察者,顾名思义,在回测运行期间跟踪现金和投资组合的价值

  • Trade观察者在交易结束时显示实际盈亏

一次交易定义为开仓并将仓位收回0(直接或从多头转为空头或从空头转为多头)

  • BuySell观察者,绘制(在价格之上)发生买卖操作的位置

这3个观察者是由cerebro自动添加的,并由stdstats参数控制(默认:True)。可以执行以下操作来禁用它们:

1
cerebro = bt.Cerebro(stdstats=False)

或稍后运行时,如下所示:

1
2
3
cerebro = bt.Cerebro()
...
cerebro.run(stdstats=False)

绘制元素

尽管Observers已经在上面介绍中提到过,但它们并不是唯一需要绘制的元素。下面这三个元素也会被绘制出来:

  • 使用adddata,replaydataresampledata添加到 Cerebro 的数据源

  • 在策略级别声明的指标(或使用addindicator添加到 cerebro 中,纯粹用于实验目的,并将指标添加到虚拟策略中)

  • 通过addobserver添加到cerebro中的观察者

观察者是与策略同步运行的线对象,可以访问整个系统,能够跟踪诸如CashValue之类的值

绘图选项

指标和观察者有几个选项来控制它们在图表上的绘制方式。有3大组:

  • 影响整个对象的绘图行为的选项

  • 影响单条线的绘制行为的选项

  • 影响系统范围绘图选项的选项

对象范围的绘图选项

这些由指标和观察员中的数据集控制:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
plotinfo = dict(plot=True,
subplot=True,
plotname='',
plotskip=False,
plotabove=False,
plotlinelabels=False,
plotlinevalues=True,
plotvaluetags=True,
plotymargin=0.0,
plotyhlines=[],
plotyticks=[],
plothlines=[],
plotforce=False,
plotmaster=None,
plotylimited=True,
)

尽管plotinfo在类定义中是一个dict,但backtrader的元类机制将其转换为可继承的对象,甚至可以进行多重继承。这意味着:

  • 如果子类把一个值更改了,例如从subplot=True改为subplot=False,则层次结构中更下方的子类会将后者作为subplot的默认值。

有两种方法可以为这些参数赋值。让我们看一下第一个种为SimpleMovingAverage类实例化的方法:

1
sma = bt.indicators.SimpleMovingAverage(self.data, period=15, plotname='mysma')

从示例中可以推断,任何没有被SimpleMovingAverage构造函数处理的**kwargs参数都将被解析(如果可能)为plotinfo值。SimpleMovingAverage定义了一个period参数。这意味着plotname将与plotinfo中的同名参数进行匹配。

第二种方法:

1
2
sma = bt.indicators.SimpleMovingAverage(self.data, period=15)
sma.plotinfo.plotname = 'mysma'

plotinfo对象可以与SimpleMovingAverage一起实例化,也可以使用标准Python的点表示法访问内部参数。

各选项的含义

  • plot:是否必须绘制对象

  • subplot:是沿着数据绘制还是在独立子图中绘制。移动平均线是绘制数据的一个示例。随机指标和RSI是以不同比例绘制在子图中的示例。

  • plotname:在图表上使用的名称而不是类名称。如上面的示例所示,名称使用mysma而不是SimpleMovingAverage

  • plotskip(已弃用):plot的旧别名

  • plotabove:是否在数据上方绘制。这仅在subplot=True的情况下有效

  • plotlinelabels:当subplot=False时,是否在图表上的图例中沿着数据绘制各个线的名称

示例:布林带有 3 条线,但指标绘制在数据之上。让图例只显示单个名称BollingerBands,而不是显示 3 个单独行的名称 ( mid, top, bot)是明智的

一个例子是BuySell观察者,显示两条线的名称及其标记是有意义的:BuySell能让最终用户清楚什么是什么。

  • plotlinevalues:控制指标和观察器中线条的图例是否具有最后绘制的值。可以通过_plotvalue为基础对每条线进行控制。

  • plotvaluetags:控制是否将具有最后一个值的值标记绘制在线的右侧。可以_plotvaluetag为基础对每条线进行控制

  • plotymargin:添加到图表上各个子图的顶部和底部的边距

它是一个百分比,但以 1 为基础。例如:0.05 -> 5%

  • plothlines:一个包含必须绘制水平线的值(在比例范围内)的迭代。

例如,这有助于具有超买、超卖区域的经典指标,例如通常在7030的RSI值处绘制线条

  • plotyticks:一个包含值(在比例范围内)的可迭代对象,必须将其值标记专门放置在比例尺上

例如,强制刻度具有一个50的值来识别刻度的中点。虽然这看起来很明显,但指标使用自动缩放机制,如果一个指标的范围在0-100,数值有30-95之间的偏移,则50指标可能不会明显位于中心。

  • plotyhlines:一个包含必须绘制水平线的值(在比例范围内)的迭代。

这可以接管plothlinesplotyticks

如果以上均未定义,则水平线和刻度线的放置位置将完全由该值控制

如果定义了上述任何一项,它们优先于该选项中存在的值

  • plotforce:有时,将数据源与指标相匹配的复杂过程可能无法绘制。这是尝试强制绘图的最后手段机制。

如果其他方法都失败了,请使用它

  • plotmaster:指标/观察者有一个控制者,它是正在运行的数据。在某些情况下,可能需要使用不同的控制者来绘制它。

一个例子是根据每月PivotPoint数据计算适用于每日数据的指标。只有将其绘制在每日数据上才有意义,这才是该指标有意义的地方。

  • plotylimited:目前仅适用于数据源。如果为True(默认),数据图上的其他线不会改变比例。示例:布林带(顶部和底部)可能远离数据馈送的实际绝对最小值/最大值。使用plotlimited=True,这些条带会保持在图表外,因为数据控制着缩放,如果设置为True,条带会影响 y-scale 并在图表上可见。

一个例子是根据每月PivotPoint数据计算但适用于每日数据的指标。只有将其绘制在每日数据上才有意义,这才是该指标有意义的地方。


这一篇就到这里啦。欢迎大家点赞、转发、私信。还没有关注我的朋友可以关注 江达小记

江达小记