用户定义佣金#

重新设计CommInfo对象以实际运行的最重要部分包括:

  • 保留原始的“CommissionInfo”类和行为

  • 为用户定义的佣金提供便利性

  • 将格式xx%设置为新的佣金方案的默认值,而不是0.xx(只是个人喜好),保持行为可配置

备注

有关参数参考,请参阅“CommInfoBase”的文档字符串如下所示

定义佣金方案#

涉及1或2个步骤

  1. 继承“CommInfoBase”

    只需更改默认参数可能就足够了。“backtrader”已经在模块“backtrader.commissions”中对一些定义进行了更改。期货的常规行业标准是每个合同和每轮固定金额。可以通过以下方式进行定义:```python

class CommInfo_Futures_Fixed(CommInfoBase):
params = (

(‘stocklike’, False), (‘commtype’, CommInfoBase.COMM_FIXED),

)

# 对于股票和基于百分比的佣金 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):

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

pseudoexec: 如果为True,则表示此操作尚未执行 ‘’’

# 更多实际示例的详细信息请参见下面如何在平台上应用此功能#

一旦创建了 CommInfoBase 的子类,关键是使用 broker.addcommissioninfo 而不是通常的 broker.setcommission 。后者将在内部使用传统的 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 <https://github.com/mementum/backtrader/issues/45> _询问一种针对期货的佣金模式,按百分比计算,并在佣金计算中使用合同的整个“虚拟”价值。即:佣金计算中包含期货乘数。应该很简单:

``` python import backtrader as bt

class CommInfo_Fut_Perc_Mult(bt.CommInfoBase):
params = (

(‘stocklike’, False), # 期货 (‘commtype’, bt.CommInfoBase.COMM_PERC), # 应用百分比佣金

)

def _getcommission(self, size, price, pseudoexec):

return size * price * self.p.commission * self.p.mult

```

将其纳入系统中:

``` python comminfo = CommInfo_Fut_Perc_Mult(

commission=0.1, # 0.1% mult=10, margin=2000 # 期货类似工具需要保证金

)

cerebro.addcommissioninfo(comminfo) ```

如果将格式 0.xx 设为默认值,只需将参数 percabs 设置为 True

``` python class CommInfo_Fut_Perc_Mult(bt.CommInfoBase):

params = (

(‘stocklike’, False), # 期货 (‘commtype’, bt.CommInfoBase.COMM_PERC), # 应用百分比佣金 (‘percabs’, True), # 将 percentage 设为 0.xx

)

comminfo = CommInfo_Fut_Perc_Mult(

commission=0.001, # 0.1% mult=10, margin=2000 # 期货类似工具需要保证金

) ```cerebro.addcommissioninfo(comminfo)

这一切都应该能解决问题。

解释“pseudoexec”#

让我们回顾一下 _getcommission 的定义:

def _getcommission(self, size, price, pseudoexec):

‘’’根据给定价格计算操作的手续费

pseudoexec: 如果为True,则表示该操作尚未执行 ‘’’

pseudoexec 参数的目的可能看起来有些模糊,但它确实有一个用途。

  • 平台可能会调用该方法来预先计算可用现金和其他一些任务

  • 这意味着该方法可能会(实际上也会)以相同的参数多次调用

pseudoexec 表示该调用是否对应于订单的实际执行。虽然乍一看可能看起来不相关,但考虑到以下情况,它是相关的: - 当交易合约的数量超过5000单位时,经纪人会提供50%的期货往返佣金折扣。

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

让场景起作用:

import backtrader as bt

class CommInfo_Fut_Discount(bt.CommInfoBase):
params = (

(‘stocklike’, False), # 期货 (‘commtype’, bt.CommInfoBase.COMM_FIXED), # 应用佣金

# 折扣的自定义参数 (‘discount_volume’, 5000), # 达到折扣的最少合约数 (‘discount_perc’, 50.0), # 50.0% 的折扣

)

negotiated_volume = 0 # 用来跟踪实际合约数量的属性

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:

# 为了未来折扣保持跟踪实际的执行数量 self.negotiated_volume += size返回 commvalue

现在希望对 pseudoexec 的目的和用途有了一定的了解。

CommInfoBase文档字符串和参数#

参见:佣金: 股票 vs 期货 获取 CommInfoBase 的参考资料。