绘图 #
尽管回测主要是基于数学计算的自动化过程,但人们常常希望能够实际可视化所发生的一切。不论是使用已经经过回测的现有算法,还是查看数据所产生的内置或自定义指标,绘图都能帮助人们更好地理解所发生的事情,剔除、修改或创建新的想法。
由于所有操作背后都是人类,绘制数据馈送、指标、操作、现金流动和投资组合价值的演变图表有助于人们更好地理解过程,从而做出更明智的决策。因此,backtrader 使用 matplotlib 提供的功能,内置了绘图设施。
如何绘图 #
任何回测运行都可以通过调用一个方法进行绘图:
cerebro.plot()
当然,这通常是最后一个命令。例如,以下简单代码使用了 backtrader 源代码中的一个示例数据:
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()
这将生成以下图表:
图表包含了 3 个观察器,由于缺乏任何交易,它们在这种情况下几乎没有意义:
- CashValue 观察器:跟踪回测运行期间的现金和总投资组合价值(包括现金)。
- Trade 观察器:在交易结束时显示实际的利润和亏损。交易定义为开仓并将仓位归零(直接或从多头转为空头或从空头转为多头)。
- BuySell 观察器:在价格图上绘制买入和卖出操作的位置。
这 3 个观察器由 cerebro 自动添加,可以通过 stdstats
参数控制(默认:True)。如果希望禁用它们,可以如下操作:
cerebro = bt.Cerebro(stdstats=False)
或在运行时:
cerebro = bt.Cerebro()
...
cerebro.run(stdstats=False)
绘图元素 #
尽管前面提到了观察器,它们并不是唯一被绘制的元素。以下 3 种元素会被绘制:
- 使用
adddata
、replaydata
和resampledata
添加到 Cerebro 的数据馈送。 - 在策略级别声明的指标(或通过
addindicator
添加到 cerebro 的指标,这纯粹用于实验目的,并将指标添加到一个虚拟策略中)。 - 使用
addobserver
添加到 cerebro 的观察器。
观察器是与策略同步运行的线性对象,并且可以访问整个生态系统,以便跟踪现金和价值等内容。
绘图选项 #
指标和观察器有几个选项可以控制它们在图表上的绘制方式,分为 3 大类:
- 影响整个对象绘图行为的选项。
- 影响单个线条绘图行为的选项。
- 影响系统级别绘图选项的选项。
对象级绘图选项 #
这些选项由指标和观察器中的 plotinfo
数据集控制:
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
在类定义时显示为字典,但 backtrader 的元类机制将其转变为一个可以继承的对象,并且可以进行多重继承。例如:
如果子类将 subplot=True
更改为 subplot=False
,则层级结构中的进一步子类将具有后者作为 subplot
的默认值。
有两种方法为这些参数赋值。让我们看一下 SimpleMovingAverage
实例化的第一种方法:
sma = bt.indicators.SimpleMovingAverage(self.data, period=15, plotname='mysma')
从示例中可以推断,SimpleMovingAverage
构造函数未消耗的任何 **kwargs 都将被解析(如果可能)为 plotinfo
值。SimpleMovingAverage
只有一个定义的参数,即 period
。这意味着 plotname
将匹配 plotinfo
中同名的参数。
第二种方法:
sma = bt.indicators.SimpleMovingAverage(self.data, period=15)
sma.plotinfo.plotname = 'mysma'
与 SimpleMovingAverage
一起实例化的 plotinfo
对象可以被访问,并且其中的参数也可以通过标准的 Python 点符号访问。与上面的语法相比,这种方法更容易理解。
参数含义 #
- plot:是否绘制该对象。
- subplot:是否与数据一起绘制或在独立的子图中绘制。例如,移动平均线是绘制在数据上的,而随机指标和 RSI 则是在不同的刻度上绘制的。
- plotname:在图表上使用的名称,而不是类名。例如上面的
mysma
而不是SimpleMovingAverage
。 - plotskip(已弃用):
plot
的旧别名。 - plotabove:是否在数据之上绘制,否则在数据下方绘制。这仅在
subplot=True
时有效。 - plotlinelabels:是否在图表的图例中显示单个线条的名称,当
subplot=False
时。 - plotlinevalues:控制图例中是否包含指标和观察器线条的最后绘制值。可以通过每条线的
_plotvalue
控制。 - plotvaluetags:控制是否在线条的右侧绘制带有最后值的标签。可以通过每条线的
_plotvaluetag
控制。 - plotymargin:在图表上单个子图顶部和底部添加的边距。它是一个以 1 为基数的百分比。例如:0.05 表示 5%。
- plothlines:一个包含值的可迭代对象(在刻度内),在这些值处绘制水平线。例如,经典指标的超买、超卖区域通常在 70 和 30 处绘制线。
- plotyticks:一个包含值的可迭代对象(在刻度内),在这些值处特意放置刻度值。例如,强制刻度有 50 以识别刻度的中点。
- plotyhlines:一个包含值的可迭代对象(在刻度内),在这些值处绘制水平线。如果未定义上述任何项,那么水平线和刻度的位置将完全由此值控制。
- plotforce:如果所有其他方法都失败,这是一个最后的强制绘图机制。
- plotmaster:一个指标/观察器有一个主控,它是工作的数据。在某些情况下,可能希望与不同的主控一起绘图。
- plotylimited:目前仅适用于数据馈送。如果为
True
(默认),其他线条在数据图上的绘图不会改变刻度。
线条特定绘图选项 #
指标/观察器有线条,如何绘制这些线条可以通过 plotlines
对象进行影响。大多数 plotlines
中的选项旨在直接传递给 matplotlib。文档主要通过示例进行说明。
重要:选项是按每条线条指定的。
一些选项由 backtrader 直接控制,这些选项都以 _
开头:
- _plotskip(布尔值):如果设置为
True
,表示跳过绘制特定线条。 - _plotvalue(布尔值):控制此线条的图例是否包含最后绘制的值(默认值为
True
)。 - _plotvaluetag(布尔值):控制是否在线条右侧绘制带有最后值的标签(默认值为
True
)。 - _name(字符串):更改特定线条的绘图名称。
- _skipnan(布尔值,默认:
False
):跳过绘制 NaN 值。 - _samecolor(布尔值):强制下一条线条使用与前一条相同的颜色,避免 matplotlib 为每个新绘制的元素循环颜色图。
- _method(字符串):选择 matplotlib 用于绘制元素的方法。
示例:
- MACDHisto 使用 `_
method=‘bar’` 绘制直方图。
- BuySell 观察器:
plotlines = dict(
buy=dict(marker='^', markersize=8.0, color='lime', fillstyle='full'),
sell=dict(marker='v', markersize=8.0, color='red', fillstyle='full')
)
- Trades 观察器:
lines = ('pnlplus', 'pnlminus')
plotlines = dict(
pnlplus=dict(_name='Positive', marker='o', color='blue', markersize=8.0, fillstyle='full'),
pnlminus=dict(_name='Negative', marker='o', color='red', markersize=8.0, fillstyle='full')
)
系统级绘图选项 #
cerebro 的 plot
方法签名:
def plot(self, plotter=None, numfigs=1, iplot=True, **kwargs):
- plotter:一个包含控制系统级绘图选项的对象/类。如果为
None
,则创建默认PlotScheme
对象。 - numfigs:将图表分解为多少个独立的图表。
- iplot:如果在 Jupyter Notebook 中运行,自动内联绘图。
- kwargs:将用于更改
plotter
或默认PlotScheme
对象的属性值。
PlotScheme #
包含控制系统级绘图的所有选项的对象。选项在代码中有文档说明。
颜色 #
PlotScheme
类定义了一个方法,可以在子类中重写,该方法返回要使用的下一个颜色:
def color(self, idx)
其中 idx
是当前线条的索引。默认颜色方案是 Tableau 10 颜色调色板,索引修改为:
tab10_index = [3, 0, 2, 1, 2, 4, 5, 6, 7, 8, 9]