13.1 Plotting

How to plot

cerebro.plot()

Then 3 observers are automatically added by cerebro, and are controlled with the stdstats parameter (default: True). Do the following to disable them if you wish:
cerebro = bt.Cerebro(stdstats=False)

Plotted Elements

Although the Observers have already been mentioned above in the introduction, they are not the only elements to get plotted. These 3 things get plotted:

  • Data Feeds added to Cerebro with adddata, replaydata and resampledata

  • Indicators declared at strategy level (or added to cerebro with addindicator which is purely meant for experimentation purposes and has the indicator added to a dummy strategy)

  • Observers added to cerebro with addobserver

The Observers are lines objects which run in sync with the strategy and have access to the entire ecosystem, to be able to track things like Cash and Value

Plotting Options

Indicators and Observers have several options that control how they have to be plotted on the chart. There are 3 big groups:

Options affecting the plotting behavior of the entire object

Options affecting the plotting behavior of individual lines

Options affecting the SYSTEM wide plotting options

Object-wide plotting options
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在类定义中给定,但是backtader 中元类的机制,可以让它在多层继承中保持。这意味着:

If a subclass changes for example a value like subplot=True to subplot=False, subclasses further down the hierarchy will have the latter as the default value for subplot

两种设定参数值的方式:
sma = bt.indicators.SimpleMovingAverage(self.data, period=15, plotname='mysma')

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

The meaning of the options

  • plot: whether the object has to be plotted

  • subplot: whether to plot along the data or in an independent subchart. Moving Averages are an example of plotting over the data. Stochastic and RSI are examples of things plotted in a subchart on a different scale.

  • plotname: name to use on the chart instead of the class name. As in the example above mysma instead of SimpleMovingAverage

  • plotabove: whether to plot above the data. Else plot below. This has only effect if subplot=True

  • plotlinelabels: whether to plot the names of the individudal lines along the data in the legend on the chart when subplot=False

Example: The Bollinger Bands have 3 lines but the indicator is plotted on top of the data. It seems sensible to have the legend only display a single name like BollingerBands rather than having the name of the 3 individual lines displayed (mid, top, bot)

A use case for this is the BuySell observer for which it makes sense to display the name of the 2 lines and its markers: Buy and Sell to make it clear for the end user what is what.

  • plotlinevalues: controls whether the legend for the lines in indicators and observers has the last plotted value. Can be controlled on a per-line basis with _plotvalue for each line

  • plotvaluetags: controls whether a value tag with the last value is plotted on the right hand side of the line. Can be controlled on a per-line basis with _plotvaluetag for each line

  • plotymargin: margin to add to the top and bottom of individual subcharts on the graph

It is a percentage but 1 based. For example: 0.05 -> 5%

  • plothlines: an iterable containing values (within the scale) at which horizontal lines have to be plotted.

This for example helps for the classical indicators with overbought, oversold areas like the RSI which usually has lines plotted at 70 and 30

  • plotyticks: an iterable containing values (within the scale) at which value ticks have to specifically be placed on the scale

For example to force the scale to have a 50 to identify the mid point of the scale. Although this seems obvious, the indicators use an auto-scaling mechanism and the 50 may not be obviously be in the centre if an indicator with a 0-100 scale moves between 30-95 on a regular basis.

  • plotyhlines: an iterable containing values (within the scale) at which horizontal lines have to be plotted.

This can take over both plothlines and plotyticks.

If none of the above are defined, then where to place horizontal lines and ticks will be entirely controlled by this value

If any of the above are defined they have precedence over the values present in this option

  • plotforce: sometimes and thus the complex process of matching data feeds to indicators and bla, bla, bla … a custom indicator may fail to plot. This is a last resort mechanism to try to enforce plotting.

Use it if all else fails

  • plotmaster: an Indicator/Observer has a master which is the data on which is working. In some cases plotting it with a different master may be wished needed.

