Skip to content

佣金:股票与期货

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

不可知性

在继续之前,让我们记住backtrader试图对数据所代表的内容保持不可知。不同的佣金方案可应用于同一数据集。

让我们看看怎么做。

使用代理快捷方式

这使得最终用户远离CommissionInfo对象,因为可以通过单个函数调用创建/设置佣金方案。在常规的cerebro创建/设置过程中,只需通过broker成员属性添加对setcommission的调用。在与互动经纪人合作时,以下通话为Eurostoxx50期货设定了常规佣金方案:

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

由于大多数用户通常只测试一台仪器,这就是问题的症结所在。如果您对数据馈送给出了一个name,因为在一张图表上同时考虑了多个仪器,那么这个调用可以稍微扩展,如下所示:

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

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

setcommission 参数的含义

  • commission(默认为0.0

    每项行动成本的绝对或百分比货币单位。

    在上述示例中,buy的每份合同为 2.0 欧元,sell的每份合同为 2.0 欧元。

    这里的重要问题是何时使用绝对值或百分比值。

    • 如果margin的计算结果为False(例如为假,0 或无),则认为commission表示price乘以size运算值的百分比

    • 如果margin是其他内容,则认为操作发生在类似futures的仪器上,commission是每个size合同的固定价格

  • margin(默认为None

    使用类似于futures的工具进行操作时所需的保证金。如上所述

    • 如果设置了margin,则commission将被理解为以百分比表示,并应用于buysell操作的price * size组件

    • 如果设置了margin,则commission将被理解为一个固定值,乘以buysell操作的size分量

  • mult(默认值:1.0)

    对于future类工具,这决定了应用于损益计算的乘数。

    这就是为什么期货同时具有吸引力和风险。

  • name(默认为无)

    将佣金方案的应用限制在与name匹配的仪器上

    这可以在创建数据提要期间设置。

    如果未设置,该方案将应用于系统中存在的任何数据。

现在有两个例子:股票与期货

上面的例子:

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

股票的一个例子是:

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

笔记

2nd语法没有设置保证金多笔反向交易者试图通过将佣金视为基于%的方式来实现明智的做法。

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

设立永久佣金计划

通过直接与CommissionInfo类合作,可以创建更持久的佣金方案。用户可以选择在某个地方使用此定义:

import backtrader as bt

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

稍后使用addcommissioninfo将其应用到另一个 Python 模块中:

from mycomm import commEurostoxx50

...

cerebro.broker.addcommissioninfo(commEuroStoxx50, name='Eurostoxxx50') 

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

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 交叉的“真实”比较

使用 SimpleMovingAverage 交叉作为入口/出口信号,相同的数据集将使用类似于futures的佣金方案进行测试,然后使用类似于stocks的佣金方案进行测试。

笔记

期货头寸不仅可以被赋予进入/退出行为,还可以在每次交易中被赋予反转行为。但这个例子是关于比较佣金方案的。

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

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,即可使用类似于stocks的方案运行。

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

期货:

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 

1st作业的价格如下:

  • 买入(执行)->3754.13/卖出(执行)->3786.93

    • 期货损益(含佣金):324.0

    • 股票损益(含佣金):-4.91

嘿佣金已经完全吞噬了stocks业务的所有利润,但这只意味着futures业务的一小部分利润。

2nd操作:

  • 买入(执行)->3863.57/卖出(执行)->>3389.24

    • 期货损益(含佣金):-247.30

    • 股票损益(含佣金):-62.84

futures的负面操作导致咬合明显增大

但是:

  • 期货累计净损益:324.00 + (-247.30) = 76.70

  • 股票累计净损益:(-4.91) + (-62.84) = -67.75

累积效应可以在下面的图表上看到,也可以看到,在全年结束时,期货产生了更大的利润,但也遭受了更大的下降(在更深的水下)

但重要的是:无论是futures还是stocks都可以进行回溯测试。

期货佣金

!image

股票佣金

!image

代码

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(def1.0:应用于资产价值/利润的乘数

  • margin(定义:None:打开/保持操作所需的货币单位数量。仅当类中的最终_stocklike属性设置为False时才适用

  • automargin(定义:False:由get_margin方法自动计算以下保单所需的保证金/担保

    • 如果参数automargin计算为False,则使用参数margin

    • 使用参数mult,如果automargin < 0使用mult * price

    • 使用参数automargin,如果automargin > 0使用automargin * price

  • commtype(定义:None:支持的值为CommInfoBase.COMM_PERC(佣金理解为%)和CommInfoBase.COMM_FIXED(佣金理解为货币单位)

    None的默认值是一个受支持的值,以保持与遗留CommissionInfo对象的兼容性。如果commtype设置为无,则以下情况适用:

    • marginNone:内部_commtype设置为COMM_PERC_stocklike设置为True(按库存百分比操作)

    • margin不是None_commtype设为COMM_FIXED_stocklike设为False(与期货交易的固定 rount 行程佣金一起操作)

    如果该参数被设置为除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,因空头和多头头寸而收取利息。如果 ths 为Trueinterest为非零,则利息将在两个方向上收取

  • leverage(定义:1.0

    与所需现金相关的资产杠杆金额

-`py`股状()

用于类股票/类期货行为的最终值

-“u commtype()

用于 PERC 与固定佣金的最终值

这两个参数在内部使用,而不是声明的参数来启用()

上述对旧版“`CommissionInfo``的兼容性检查()

对象()

类 backtrader.CommissionInfo()

实际佣金方案的基类。

Comminfo Base 的创建是为了为backtrader提供的原始、不完整的支持提供支持。新的佣金方案源自该类,该类子类为CommInfoBase

percabs的默认值也更改为True

参数:

  • percabs(定义:True):当commtype设置为 COMM_PERC 时,参数commission是否必须理解为 XX%或 0.XX

    如果此参数为真:0.XX 如果此参数为假:XX%

获取杠杆()

返回此佣金方案允许的杠杆级别

getsize(价格、现金)

返回以给定价格满足现金操作所需的大小

getoperationcost(尺寸、价格)

返回操作所需的现金量

getvaluesize(大小、价格)

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

getvalue(位置、价格)

返回给定价格的头寸值。对于类似未来的对象,它固定在size * margin

获得利润(价格)

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

  • 如果参数automargin计算为False,则使用参数margin

  • 使用参数mult,即automargin < 0时使用mult * price

  • 使用参数automargin,即automargin > 0时使用automargin * price

佣金(尺寸、价格)

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

_ 获取佣金(规模、价格、伪执行)

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

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

利润和损失(规模、价格、新价格)

返回持仓的实际损益

现金调整(尺寸、价格、新价格)

计算给定差价的现金调整

获取信贷利息(数据、pos、dt)

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

_ 获取信贷利息(数据、大小、价格、天数、dt0、dt1)

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

size > 0的情况下,仅当类interest_long的参数为True时才会调用此方法

计算信贷利率的公式为:

公式: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未在默认实现中使用,而是作为重写方法的额外输入提供


我们一直在努力

apachecn/AiLearning

【布客】中文翻译组