BackTrader 中文文档(九)(3)

简介: BackTrader 中文文档(九)

BackTrader 中文文档(九)(2)https://developer.aliyun.com/article/1505289

Fillers

原文:www.backtrader.com/docu/filler/

当涉及使用成交量执行订单时,backtrader 经纪人模拟具有默认策略:

  • 忽略成交量

这基于两个前提:

  • 在足够流动的市场中进行交易,以完全吸收一次性 买入/卖出 订单
  • 真实成交量匹配需要真实世界
    快速示例是 Fill or Kill 订单。即使到了 tick 分辨率并且有足够的 fill 量,backtrader 经纪人也无法知道市场上有多少额外的参与者,以区分这样一个订单是否会匹配以坚持 Fill 部分,或者该订单是否应该 Kill

但是 broker 可以接受 Volume Fillers,这些填充器确定在给定时间点使用多少成交量用于 order matching

填充器的签名

backtrader 生态系统中的一个 filler 可以是符合以下签名的任何 callable

callable(order, price, ago)

其中:

  • order 是将要执行的订单
    此对象提供对 data 对象的访问,该对象是操作目标,创建大小/价格,执行价格/大小/剩余大小和其他细节
  • 订单将被执行的 price
  • ago 是在其中查找体积和价格元素的 order 中的 data 的索引
    在几乎所有情况下,这将是 0(当前时间点),但在一种角落情况下,以涵盖 Close 订单,这可能是 -1
    例如,要访问条形图的体积:
