Visual Chart
与 Visual Chart 的集成支持两者:
- 实时数据提供
- 实时交易
Visual Chart是完整的交易解决方案:
- 在单个平台上集成图表、数据源和经纪功能
更多信息,请访问:www.visualchart.com
需求
- VisualChart 6
- Windows - VisualChart 正在运行的平台
comtypes分支:github.com/mementum/comtypes
使用以下命令安装:pip install https://github.com/mementum/comtypes/archive/master.zip
Visual Chart API 基于COM。
当前的comtypes主分支不支持对VT_RECORD的VT_ARRAYS的解包。这是由Visual Chart使用的
Pull Request #104已提交但尚未集成。一旦集成,就可以使用主分支。pytz(可选,但真的很推荐)
确保每个数据都在市场时间内返回。
对大多数市场而言这是真实的,但有些市场确实是例外情况(全球指数是一个很好的例子)
Visual Chart内部的时间管理及其与COM传递的时间的关系是复杂的,并且使用pytz倾向于简化事情。
示例代码
源代码包含一个完整的示例:
samples/vctest/vctest.py
示例无法涵盖每种可能的用例,但它试图提供广泛的见解,并应强调在使用回测模块或实时数据模块时没有真正的区别。
可以指出一件事:
- 在进行任何交易活动之前,示例等待
data.LIVE数据状态通知。
这可能是任何实时策略中需要考虑的事情。
VCStore - 存储库
存储库是实时数据源/交易支持的关键,为COM API 和数据源以及经纪人代理的需求之间提供一层适应性。
- 提供获取经纪人实例的方法:
VCStore.getbroker(*args, **kwargs)
- 提供对获取器数据源实例的访问
VCStore.getedata(*args, **kwargs)
- 在这种情况下,许多
**kwargs对于数据源都是常见的,如dataname,fromdate,todate,sessionstart,sessionend,timeframe,compression
数据可能提供其他参数。请查看下面的参考资料。
VCStore将尝试:
- 使用Windows Registry自动定位VisualChart在系统中的位置
- 如果找到,将扫描安装目录以查找COM DLL 以创建COM typelibs,并能够实例化适当的对象。
- 如果未找到,则将尝试使用已知的和硬编码的CLSIDs执行相同操作。
注意
即使可以通过扫描文件系统找到 DLL,Visual Chart本身也必须正在运行。backtrader 不会启动Visual Chart
VCStore的其他职责:
- 保持对 Visual Chart 与服务器的连接状态的一般跟踪
VCData feeds
通用
Visual Chart 提供的数据源具有一些有趣的特性:
- 重新采样由平台完成
并非所有情况:秒不受支持,仍需由 backtrader 完成
因此,只有在处理秒数时,最终用户才需要执行:
vcstore = bt.stores.VCStore() vcstore.getdata(dataname='015ES', timeframe=bt.TimeFrame.Ticks) cerebro.resampledata(data, timeframe=bt.TimeFrame.Seconds, compression=5)`
- 在所有其他情况下,仅需要:
vcstore = bt.stores.VCStore() data = vcstore.getdata(dataname='015ES', timeframe=bt.TimeFrame.Minutes, compression=2) cerebro.addata(data)`
数据将通过比较内部设备时钟和平台提供的ticks来内部计算timeoffset,以便在没有新的ticks到达时尽快提供自动重新采样的柱状图。
实例化数据:
- 将在VisualChart左上方看到的符号传递,不包括空格。 例如:
- ES-Mini 显示为
001 ES。 实例化它为:
data = vcstore.getdata(dataname='001ES', ...)`
- EuroStoxx 50 显示为
015 ES。 实例化它为:
data = vcstore.getdata(dataname='015ES', ...)`
注意
backtrader 将尽力清除位于名称直接从 Visual Chart 粘贴的第四个位置的空格。
时间管理
时间管理遵循 backtrader 的一般规则
- 给出市场时间,以确保代码不依赖于在不同时间发生 DST 转换,并使本地时间对时间比较不可靠。
这适用于 Visual Chart 中的大多数市场,但对于某些市场进行了特定的管理:
- 交换
096中的数据被命名为International Indices。
理论上这些被报告为位于Europe/London时区,但测试表明这似乎只是部分正确,某些内部管理措施已经覆盖了它。
可以通过传递参数 usetimezones=True 来启用实际时区的时间管理。 如果可用,会尝试使用 pytz。 并不需要,因为对于大多数市场,Visual Chart 提供的内部时间偏移量允许无缝转换到市场时间。
在任何情况下,报告096.DJI位于Europe/London时间似乎是毫无意义的,当实际上它位于US/Eastern时。 因此,backtrader 将在后者中报告它。 在这种情况下,强烈推荐使用 pytz。
注意
道琼斯工业指数(不是全球版本)位于 099I-DJI
注意
所有这些时间管理都在 DST 转换期间进行真正的测试,期间本地和远程市场发生了与 DST 相关的不同步现象。
VCDATA中定义了输出时区的International Indices列表:
'096.FTSE': 'Europe/London', '096.FTEU3': 'Europe/London', '096.MIB30': 'Europe/Berlin', '096.SSMI': 'Europe/Berlin', '096.HSI': 'Asia/Hong_Kong', '096.BVSP': 'America/Sao_Paulo', '096.MERVAL': 'America/Argentina/Buenos_Aires', '096.DJI': 'US/Eastern', '096.IXIC': 'US/Eastern', '096.NDX': 'US/Eastern',
小时间问题
使用给定的时间而不是默认的 00:00:00 传递 fromdate 或 todate 似乎会在 COM API 中创建一个过滤器,并且任何日期的柱状图只会在给定时间之后交付。
因此:
- 请仅向
VCData传递完整日期,如下所示:
data = vcstore.getdata(dataname='001ES', fromdate=datetime(2016, 5, 15))`
- 并非::
data = vcstore.getdata(dataname=‘001ES’, fromdate=datetime(2016, 5, 15, 8, 30))`
补偿时间长度
如果最终用户未指定fromdate,平台将自动尝试回填,然后继续实时数据。回填是时间框架相关的,如下:
Ticks,MicroSeconds,Seconds:1 天
对于给定的 3 个时间框架,秒和微秒不受Visual Chart直接支持,通过Ticks的重新采样完成分钟:2 天天数:1 年周:2 年月份:5 年月份:20 年
定义的回填期将乘以请求的压缩,即:如果时间框架是分钟,压缩是 5,则最终回填期将是:2 天 * 5 -> 10 天
交易数据
Visual Chart提供连续未来。无需手动管理,您可以跟踪所选的未来而无需中断。这是一个优势,也提出了一个小挑战:
ES-Mini是001ES,但实际交易资产(例如:Sep-2016)是ESU16。
为了克服这一点,并允许跟踪连续未来并交易真实资产的策略,在数据实例化期间可以指定以下内容:
data = vcstore.getdata(dataname='001ES', tradename='ESU16')
交易将在ESU16上进行,但数据源将来自001ES(数据相同,为期 3 个月)
其他参数
qcheck(默认:0.5秒)控制唤醒与内部重新采样器/重播器交流的频率,以避免延迟传递条形图。将应用以下逻辑来使用此参数:
- 如果检测到内部重新采样/重播,则将使用该值。
- 如果未检测到内部重新采样/重播,数据源将不会唤醒,因为没有要报告的内容。
- 数据源仍将唤醒以检查Visual Chart内置的重新采样器,但这是自动控制的。
数据通知
数据源将通过以下一种或多种方式报告当前状态(检查Cerebro和Strategy参考)
Cerebro.notify_data(如果被覆盖)- 使用
Cerebro.adddatacb添加的回调 Strategy.notify_data(如果被覆盖)
策略内的一个示例:
class VCStrategy(bt.Strategy): def notify_data(self, data, status, *args, **kwargs): if status == data.LIVE: # the data has switched to live data # do something pass
系统发生变化后将发送以下通知:
CONNECTED
成功初始连接时发送DISCONNECTED在这种情况下,不再可能检索数据,数据将指示系统无法执行任何操作。可能的情况:
- 指定了错误的合同
- 在历史下载期间中断
- 尝试重新连接到 TWS 的次数超过了
CONNBROKEN
连接已丢失,无论是到 TWS 还是到数据中心。数据源将尝试(通过存储)重新连接和回填,必要时,并恢复操作NOTSUBSCRIBED
合同和连接正常,但由于权限不足,无法检索数据。
数据将指示系统无法检索数据DELAYED
表示历史/回填操作正在进行中,并且策略处理的数据不是实时数据LIVE
表示从这一点开始要处理的数据是实时数据
策略的开发人员应考虑在发生断开连接或接收延迟数据时采取哪些行动。
VCBroker - 实时交易
使用经纪人
要使用VCBroker,必须替换由cerebro创建的标准经纪人模拟实例。
使用Store模型(首选):
import backtrader as bt cerebro = bt.Cerebro() vcstore = bt.stores.VCStore() cerebro.broker = vcstore.getbroker() # or cerebro.setbroker(...)
经纪人参数
无论是直接还是通过getbroker,VCBroker经纪人都不支持参数。 这是因为经纪人只是对真实经纪人的代理。 真正的经纪人给出的,不应被拿走。
限制
仓位
Visual Chart报告持仓。 这在大多数情况下可以用来控制实际仓位,但缺少指示仓位已关闭的最终事件。
这使得backtrader必须对Position进行完整的会计核算,并与您帐户中任何先前存在的仓位分开
佣金
COM交易界面不报告佣金。 backtrader没有机会做出合理猜测,除非:
- 经纪人与指示实际发生的佣金的佣金实例一起实例化。
与其进行交易
账户
Visual Chart在一个经纪人上同时支持多个帐户。 可以使用以下参数控制选择的帐户:
account(默认值:None)
VisualChart 支持同时在经纪人上使用多个帐户。 如果使用默认值None,则将使用 ComTraderAccounts集合中的第一个帐户。
如果提供了帐户名称,则将检查并使用Accounts集合(如果存在)
操作
关于标准用法没有变化。 只需使用策略中可用的方法(有关详细说明,请参阅Strategy参考)
buysellclosecancel
返回的订单对象
- 标准backtrader
Order对象
订单执行类型
Visual Chart支持backtrader所需的最小订单执行类型,因此,任何经过回测的内容都可以实时执行。
因此,订单执行类型仅限于经纪人模拟中可用的类型:
Order.MarketOrder.CloseOrder.LimitOrder.Stop(当Stop触发时,Market订单随后进行)Order.StopLimit(当Stop触发时,Limit订单随后进行)
订单有效性
在回测期间可用的相同有效性概念(用于valid到buy和sell)可用,并具有相同含义。 因此,对于以下值,valid参数转换如下以用于Visual Chart Orders:
None翻译为Good Til Cancelled
因为未指定有效期,因此理解订单必须有效直至取消datetime/date翻译为Good Til Date
注意
注意:Visual Chart仅支持“完整日期”,并且忽略了时间部分。timedelta(x)翻译为 有效期至(这里timedelta(x) != timedelta())
注释
注意:Visual Chart 仅支持完整日期,并且会将时间部分丢弃。
这被解释为指示订单从now+timedelta(x)开始有效timedelta() or 0翻译为 会话
已传递一个值(而不是None),但是值为 Null,并被解释为仅在当前 日期(会话)有效的订单
通知
标准 Order 状态将通过方法 notify_order(如果被覆盖)通知到一个 策略 上
已提交- 订单已发送至 TWS已接受- 订单已下达已拒绝- 订单放置失败或在其生命周期内被系统取消部分完成- 部分执行已经发生已完成- 订单已完全执行已取消(或取消)已过期- 目前尚未报告。需要一种启发式方法来区分此状态与取消的区别
参考
VCStore
类 backtrader.stores.VCStore()
包装 ibpy ibConnection 实例的单例类。
这些参数也可以在使用该存储的类中指定,例如 VCData 和 VCBroker
VCBroker
类 backtrader.brokers.VCBroker(**kwargs)
VisualChart 的经纪商实现。
此类将 VisualChart 的订单/持仓映射到 backtrader 的内部 API。
参数:
账户(默认值:None)
VisualChart 支持在经纪商上同时使用多个账户。如果默认值为None,则将使用 ComTraderAccounts集合中的第 1 个账户。
如果提供了账户名称,则将检查并使用Accounts集合(如果存在)佣金(默认值:None)
如果未传递佣金方案,则将自动生成对象
有关更多解释,请参阅下面的注释
注释
- 持仓
VisualChart 通过 ComTrader 接口报告“OpenPositions”更新,但仅当持仓具有“大小”时。指示持仓已移至零的更新通过不存在此类持仓来报告。这强制通过观察执行事件来保持持仓的会计,就像模拟经纪商一样。
- 佣金
VisualChart 的 ComTrader 接口不报告佣金,因此自动生成的 CommissionInfo 对象不能使用不存在的佣金来正确计算它们。为了支持佣金,必须传递带有适当佣金方案的 commission 参数。
佣金方案的文档详细介绍了如何实现这一点
- 过期时间
ComTrader 接口(或者是 comtypes 模块?)从 datetime 对象中丢弃了 time 信息,并且到期日期始终是完整日期。
- 过期报告
目前还没有启发式方法来确定取消的订单何时因过期而取消。因此,过期订单被报告为已取消。
VCData
类 backtrader.feeds.VCData(**kwargs)
VisualChart 数据源。
参数:
qcheck(默认值:0.5)唤醒以便让重采样器/重播器检查当前柱是否可以进行交付的默认超时时间
该值仅在数据中插入了重采样/重播过滤器时才会使用historical(默认值:False)如果没有提供todate参数(在基类中定义),则将强制仅进行历史下载(如果设置为True)
如果提供了todate,则可以实现相同的效果milliseconds(默认值:True)由Visual Chart构建的柱状图具有如下外观:HH:MM:59.999000
如果该参数设置为True,将会在时间上增加一毫秒,使其看起来像是:HH::MM + 1:00.000000tradename(默认值:None)连续期货无法交易,但非常适合数据跟踪。如果提供了该参数,它将是当前期货的名称,该名称将成为交易资产。示例:
- 001ES -> ES-Mini 连续提供作为
dataname - ESU16 -> ES-Mini 2016-09. 如果在
tradename中提供了此信息,它将成为交易资产。
usetimezones(默认值:True)对于大多数市场,Visual Chart提供的时间偏移信息允许将日期时间转换为市场时间(backtrader选择的表示方式)
一些市场是特殊的(096),需要特殊的内部覆盖和时区支持以显示用户预期的市场时间。
如果该参数设置为True,将尝试导入pytz以使用时区(默认值)
禁用它将取消时区使用(可能有助于减轻负载过重的情况)
绘图
绘图
尽管回测是基于数学计算的自动化过程,但通常情况下,人们希望实际可视化正在发生的情况。 无论是使用经过回测运行的现有算法,还是查看真正的指标(内置或自定义)与数据一起提供了什么。
而且因为一切都有人类的背后,绘制数据源、指标、操作、现金和组合价值的发展可以帮助人类更好地理解正在发生的事情,丢弃/修改/创建想法以及查看图表的人类可以用视觉信息做的任何事情。
这就是为什么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观察器,如其名称所示,在回测运行的生命周期内跟踪Cash和总投资组合Value(包括现金) - 一个
Trade观察器,在一次交易结束时显示实际的盈亏
交易被定义为开仓并将仓位调回0(直接或从多头到空头或空头到多头) - 一个
BuySell观察器,在价格之上绘制买入和卖出操作的位置
这3 个观察器是由cerebro自动添加的,并且通过stdstats参数(默认为True)进行控制。 如果希望禁用它们,请执行以下操作:
cerebro = bt.Cerebro(stdstats=False)
或者稍后运行时,例如:
cerebro = bt.Cerebro() ... cerebro.run(stdstats=False)
绘制的元素
尽管在介绍中已经提到了Observers,但它们并不是唯一要绘制的元素。 这三个东西被绘制出来:
- 使用
adddata、replaydata和resampledata将数据源添加到 Cerebro - 在策略级别声明的指标(或者使用
addindicator将其添加到 cerebro,这纯粹是为了实验目的,并将指标添加到虚拟策略中) - 使用
addobserver将观察器添加到 cerebro 的选项
观察器是lines对象,它们与strategy同步运行,并且可以访问整个生态系统,以便跟踪Cash和Value等情况
绘图选项
指标和观察器有几个选项,控制它们在图表上的绘制方式。 有三大组:
- 影响整个对象绘图行为的选项
- 影响单个线条绘图行为的选项
- 影响系统范围绘图选项的选项
对象范围的绘图选项
这些由 Indicators 和 Observers 中的数据集控制:
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的默认值。
给这些参数赋值有两种方法。让我们看一下第 1 种方法的 SimpleMovingAverage 实例化:
sma = bt.indicators.SimpleMovingAverage(self.data, period=15, plotname='mysma')
如示例所示,SimpleMovingAverage 构造函数未使用的任何 **kwargs 将被解析(如果可能)为 plotinfo 的值。SimpleMovingAverage 仅定义了一个名为 period 的参数。这意味着 plotname 将与 plotinfo 中同名的参数相匹配。
第 2 种方法:
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时,是否在图表上绘制单个线条名称的图例。
示例:布林带 有 3 条线,但指标是绘制在数据的上方。在图例中仅显示单个名称如BollingerBands看起来更合理,而不是显示 3 条单独线的名称(mid、top、bot)。
对于BuySell观察者的用例,将显示 2 条线和其标记的名称是有意义的:Buy和Sell,以便清楚地告诉最终用户什么是什么。plotlinevalues:控制指标和观察者中的线条图例是否具有最后绘制的值。可以使用每条线的_plotvalue控制单个线的显示方式。plotvaluetags:控制是否在线条右侧绘制带有最后值的值标签。可以使用每条线的_plotvaluetag控制单个线的显示方式。plotymargin:在图表上单个子图的顶部和底部添加的边距
这是一个基于 1 的百分比。例如:0.05 -> 5%plothlines:包含在比例尺内需要绘制 水平线 的值的 可迭代对象。
例如,这有助于经典指标,如RSI,通常在70和30处绘制线条的超买,超卖区域。plotyticks:包含在比例尺上必须特别放置值刻度的可迭代对象
例如,为了强制比例尺具有50来识别比例尺的中点。尽管这似乎很明显,指标使用自动缩放机制,如果一个具有0-100比例尺的指标在 30-95 之间定期移动,50可能不明显位于中心。plotyhlines:包含在比例尺上必须绘制水平线的值(在比例尺内)。
这可以同时控制plothlines和plotyticks。
如果上述选项都未定义,则水平线和刻度的放置完全由此值控制
如果上述任何选项被定义,它们将优先于此选项中的值plotforce:有时候,通过匹配数据源和指标等复杂过程,自定义指标可能无法绘制。这是一种最后的手段机制,试图强制绘制。
如果其他方法都失败,请使用它plotmaster:指标/观察者有一个主数据,即其工作的数据。在某些情况下,可能希望使用不同的主数据来绘制它。
一个用例是PivotPoint指标,它是在月度数据上计算的,但是适用于每日数据。只有在每日数据上绘制它才有意义,这是指标有意义的地方。plotylimited:目前仅适用于数据源。如果设置为True(默认值),数据图上的其他线条不会改变比例尺。例如:布林带(顶部和底部)可能远离实际数据源的绝对最小值/最大值。如果设置为\plotlimited=True,这些带子将保持在图表之外,因为数据控制着比例尺。如果设置为False`,这些带子会影响 y 轴比例尺,并在图表上可见。
一个用例是PivotPoint指标,它是在月度数据上计算的,但是适用于每日数据。只有在每日数据上绘制它才有意义,这是指标有意义的地方。
线条特定的绘图选项
指标/观察者有线条,如何绘制这些线条可以通过plotlines对象进行影响。plotlines中指定的大多数选项意味着在绘图时直接传递给matplotlib。因此,文档依赖于已完成的示例。
重要:选项是基于每行指定的。
一些选项由backtrader直接控制。所有这些选项都以下划线(_)开头:
_plotskip(布尔值)指示如果设置为True,则必须跳过特定线条的绘制_plotvalue(布尔值)控制是否在此线条的图例中包含最后绘制的值(默认值为True)_plotvaluetag(布尔值)控制是否绘制带有最后值的右侧标签(默认为True)_name(字符串)用于更改特定线路的绘图名称_skipnan(布尔值,默认值:False):在绘图时跳过NaN值,例如允许绘制由指标生成的两个远点之间的线,其中所有中间值都为NaN(新创建的数据点的默认值)_samecolor(布尔值)这会强制下一行具有与前一行相同的颜色,避免了matplotlib默认的循环遍历颜色映射以绘制每个新绘制的元素的机制_method(字符串)选择matplotlib将用于元素的绘图方法。如果未指定,则将选择最基本的plot方法。
来自MACDHisto的示例。这里histo线路被绘制为bar,这是行业的事实标准。在MACDHisto的定义中可以找到以下定义:
lines = ('histo',) plotlines = dict(histo=dict(_method='bar', alpha=0.50, width=1.0))`
alpha和width是matplotlib的选项_fill_gt/_fill_lt允许在给定线路和之间填充:
- 另一条线路
- 一个数值
- 参数是一个包含 2 个元素的可迭代对象,其中:
- 第一个参数是一个字符串(参考线路名称)或数值
填充将在自身值和线路或数值的值之间完成 - 第二个参数是:
- 一个字符串,带有颜色名称(matplotlib兼容)或十六进制规范(参见matloplit示例)
- 或
- 一个可迭代对象,其中第一个元素是颜色的字符串/十六进制值,第二个元素是指定 alpha 透明度的数值(默认值:
0.20,由绘图方案中的fillalpha控制)
- 示例:
# Fill for myline when above other_line with colour red plotlines = dict( myline=dict(_fill_gt('other_line', 'red')) ) # Fill for myline when above 50 with colour red plotlines = dict( myline=dict(_fill_gt(50, 'red)) ) # Fill for myline when above other_line with colour red and 50% # transparency (1.0 means "no transparency") plotlines = dict( myline=dict(_fill_gt('other_line', ('red', 0.50))) )`
将选项传递给尚未知道的线路
- 使用名称
_X,其中X代表零为基础索引中的数字。这意味着选项适用于线路X
OscillatorMixIn的一个用例:
plotlines = dict(_0=dict(_name='osc'))
如名称所示,这是一个混合类,旨在在多重继承方案(特别是在右侧)中使用。 mixin对来自将成为多重继承混合的其他指标的第一个线路的实际名称(索引从零开始)没有任何了解。
这就是为什么选项被指定为:_0。子类化完成后,结果类的第一行将在图中具有名称osc。
一些绘图线路示例
BuySell观察器包括以下内容:
plotlines = dict( buy=dict(marker='^', markersize=8.0, color='lime', fillstyle='full'), sell=dict(marker='v', markersize=8.0, color='red', fillstyle='full') )
buy和sell线路有一些选项,直接传递给matplotlib以定义marker、markersize、color和fillstyle。所有这些选项都在matplotlib中定义。
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') )
这里使用_name将线路名称重新定义为例如pnlplus变为Positive。其余选项用于matplotlib
DrawDown观察器:
lines = ('drawdown', 'maxdrawdown',) ... plotlines = dict(maxdrawdown=dict(_plotskip='True',))
这个定义了两条线,让最终用户不仅可以访问当前 drawdown 的值,还可以访问其最大值 (maxdrawdown)。但由于 _plotskip=True,后者不会绘制出来
BollingerBands 指标:
plotlines = dict( mid=dict(ls='--'), top=dict(_samecolor=True), bot=dict(_samecolor=True), )
这里 mid 线将以 虚线 样式绘制,而 top 和 bot 线将与 mid 线具有相同的颜色。
Stochastic(在 _StochasticBase 中定义并继承):
lines = ('percK', 'percD',) ... plotlines = dict(percD=dict(_name='%D', ls='--'), percK=dict(_name='%K'))
较慢的线 percD 以 虚线 样式绘制。并且线的名称更改为包含花哨的 % 符号(%K 和 %D),在 Python 中无法在名称定义中使用
控制绘图的方法
处理 Indicators 和 Observers 时,支持以下方法以进一步控制绘图:
_plotlabel(self)应该返回一列东西,以符合将在Indicators或Observer名称后放置在括号中的标签从RSI指标的一个例子:
def _plotlabel(self): plabels = [self.p.period] plabels += [self.p.movav] * self.p.notdefault('movav') return plabels`
- 可以看到这个方法返回:
- 一个
int,表示为RSI配置的周期,如果默认移动平均线已更改,则是特定的类
在后台,两者都将转换为字符串。在 class 的情况下,将努力只打印类的名称,而不是完整的module.name组合。
_plotinit(self)
在绘图开始时调用,执行指标可能需要的任何特定初始化。再次,来自RSI的一个例子:
def _plotinit(self): self.plotinfo.plotyhlines = [self.p.upperband, self.p.lowerband]`
- 这里的代码为
plotyhlines赋值,以在特定y值处绘制水平线(hlines部分)。
参数upperband和lowerband的值将用于此操作,因为参数可以由最终用户更改,所以无法事先知道
BackTrader 中文文档(十二)(2)https://developer.aliyun.com/article/1505309