BackTrader 中文文档(十二)(1)https://developer.aliyun.com/article/1505316
系统范围内的绘图选项
首先是在 cerebro 中的 plot
的签名:
def plot(self, plotter=None, numfigs=1, iplot=True, **kwargs):
这意味着:
plotter
:包含作为属性的选项,控制系统范围内绘图的对象/类
如果传递了None
,则将实例化一个默认的PlotScheme
对象(见下文)numfigs
:将绘图分解为多少个独立图表
有时图表包含太多条形,如果在单个图中打包,将不容易阅读。这将根据请求的数量将其分解为相同数量的部分iplot
:如果在 Jupyter Notebook 中运行,则自动绘制内联**kwargs
:args 将用于更改plotter
或默认PlotScheme
对象的属性值,如果没有传递plotter
则会创建默认的PlotScheme
对象。
PlotScheme
此对象包含控制系统范围内绘图的所有选项。选项在代码中有文档:
class PlotScheme(object): def __init__(self): # to have a tight packing on the chart wether only the x axis or also # the y axis have (see matplotlib) self.ytight = False # y-margin (top/bottom) for the subcharts. This will not overrule the # option plotinfo.plotymargin self.yadjust = 0.0 # Each new line is in z-order below the previous one. change it False # to have lines paint above the previous line self.zdown = True # Rotation of the date labes on the x axis self.tickrotation = 15 # How many "subparts" takes a major chart (datas) in the overall chart # This is proportional to the total number of subcharts self.rowsmajor = 5 # How many "subparts" takes a minor chart (indicators/observers) in the # overall chart. This is proportional to the total number of subcharts # Together with rowsmajor, this defines a proportion ratio betwen data # charts and indicators/observers charts self.rowsminor = 1 # Distance in between subcharts self.plotdist = 0.0 # Have a grid in the background of all charts self.grid = True # Default plotstyle for the OHLC bars which (line -> line on close) # Other options: 'bar' and 'candle' self.style = 'line' # Default color for the 'line on close' plot self.loc = 'black' # Default color for a bullish bar/candle (0.75 -> intensity of gray) self.barup = '0.75' # Default color for a bearish bar/candle self.bardown = 'red' # Level of transparency to apply to bars/cancles (NOT USED) self.bartrans = 1.0 # Wether the candlesticks have to be filled or be transparent self.barupfill = True self.bardownfill = True # Wether the candlesticks have to be filled or be transparent self.fillalpha = 0.20 # Wether to plot volume or not. Note: if the data in question has no # volume values, volume plotting will be skipped even if this is True self.volume = True # Wether to overlay the volume on the data or use a separate subchart self.voloverlay = True # Scaling of the volume to the data when plotting as overlay self.volscaling = 0.33 # Pushing overlay volume up for better visibiliy. Experimentation # needed if the volume and data overlap too much self.volpushup = 0.00 # Default colour for the volume of a bullish day self.volup = '#aaaaaa' # 0.66 of gray # Default colour for the volume of a bearish day self.voldown = '#cc6073' # (204, 96, 115) # Transparency to apply to the volume when overlaying self.voltrans = 0.50 # Transparency for text labels (NOT USED CURRENTLY) self.subtxttrans = 0.66 # Default font text size for labels on the chart self.subtxtsize = 9 # Transparency for the legend (NOT USED CURRENTLY) self.legendtrans = 0.25 # Wether indicators have a leged displaey in their charts self.legendind = True # Location of the legend for indicators (see matplotlib) self.legendindloc = 'upper left' # Plot the last value of a line after the Object name self.linevalues = True # Plot a tag at the end of each line with the last value self.valuetags = True # Default color for horizontal lines (see plotinfo.plothlines) self.hlinescolor = '0.66' # shade of gray # Default style for horizontal lines self.hlinesstyle = '--' # Default width for horizontal lines self.hlineswidth = 1.0 # Default color scheme: Tableau 10 self.lcolors = tableau10 # strftime Format string for the display of ticks on the x axis self.fmt_x_ticks = None # strftime Format string for the display of data points values self.fmt_x_data = None
PlotScheme 中的颜色
PlotScheme
类定义了一个方法,可以在子类中重写,该方法返回下一个要使用的颜色:
def color(self, idx)
其中idx
是当前正在绘制的单个子图上的行的索引。例如,MACD
绘制了 3 条线,因此idx
变量只会有以下值:0
、1
和2
。下一个图表(可能是另一个指标)将从0
开始重新计数。
默认颜色方案使用的是backtrader中的(如上所示)Tableau 10 Color Palette
,其索引修改为:
tab10_index = [3, 0, 2, 1, 2, 4, 5, 6, 7, 8, 9]
通过覆盖color
方法或将lcolors
变量传递给plot
(或在PlotScheme
的子类中),可以完全改变着色方式。
源代码还包含了Tableau 10 Light
和Tableau 20
颜色调色板的定义。
绘制日期范围
原文:
www.backtrader.com/docu/plotting/ranges/plotting-date-ranges/
发布的1.9.31.x
版本增加了制作部分图表的功能。
- 要么使用策略实例中保留的时间戳完整数组的索引
- 或者使用实际的
datetime.date
或datetime.datetime
实例来限制需要绘制的内容。
仍然在标准的cerebro.plot
上。示例:
cerebro.plot(start=datetime.date(2005, 7, 1), end=datetime.date(2006, 1, 31))
作为人类直接执行的方式。具有扩展能力的人类实际上可以尝试将datetime
时间戳作为索引,如下所示:
cerebro.plot(start=75, end=185)
一个非常标准的示例包含简单移动平均线(在数据绘图中)、随机指标(独立绘图)和随机指标线的交叉点,如下所示。cerebro.plot
的参数作为命令行参数传递。
使用date
方法执行:
./partial-plot.py --plot 'start=datetime.date(2005, 7, 1),end=datetime.date(2006, 1, 31)'
Python 中的eval
魔法允许直接在命令行中编写datetime.date
,并将其映射到有意义的内容。输出图表
让我们将其与完整图表进行比较,以查看数据实际上是从两端跳过的:
./partial-plot.py --plot
Python 中的eval
魔法允许直接在命令行中编写datetime.date
,并将其映射到有意义的内容。输出图表
示例用法
$ ./partial-plot.py --help usage: partial-plot.py [-h] [--data0 DATA0] [--fromdate FROMDATE] [--todate TODATE] [--cerebro kwargs] [--broker kwargs] [--sizer kwargs] [--strat kwargs] [--plot [kwargs]] Sample for partial plotting optional arguments: -h, --help show this help message and exit --data0 DATA0 Data to read in (default: ../../datas/2005-2006-day-001.txt) --fromdate FROMDATE Date[time] in YYYY-MM-DD[THH:MM:SS] format (default: ) --todate TODATE Date[time] in YYYY-MM-DD[THH:MM:SS] format (default: ) --cerebro kwargs kwargs in key=value format (default: ) --broker kwargs kwargs in key=value format (default: ) --sizer kwargs kwargs in key=value format (default: ) --strat kwargs kwargs in key=value format (default: ) --plot [kwargs] kwargs in key=value format (default: )
示例代码
from __future__ import (absolute_import, division, print_function, unicode_literals) import argparse import datetime import backtrader as bt class St(bt.Strategy): params = ( ) def __init__(self): bt.ind.SMA() stoc = bt.ind.Stochastic() bt.ind.CrossOver(stoc.lines.percK, stoc.lines.percD) def next(self): pass def runstrat(args=None): args = parse_args(args) cerebro = bt.Cerebro() # Data feed kwargs kwargs = dict() # Parse from/to-date dtfmt, tmfmt = '%Y-%m-%d', 'T%H:%M:%S' for a, d in ((getattr(args, x), x) for x in ['fromdate', 'todate']): if a: strpfmt = dtfmt + tmfmt * ('T' in a) kwargs[d] = datetime.datetime.strptime(a, strpfmt) # Data feed data0 = bt.feeds.BacktraderCSVData(dataname=args.data0, **kwargs) cerebro.adddata(data0) # Broker cerebro.broker = bt.brokers.BackBroker(**eval('dict(' + args.broker + ')')) # Sizer cerebro.addsizer(bt.sizers.FixedSize, **eval('dict(' + args.sizer + ')')) # Strategy cerebro.addstrategy(St, **eval('dict(' + args.strat + ')')) # Execute cerebro.run(**eval('dict(' + args.cerebro + ')')) if args.plot: # Plot if requested to cerebro.plot(**eval('dict(' + args.plot + ')')) def parse_args(pargs=None): parser = argparse.ArgumentParser( formatter_class=argparse.ArgumentDefaultsHelpFormatter, description=( 'Sample for partial plotting' ) ) parser.add_argument('--data0', default='../../datas/2005-2006-day-001.txt', required=False, help='Data to read in') # Defaults for dates parser.add_argument('--fromdate', required=False, default='', help='Date[time] in YYYY-MM-DD[THH:MM:SS] format') parser.add_argument('--todate', required=False, default='', help='Date[time] in YYYY-MM-DD[THH:MM:SS] format') parser.add_argument('--cerebro', required=False, default='', metavar='kwargs', help='kwargs in key=value format') parser.add_argument('--broker', required=False, default='', metavar='kwargs', help='kwargs in key=value format') parser.add_argument('--sizer', required=False, default='', metavar='kwargs', help='kwargs in key=value format') parser.add_argument('--strat', required=False, default='', metavar='kwargs', help='kwargs in key=value format') parser.add_argument('--plot', required=False, default='', nargs='?', const='{}', metavar='kwargs', help='kwargs in key=value format') return parser.parse_args(pargs) if __name__ == '__main__': runstrat()
在同一轴上绘制
前一篇帖子中的未来点,是在同一空间上绘制了原始数据和略微(随机)修改的数据,但没有在同一轴上。
从那篇帖子中恢复第一张图片。
人们可以看到:
- 图表的左右两侧有不同的比例尺
- 当观察摆动的红线(随机数据)围绕原始数据振荡
+- 50
点时,这一点最为明显。
在图表上的视觉印象是,这些随机数据大多数时候都在原始数据之上。这只是由于不同的比例尺造成的视觉印象。
尽管发行版 1.9.32.116
已经初步支持在同一轴上完全绘制,但图例标签会重复(只有标签,没有数据),这真的很令人困惑。
发行版 1.9.33.116
解决了这个效果,并允许完全在同一轴上绘制。用法模式与决定与哪些其他数据一起绘制的模式相似。从前一篇帖子中。
import backtrader as bt cerebro = bt.Cerebro() data0 = bt.feeds.MyFavouriteDataFeed(dataname='futurename') cerebro.adddata(data0) data1 = bt.feeds.MyFavouriteDataFeed(dataname='spotname') data1.compensate(data0) # let the system know ops on data1 affect data0 data1.plotinfo.plotmaster = data0 data1.plotinfo.sameaxis = True cerebro.adddata(data1) ... cerebro.run()
data1
获得一些 plotinfo
值以:
- 在与
plotmaster
(即data0
)相同的空间中绘制 - 获得使用
sameaxis
的指示
这种指示的原因是平台无法预先知道每个数据的比例尺是否兼容。这就是为什么它会在独立的比例尺上绘制它们的原因。
前面的示例获取了一个额外的选项,以在 sameaxis
上绘制。一个示例执行:
$ ./future-spot.py --sameaxis
以及产生的图表
要注意:
- 右侧只有一个比例尺
- 现在随机数据似乎明显围绕着原始数据振荡,这是预期的视觉行为
示例用法
$ ./future-spot.py --help usage: future-spot.py [-h] [--no-comp] [--sameaxis] Compensation example optional arguments: -h, --help show this help message and exit --no-comp --sameaxis
示例代码
from __future__ import (absolute_import, division, print_function, unicode_literals) import argparse import random import backtrader as bt # The filter which changes the close price def close_changer(data, *args, **kwargs): data.close[0] += 50.0 * random.randint(-1, 1) return False # length of stream is unchanged # override the standard markers class BuySellArrows(bt.observers.BuySell): plotlines = dict(buy=dict(marker='$\u21E7$', markersize=12.0), sell=dict(marker='$\u21E9$', markersize=12.0)) class St(bt.Strategy): def __init__(self): bt.obs.BuySell(self.data0, barplot=True) # done here for BuySellArrows(self.data1, barplot=True) # different markers per data def next(self): if not self.position: if random.randint(0, 1): self.buy(data=self.data0) self.entered = len(self) else: # in the market if (len(self) - self.entered) >= 10: self.sell(data=self.data1) def runstrat(args=None): args = parse_args(args) cerebro = bt.Cerebro() dataname = '../../datas/2006-day-001.txt' # data feed data0 = bt.feeds.BacktraderCSVData(dataname=dataname, name='data0') cerebro.adddata(data0) data1 = bt.feeds.BacktraderCSVData(dataname=dataname, name='data1') data1.addfilter(close_changer) if not args.no_comp: data1.compensate(data0) data1.plotinfo.plotmaster = data0 if args.sameaxis: data1.plotinfo.sameaxis = True cerebro.adddata(data1) cerebro.addstrategy(St) # sample strategy cerebro.addobserver(bt.obs.Broker) # removed below with stdstats=False cerebro.addobserver(bt.obs.Trades) # removed below with stdstats=False cerebro.broker.set_coc(True) cerebro.run(stdstats=False) # execute cerebro.plot(volume=False) # and plot def parse_args(pargs=None): parser = argparse.ArgumentParser( formatter_class=argparse.ArgumentDefaultsHelpFormatter, description=('Compensation example')) parser.add_argument('--no-comp', required=False, action='store_true') parser.add_argument('--sameaxis', required=False, action='store_true') return parser.parse_args(pargs) if __name__ == '__main__': runstrat()
BackTrader 中文文档(十二)(3)https://developer.aliyun.com/article/1505318