A use case is the PivotPoint indicator which is calculated on Monthly data but is meant for Daily data. It only makes sense to plot it on the daily data which is where the indicator makes sense.

  • plotylimited: currently only applies to data feeds. If True (default), other lines on the data plot don’t change the scale. Example: Bollinger Bands (top and bottom) may be far away from the actual absolute minimum/maximum of the data feed. With \plotlimited=True, those bands remain out of the chart, because the data controls the scaling. If set toFalse`, the bands affects the y-scale and become visible on the chart
Line specific plotting options

Indicators/Observers have lines and how this lines are plotted can be influenced with the plotlines object. Most of options specified in plotlines are meant to be directly passed over to matplotlib when plotting. The documentation relies therefore on examples of things that have been done.

Some of the options are controlled directly by backtrader. These all start with an underscore (_):

  • _plotskip (boolean) which indicates that plotting of a specific line has to be skipped if set to True

  • _plotvalue (boolean) to control if the legend of this line will contain the last plotted value (default is True)

  • _plotvaluetag (boolean) to control if a righ hand side tag with the last value is plotted (default is True)

  • _name (string) which changes the plot name of a specific line

  • _skipnan (bool, default: False): to skip NaN values when plotting and allowing for example to draw a line between 2 distant points generated by an indicator, which has all intermediate values as NaN (default value for new created data points)

_samecolor (boolean) this forces the next line to have the same color as the previous one avoiding the matplotlib default mechanism of cycling trough a color map for each new plotted element

  • _method (string) which chooses the plotting method matplotlib will use for the element. If this is not specified, then the most basic plot method will be chosen.

Example from MACDHisto. Here the histo line is plotted as a bar which is the industry de-facto standard. The following definition can be found in the definition of MACDHisto:

lines = ('histo',)
plotlines = dict(histo=dict(_method='bar', alpha=0.50, width=1.0))

alpha and width are options for matplotlib

  • _fill_gt / _fill_lt

Allow filling between the given line and:

Another line

A numeric value

The arguments is an iterable of 2 elements in which:

The 1st argument is a string (name of reference line) or a numeric value

The filling will be done in between the own values and the values of the line or the numeric value

The 2nd argument is either:

A string with a colour name (matplotlib compatible) or hex specification (see matloplit examples)
or

An iterable where the 1st element is the string/hex value for the colour and the second element is a numeric value specifying the alpha transparency (default: 0.20 controlled with fillalpha in a plotting scheme)

Passing options to a not yet known line

Ue the name _X where X stands for a digit in a zero-based index. This means that the options are for line X

A use case from OscillatorMixIn:

plotlines = dict(_0=dict(_name='osc'))

As the name implies, this is a mixin class intended to be used in multiple inheritance schemes (specifically on the right hand side). The mixin has no knowledge of the actual name of the 1st line (index is zero-based) from the other indicator that will be part of the multiple inheritance mix.

And that’s why the options are specified to be for: _0. After the subclassing has taken place the 1st line of the resulting class will have the name osc in plot.

Some plotlines examples
plotlines = dict(
    buy=dict(marker='^', markersize=8.0, color='lime', fillstyle='full'),
    sell=dict(marker='v', markersize=8.0, color='red', fillstyle='full')
)


...
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')
)


lines = ('drawdown', 'maxdrawdown',)

...

plotlines =   dict(maxdrawdown=dict(_plotskip='True',))


plotlines = dict(
     mid=dict(ls='--'),
    top=dict(_samecolor=True),
    bot=dict(_samecolor=True),
)

lines = ('percK', 'percD',)
...
plotlines = dict(percD=dict(_name='%D', ls='--'),
                 percK=dict(_name='%K'))
Methods controlling plotting

When dealing with Indicators and Observers the following methods are supported to further control plotting:

  • _plotlabel(self)
    Which should return a list of things to conform the labels which will be placed in between parentheses after the name of the Indicators or Observer (SMA(30))

  • _plotinit(self)
    Which is called at the beginning of plotting to do whatever specific initialization the indicator may need.

System-wide plotting options

First the signature of plot within cerebro:
def plot(self, plotter=None, numfigs=1, iplot=True, **kwargs):

Which means:

  • plotter: an object/class containing as attributes the options controlling the system wide plotting

If None is passed a default PlotScheme object (see below) will be instantiated

  • numfigs: in how many independent charts a plot has to be broken

Sometimes a chart contains too many bars and will not be easily readable if packed in a single figure. This breaks it down in as many pieces as requested

  • iplot: automatically plot inline if running inside a Jupyter Notebook

  • **kwargs: the args will be used to change the values of the attributes of plotter or the default PlotScheme object created if no plotter is passed.

PlotScheme

This object contains all the options that contol system-wide plotting.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,454评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,553评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,921评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,648评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,770评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,950评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,090评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,817评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,275评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,592评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,724评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,409评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,052评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,815评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,043评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,503评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,627评论 2 350