13.1 Plotting

2020-04-30  本文已影响0人  wanggs66

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:

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

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.

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

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

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.

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

Use it if all else fails

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.

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 (_):

_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

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

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:

System-wide plotting options

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

Which means:

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

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

PlotScheme

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

上一篇下一篇

猜你喜欢

热点阅读