barvolume = order.data.volume[ago]` 

可调用对象可以是函数,也可以是例如支持 __call__ 方法的类的实例,如:

class MyFiller(object):
    def __call__(self, order, price, ago):
        pass

向经纪人添加一个 Filler

最直接的方法是使用 set_filler

import backtrader as bt
cerebro = Cerebro()
cerebro.broker.set_filler(bt.broker.fillers.FixedSize())

第二种选择是完全替换 broker,虽然这可能只适用于已重写部分功能的 BrokerBack 的子类:

import backtrader as bt
cerebro = Cerebro()
filler = bt.broker.fillers.FixedSize()
newbroker = bt.broker.BrokerBack(filler=filler)
cerebro.broker = newbroker

示例

backtrader 源代码中包含一个名为 volumefilling 的示例,允许测试一些集成的 fillers(最初全部)

参考资料

class backtrader.fillers.FixedSize()

使用 百分比 的体积返回给定订单的执行大小。

此百分比通过参数 perc 设置

参数:

  • size(默认值:None)要执行的最大尺寸。如果执行时的实际体积小于大小,则也是限制
    如果此参数的值计算为 False,则整个条的体积将用于匹配订单
class backtrader.fillers.FixedBarPerc()

使用条中体积的 百分比 返回给定订单的执行大小。

此百分比通过参数 perc 设置

参数:

  • perc(默认值:100.0)(有效值:0.0 - 100.0
    用于执行订单的成交量栏的百分比
class backtrader.fillers.BarPointPerc()

返回给定订单的执行大小。成交量将在 high-low 范围内均匀分布,使用 minmov 进行分区。

从给定价格的分配交易量中,将使用 perc 百分比

参数:

  • minmov(默认值:0.01
    最小价格变动。用于将范围 - 分割,以在可能的价格之间按比例分配交易量
  • perc(默认值:100.0)(有效值:0.0 - 100.0
    分配给订单执行价格的交易量百分比,用于匹配

位置

原文:www.backtrader.com/docu/position/

通常在策略内部检查资产的持仓情况:

  • position(一种属性)或 getposition(data=None, broker=None)
    这将返回由 cerebro 提供的默认 broker 中策略的 datas[0] 上的位置

一个持仓只是指:

  • 资产持有 size
  • 平均价格为 price

它作为一种状态,并且例如可以用来决定是否要发出订单(例如:仅在没有持仓时才进入多头持仓)

参考:Position

类 backtrader.position.Position(size=0, price=0.0)

保持并更新持仓的大小和价格。该对象与任何资产无关,仅保留大小和价格。

成员属性:

* size (int): current size of the position
* price (float): current price of the position

Position 实例可以使用 len(position) 进行测试,以查看大小是否为空

交易

原文:www.backtrader.com/docu/trade/

交易的定义:

  • 当仪器中的持仓从 0 变为大小 X 时,交易就开始了,大小可以是正的/负的,分别表示多头/空头仓位)
  • 当仓位从 X 变为 0 时,交易关闭。

以下两个动作:

  • 正至负
  • 负至正

实际上被视为:

  1. 一个交易已经关闭(仓位从 X 变为 0)
  2. 一个新交易已经打开(仓位从 0 变为 Y)

交易仅用于信息提供,没有用户可调用的方法。

参考:交易

类 backtrader.trade.Trade(data=None, tradeid=0, historyon=False, size=0, price=0.0, value=0.0, commission=0.0)

跟踪交易的生命周期:大小、价格、佣金(和价值?)

一个交易从 0 开始,可以增加和减少,并且如果回到 0 可以被视为关闭。

交易可以是多头(正大小)或空头(负大小)

一个交易不打算被反转(逻辑上不支持)

成员属性:

  • ref: 唯一的交易标识符
  • status (int): Created、Open、Closed 中的一个
  • tradeid: 在创建订单时传递给订单的交易 id 分组,默认为 0
  • size (int): 交易的当前大小
  • price (float): 交易的当前价格
  • value (float): 交易的当前价值
  • commission (float): 当前累积佣金
  • pnl (float): 交易的当前利润和损失(毛利润)
  • pnlcomm (float): 交易的当前利润和损失减去佣金(净利润)
  • isclosed (bool): 记录最后一个更新是否关闭了交易(将大小设置为 null)
  • isopen (bool): 记录是否有任何更新打开了交易
  • justopened (bool): 如果交易刚刚开启
  • baropen (int): 开启此交易的柱
  • dtopen(float): 交易开启的浮点编码日期时间
  • 使用方法 open_datetime 获取 Python datetime.datetime 或使用平台提供的 num2date 方法
  • barclose (int): 关闭此交易的柱
  • dtclose(float): 交易关闭的浮点编码日期时间
  • 使用方法 close_datetime 获取 Python datetime.datetime 或使用平台提供的 num2date 方法
  • barlen (int): 此交易持续的周期数
  • historyon (bool): 是否记录历史记录
  • history (list): 每个“update”事件更新的列表,包含更新后的状态和更新中使用的参数
    历史记录中的第一个条目是开仓事件,最后一个条目是关闭事件

佣金方案

佣金:股票与期货

原文:www.backtrader.com/docu/commission-schemes/commission-schemes/

不可知论

在继续之前,让我们记住,backtrader试图保持对数据表示的不可知性。 可以将不同的佣金方案应用于相同的数据集。

让我们看看如何做到这一点。

使用经纪商快捷方式

这使得最终用户远离了CommissionInfo对象,因为可以通过单个函数调用来创建/设置佣金方案。 在常规的cerebro创建/设置过程中,只需在broker成员属性上添加一个对setcommission的调用。 以下调用为使用Interactive Brokers时的Eurostoxx50期货设置了一个常规佣金方案:

cerebro.broker.setcommission(commission=2.0, margin=2000.0, mult=10.0)

由于大多数用户通常只会测试单个工具,因此这就是所有的内容。 如果您已为数据源(data feed)指定了name,因为在图表上同时考虑了多个工具,因此可以稍微扩展此调用,如下所示:

cerebro.broker.setcommission(commission=2.0, margin=2000.0, mult=10.0, name='Eurostoxxx50')

在这种情况下,此即时佣金方案仅适用于名称匹配为Eurostoxx50的工具。

设置佣金参数的含义

  • commission(默认值:0.0)绝对或百分比单位中每个操作的货币单位成本。在上面的示例中,每个buy合约的费用为 2.0 欧元,每个sell合约再次为 2.0 欧元。这里重要的问题是何时使用绝对值或百分比值。
  • 如果margin评估为False(例如为 False、0 或 None),则会认为commission表示price乘以size操作值的百分比
  • 如果margin是其他值,则认为操作发生在类似期货的工具上,commission是每个size合约的固定价格
  • margin(默认值:None)使用期货类似工具时需要的保证金。 如上所述
  • 如果未设置**margin**,则将理解commission为以百分比表示,并应用于buysell操作的price * size组件。
  • 如果设置了margin,则将理解commission为固定值,该值将乘以buysell操作的size组件。
  • mult(默认值:1.0)
    对于类似期货的工具,这确定要应用于利润和损失计算的乘数。
    这就是期货同时具有吸引力和风险的原因。
  • name(默认值:无)
    将佣金方案的应用限制为与name匹配的工具
    这可以在数据源创建期间设置。
    如果未设置,该方案将适用于系统中的任何数据。

现在有两个示例:股票 vs 期货

上述期货示例:

cerebro.broker.setcommission(commission=2.0, margin=2000.0, mult=10.0)

以股票为例:

cerebro.broker.setcommission(commission=0.005)  # 0.5% of the operation value

注意

第 2 种语法不设置marginmultbacktrader会尝试通过考虑佣金为来采用智能方法。

要完全指定佣金方案,需要创建CommissionInfo的子类

创建永久委员会方案

可以通过直接使用CommissionInfo类来创建更永久的佣金方案。用户可以选择在某处定义此定义:

import backtrader as bt
commEurostoxx50 = bt.CommissionInfo(commission=2.0, margin=2000.0, mult=10.0)

稍后在另一个 Python 模块中应用它与 addcommissioninfo

from mycomm import commEurostoxx50
...
cerebro.broker.addcommissioninfo(commEuroStoxx50, name='Eurostoxxx50')

CommissionInfo是一个对象,它使用与backtrader环境中的其他对象相同的params声明。因此,以上内容也可以表示为:

import backtrader as bt
class CommEurostoxx50(bt.CommissionInfo):
    params = dict(commission=2.0, margin=2000.0, mult=10.0)

以后:

from mycomm import CommEurostoxx50
...
cerebro.broker.addcommissioninfoCommEuroStoxx50(), name='Eurostoxxx50')

现在进行与 SMA 交叉的“真实”比较

使用简单移动平均线交叉作为入/出信号,同一数据集将使用期货类似的佣金方案进行测试,然后使用类似于股票的方案进行测试。

注意

期货持仓不仅可以给出进入/退出行为,还可以在每次发生时进行反转行为。但这个示例是关于比较委员会方案的。

代码(请参阅底部的完整策略)是相同的,可以在定义策略之前选择方案。

futures_like = True
if futures_like:
    commission, margin, mult = 2.0, 2000.0, 10.0
else:
    commission, margin, mult = 0.005, None, 1

只需将futures_like设置为 false 即可运行类似于股票的方案。

已添加一些记录代码以评估不同佣金方案的影响。让我们只关注前两个操作。

对于期货:

2006-03-09, BUY CREATE, 3757.59
2006-03-10, BUY EXECUTED, Price: 3754.13, Cost: 2000.00, Comm 2.00
2006-04-11, SELL CREATE, 3788.81
2006-04-12, SELL EXECUTED, Price: 3786.93, Cost: 2000.00, Comm 2.00
2006-04-12, OPERATION PROFIT, GROSS 328.00, NET 324.00
2006-04-20, BUY CREATE, 3860.00
2006-04-21, BUY EXECUTED, Price: 3863.57, Cost: 2000.00, Comm 2.00
2006-04-28, SELL CREATE, 3839.90
2006-05-02, SELL EXECUTED, Price: 3839.24, Cost: 2000.00, Comm 2.00
2006-05-02, OPERATION PROFIT, GROSS -243.30, NET -247.30

对于股票:

2006-03-09, BUY CREATE, 3757.59
2006-03-10, BUY EXECUTED, Price: 3754.13, Cost: 3754.13, Comm 18.77
2006-04-11, SELL CREATE, 3788.81
2006-04-12, SELL EXECUTED, Price: 3786.93, Cost: 3786.93, Comm 18.93
2006-04-12, OPERATION PROFIT, GROSS 32.80, NET -4.91
2006-04-20, BUY CREATE, 3860.00
2006-04-21, BUY EXECUTED, Price: 3863.57, Cost: 3863.57, Comm 19.32
2006-04-28, SELL CREATE, 3839.90
2006-05-02, SELL EXECUTED, Price: 3839.24, Cost: 3839.24, Comm 19.20
2006-05-02, OPERATION PROFIT, GROSS -24.33, NET -62.84

第一次操作的价格如下:

  • 买入(执行)-> 3754.13 / 卖出(执行)-> 3786.93
  • 期货利润与损失(含佣金):324.0
  • 股票利润与损失(含佣金):-4.91

嘿!!佣金完全吃掉了股票操作的任何利润,但对期货操作只是造成了小小的影响。

第二次操作:

  • 买入(执行)->3863.57/ 卖出(执行)->3389.24
  • 期货利润与损失(含佣金):-247.30
  • 股票利润与损失(含佣金):-62.84

对于这个负操作,期货的影响更大。

但:

  • 期货累积净利润与损失:324.00 + (-247.30) = 76.70
  • 股票累积净利润与损失:(-4.91) + (-62.84) = -67.75

累积效果可以在下面的图表中看到,在完整年份结束时,期货产生了更大的利润,但也遭受了更大的回撤(更深的亏损)

但重要的是:无论是期货还是股票…… 都可以进行回测。

期货佣金

股票佣金

代码

from __future__ import (absolute_import, division, print_function,
                        unicode_literals)
import backtrader as bt
import backtrader.feeds as btfeeds
import backtrader.indicators as btind
futures_like = True
if futures_like:
    commission, margin, mult = 2.0, 2000.0, 10.0
else:
    commission, margin, mult = 0.005, None, 1
class SMACrossOver(bt.Strategy):
    def log(self, txt, dt=None):
  ''' Logging function fot this strategy'''
        dt = dt or self.datas[0].datetime.date(0)
        print('%s, %s' % (dt.isoformat(), txt))
    def notify(self, order):
        if order.status in [order.Submitted, order.Accepted]:
            # Buy/Sell order submitted/accepted to/by broker - Nothing to do
            return
        # Check if an order has been completed
        # Attention: broker could reject order if not enougth cash
        if order.status in [order.Completed, order.Canceled, order.Margin]:
            if order.isbuy():
                self.log(
                    'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                    (order.executed.price,
                     order.executed.value,
                     order.executed.comm))
                self.buyprice = order.executed.price
                self.buycomm = order.executed.comm
                self.opsize = order.executed.size
            else:  # Sell
                self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                         (order.executed.price,
                          order.executed.value,
                          order.executed.comm))
                gross_pnl = (order.executed.price - self.buyprice) * \
                    self.opsize
                if margin:
                    gross_pnl *= mult
                net_pnl = gross_pnl - self.buycomm - order.executed.comm
                self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
                         (gross_pnl, net_pnl))
    def __init__(self):
        sma = btind.SMA(self.data)
        # > 0 crossing up / < 0 crossing down
        self.buysell_sig = btind.CrossOver(self.data, sma)
    def next(self):
        if self.buysell_sig > 0:
            self.log('BUY CREATE, %.2f' % self.data.close[0])
            self.buy()  # keep order ref to avoid 2nd orders
        elif self.position and self.buysell_sig < 0:
            self.log('SELL CREATE, %.2f' % self.data.close[0])
            self.sell()
if __name__ == '__main__':
    # Create a cerebro entity
    cerebro = bt.Cerebro()
    # Add a strategy
    cerebro.addstrategy(SMACrossOver)
    # Create a Data Feed
    datapath = ('../../datas/2006-day-001.txt')
    data = bt.feeds.BacktraderCSVData(dataname=datapath)
    # Add the Data Feed to Cerebro
    cerebro.adddata(data)
    # set commission scheme -- CHANGE HERE TO PLAY
    cerebro.broker.setcommission(
        commission=commission, margin=margin, mult=mult)
    # Run over everything
    cerebro.run()
    # Plot the result
    cerebro.plot()

参考

类 backtrader.CommInfoBase()

基于委员会方案的基类。

参数:

  • commission(默认值:0.0):以百分比或货币单位表示的基础佣金值
  • mult(默认为1.0):应用于资产的值/利润的乘数
  • margin(默认值:None):需要开设/持有操作的货币单位金额。只有当类中的最终_stocklike属性设置为False时才适用
  • automargin(默认:False):方法get_margin使用的,用于自动计算以下策略所需的保证金/担保
  • 如果参数automargin的评估为False,则使用参数margin
  • 如果automargin < 0,则使用参数multmult * price
  • 如果automargin > 0,则使用参数automarginautomargin * price
  • commtype(默认:None):支持的值为CommInfoBase.COMM_PERC(将佣金理解为%)和CommInfoBase.COMM_FIXED(将佣金理解为货币单位)None的默认值是支持的值,以保持与传统的CommissionInfo对象的兼容性。 如果commtype设置为 None,则适用以下规则:
  • marginNone:内部_commtype设置为COMM_PERC_stocklike设置为True(与股票的百分比方式运作)
  • 如果margin不是None_commtype设置为COMM_FIXED_stocklike设置为False(使用期货的固定来回佣金)
  • 如果此参数设置为None之外的内容,则它将传递给内部的_commtype属性,并且参数stocklike和内部属性_stocklike也是如此
  • stocklike(默认:False):指示工具是否类似于股票或期货(参见上文的commtype讨论)
  • percabs(默认:False):当commtype设置为 COMM_PERC 时,参数commission是否必须理解为 XX%或 0.XX
    如果此参数为True:0.XX 如果此参数为False:XX%
  • interest(默认:0.0
    如果这不是零,则这是持有空头卖出头寸所收取的年息。 这主要是针对股票的空头卖出
    公式:days * price * abs(size) * (interest / 365)
    必须用绝对值指定:0.05 -> 5%
    注意
    通过覆盖方法_get_credit_interest可以更改行为
  • interest_long(默认:False
    某些产品,如 ETF,对空头和多头头寸收取利息。 如果这是True并且interest不为零,则将在两个方向上收取利息
  • leverage(默认:1.0
    对于所需现金的资产的杠杆倍数
- _stocklike()

用于类 Stock-like/Futures-like 行为的最终值

- _commtype()

PERC vs FIXED 佣金的最终值

这两个参数在内部使用,而不是声明的参数,以启用该方法
描述的兼容性检查适用于遗留的CommissionInfo()
对象()
类 backtrader.CommissionInfo()

实际佣金方案的基类。

CommInfoBase 被创建以保持对backtrader提供的原始,不完整的支持的支持。新的佣金方案派生自这个类,这些类是CommInfoBase的子类。

percabs的默认值也更改为True

参数:

  • percabs(默认:True):当commtype设置为 COMM_PERC 时,参数commission是否必须理解为 XX%或 0.XX
    如果此参数为 True:0.XX 如果此参数为 False:XX%
get_leverage()

返回此佣金方案允许的杠杆水平

getsize(price, cash)

返回在给定价格下执行现金操作所需的大小

getoperationcost(size, price)

返回操作将花费的现金金额

getvaluesize(size, price)

返回给定价格的大小值。对于类似期货的对象,它在size * margin处固定。

getvalue(position, price)

返回给定价格的位置值。对于类似期货的对象,它在size * margin处固定。

get_margin(price)

返回给定价格下资产单个项目所需的实际保证金/担保。默认实现具有以下策略:

  • 如果参数automargin评估为False,则使用参数margin
  • 使用参数mult,即如果automargin < 0,则为mult * price
  • 使用参数automargin,即如果automargin > 0,则为automargin * price
getcommission(size, price)

计算给定价格的操作的佣金

_getcommission(size, price, pseudoexec)

计算给定价格的操作的佣金

pseudoexec:如果为 True,则操作尚未执行

profitandloss(size, price, newprice)

返回位置的实际盈亏

cashadjust(size, price, newprice)

计算给定价格差异的现金调整

get_credit_interest(data, pos, dt)

计算卖空或特定产品的信用费用

_get_credit_interest(data, size, price, days, dt0, dt1)

此方法返回经纪人收取的信用利息成本。

如果size > 0,则仅在类的参数interest_longTrue时才调用此方法。

计算信用利率的公式为:

公式:days * price * abs(size) * (interest / 365)

参数:

* `data`: data feed for which interest is charged
* `size`: current position size. > 0 for long positions and < 0 for
  short positions (this parameter will not be `0`)
* `price`: current position price
* `days`: number of days elapsed since last credit calculation
  (this is (dt0 - dt1).days)
* `dt0`: (datetime.datetime) current datetime
* `dt1`: (datetime.datetime) datetime of previous calculation

dt0dt1在默认实现中未被使用,并作为覆盖方法的额外输入提供


BackTrader 中文文档(九)(4)https://developer.aliyun.com/article/1505292

相关文章
|
9月前
BackTrader 中文文档(七)(2)
BackTrader 中文文档(七)
55 3
|
9月前
|
C++ 索引
BackTrader 中文文档(七)(3)
BackTrader 中文文档(七)
56 3
|
9月前
BackTrader 中文文档(八)(2)
BackTrader 中文文档(八)
77 0
BackTrader 中文文档(八)(2)
|
9月前
|
存储 编解码 API
BackTrader 中文文档(四)(1)
BackTrader 中文文档(四)
99 1
|
9月前
|
Python
BackTrader 中文文档(十)(3)
BackTrader 中文文档(十)
160 0
|
9月前
|
索引
BackTrader 中文文档(七)(4)
BackTrader 中文文档(七)
65 0
|
9月前
|
存储 Python
BackTrader 中文文档(八)(1)
BackTrader 中文文档(八)
71 0
|
9月前
|
存储 索引
BackTrader 中文文档(十)(4)
BackTrader 中文文档(十)
60 0
|
9月前
BackTrader 中文文档(八)(3)
BackTrader 中文文档(八)
50 0
|
9月前
BackTrader 中文文档(十)(2)
BackTrader 中文文档(十)
44 0

热门文章

最新文章