用户定义的佣金

CommInfo 对象改造成实际涉及的最重要的部分:

  • 保留原来的CommissionInfo类和行为
  • 为轻松创建用户定义的佣金打开大门
  • 使格式 xx% 成为新佣金方案的默认值,而不是 0.xx(只是个人喜好问题),保持行为可配置

定义佣金计划

它涉及 1 或 2 个步骤

1、子类化CommInfoBase

只需更改默认参数就足够了。backtrader 已经使用模块中存在的一些定义来做到这一点 backtrader.commissions。期货的常规行业标准是每份合约和每轮固定金额。定义可以如下:

class CommInfo_Futures_Fixed(CommInfoBase):
    params = (
        ('stocklike', False),
        ('commtype', CommInfoBase.COMM_FIXED),
    )

对于股票和 perc-wise 佣金:

class CommInfo_Stocks_Perc(CommInfoBase):
    params = (
        ('stocklike', True),
        ('commtype', CommInfoBase.COMM_PERC),
    )

如上所述,此处解释百分比的默认值(作为参数传递commission)是:xx%。如果希望旧的/其他行为0.xx,可以轻松完成:

class CommInfo_Stocks_PercAbs(CommInfoBase):
    params = (
        ('stocklike', True),
        ('commtype', CommInfoBase.COMM_PERC),
        ('percabs', True),
    )

2、覆盖(如果需要)_getcommission方法

定义为:

def _getcommission(self, size, price, pseudoexec):
   '''Calculates the commission of an operation at a given price

   pseudoexec: if True the operation has not yet been executed
   '''

下面的实际示例中的更多详细信息

如何将此应用到平台

一旦有了CommInfoBase子类,诀窍就是使用 broker.addcommissioninfo而不是通常的broker.setcommission. 后者将在内部使用 legacy CommissionInfoObject

做起来比说的容易:

...

comminfo = CommInfo_Stocks_PercAbs(commission=0.005)  # 0.5%
cerebro.broker.addcommissioninfo(comminfo)

addcommissioninfo方法定义如下:

def addcommissioninfo(self, comminfo, name=None):
    self.comminfo[name] = comminfo

设置name意味着该comminfo对象将仅适用于具有该名称的资产。默认值None表示它适用于系统中的所有资产。

一个实际的例子

Ticket #45询问适用于期货的佣金计划,以百分比计算,并使用合约的整个“虚拟”价值的佣金百分比。即:在佣金计算中包括未来乘数。

这应该很容易:

import backtrader as bt

class CommInfo_Fut_Perc_Mult(bt.CommInfoBase):
    params = (
      ('stocklike', False),  # Futures
      ('commtype', bt.CommInfoBase.COMM_PERC),  # Apply % Commission
    # ('percabs', False),  # pass perc as xx% which is the default
    )

    def _getcommission(self, size, price, pseudoexec):
        return size * price * self.p.commission * self.p.mult

将其放入系统:

comminfo = CommInfo_Fut_Perc_Mult(
    commission=0.1,  # 0.1%
    mult=10,
    margin=2000  # Margin is needed for futures-like instruments
)

cerebro.addcommissioninfo(comminfo)

如果首选格式0.xx作为默认值,只需将 param 设置percabs 为True

class CommInfo_Fut_Perc_Mult(bt.CommInfoBase):
    params = (
      ('stocklike', False),  # Futures
      ('commtype', bt.CommInfoBase.COMM_PERC),  # Apply % Commission
      ('percabs', True),  # pass perc as 0.xx
    )

comminfo = CommInfo_Fut_Perc_Mult(
    commission=0.001,  # 0.1%
    mult=10,
    margin=2000  # Margin is needed for futures-like instruments
)

cerebro.addcommissioninfo(comminfo)

这一切都应该解决问题。

解释pseudoexec

让我们回顾一下 的定义_getcommission

def _getcommission(self, size, price, pseudoexec):
    '''Calculates the commission of an operation at a given price

    pseudoexec: if True the operation has not yet been executed
    '''

arg的目的pseudoexec可能看起来晦涩难懂,但它是有目的的。

  • 平台可能会调用该方法来进行可用现金的预计算和一些其他任务
  • 这意味着该方法可能(并且实际上会)使用相同的参数多次调用

pseudoexec指示调用是否对应于订单的实际执行。尽管乍一看这似乎并不“相关”,但如果考虑到以下情况:

  • 一旦谈判合约数量超过5000个单位,经纪人提供期货往返佣金50%的折扣

    在这种情况下,如果pseudoexec不存在,对该方法的多次非执行调用将迅速触发折扣已到位的假设。

让场景发挥作用:

import backtrader as bt

class CommInfo_Fut_Discount(bt.CommInfoBase):
    params = (
      ('stocklike', False),  # Futures
      ('commtype', bt.CommInfoBase.COMM_FIXED),  # Apply Commission

      # Custom params for the discount
      ('discount_volume', 5000),  # minimum contracts to achieve discount
      ('discount_perc', 50.0),  # 50.0% discount
    )

    negotiated_volume = 0  # attribute to keep track of the actual volume

    def _getcommission(self, size, price, pseudoexec):
        if self.negotiated_volume > self.p.discount_volume:
           actual_discount = self.p.discount_perc / 100.0
        else:
           actual_discount = 0.0

        commission = self.p.commission * (1.0 - actual_discount)
        commvalue = size * price * commission

        if not pseudoexec:
           # keep track of actual real executed size for future discounts
           self.negotiated_volume += size

        return commvalue

目的和存在pseudoexec希望现在很清楚。

CommInfoBase 文档字符串和参数

请参阅佣金:股票与期货以供参考 CommInfoBase

评论被关闭。