佣金: 股票 vs 期货#

对于数据代表的含义,“backtrader”试图保持不可知性。 不同的佣金方案可以应用于相同的数据集。

让我们看看如何实现。

使用经纪人快捷方式#

这样可以让最终用户远离“CommissionInfo”对象,因为可以通过单个函数调用创建/设置佣金方案。 在常规的“cerebro”创建/设置过程中,只需在“broker”成员属性上添加一次“setcommission”调用即可。 以下调用在使用“Interactive Brokers”处理“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”匹配的工具。设置佣金参数的含义#

  • commission (默认值: 0.0

    每次操作 所需的货币单位,可以是绝对值或百分比。

    在上面的例子中,每个合同的买入费用为2.0欧元,卖出费用也是2.0欧元。

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

    • 如果 margin 评估为 False (例如,False、0或None),则认为 commission 表示 price 乘以 size 操作值的百分比。

    • 如果 margin 是其他值,则认为操作发生在类似”期货”的工具上,而 commission 是每个 size 合同的固定价格。

  • margin (默认值: None

    使用类似”期货”的工具进行操作时需要的保证金。如上所述

    • 如果没有设置 保证金 ,则会将 commission 理解为百分比,并应用于 price * size 部分的”买入”或”卖出”操作中。- 如果设置了“margin”,则理解“commission”是一个固定值,乘以“buy”或“sell”操作的“size”组成部分

  • “mult”(默认值:1.0)

    对于像期货这样的工具,确定要应用于盈亏计算的乘法因子。

    这就是期货同时具有吸引力和风险的原因。

  • “name”(默认值:None)

    将佣金方案的应用限制在与“name”匹配的工具上

    可以在创建数据源期间设置。

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

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

之前的期货示例::cerebro.broker.setcommission(commission=2.0, margin=2000.0, mult=10.0)

一个股票的例子:

cerebro.broker.setcommission(commission=0.005)  # 交易金额的0.5%

注意

第二种语法没有设置 marginmultbacktrader 会根据佣金来智能计算。

要完全指定佣金计划,需要创建 CommissionInfo 的子类。

创建永久佣金计划#

可以通过直接使用 CommissionInfo 类来创建一个更长期的佣金计划。用户可以选择在某个地方进行定义:

import backtrader as bt

commEurostoxx50 = bt.CommissionInfo(commission=2.0, margin=2000.0, mult=10.0)为了在另一个Python模块中稍后使用 ``addcommissioninfo`` :
```python

from mycomm import commEurostoxx50

cerebro.broker.addcommissioninfo(commEurostoxx50, name=’Eurostoxx50’)

```

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

```python

import backtrader as bt

class CommEurostoxx50(bt.CommissionInfo):

params = dict(commission=2.0, margin=2000.0, mult=10.0)

```

然后:

```python

from mycomm import CommEurostoxx50

```现在使用 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, 买入创建,3757.59
2006-03-10, 买入执行,价格:3754.13,成本:2000.00,佣金 2.00
2006-04-11, 卖出创建,3788.81
2006-04-12, 卖出执行,价格:3786.93,成本:2000.00,佣金 2.00
2006-04-12, 操作利润,总额 328.00,净额 324.00
2006-04-20, 买入创建,3860.00
2006-04-21, 买入执行,价格:3863.57,成本:2000.00,佣金 2.00
2006-04-28, 卖出创建,3839.90
2006-05-02, 卖出执行,价格:3839.24,成本:2000.00,佣金 2.00
2006-05-02, 操作利润,总额 -243.30,净额 -247.30对于股票::

2006-03-09,买入创建,3757.59
2006-03-10,买入执行,价格:3754.13,成本:3754.13,佣金:18.77
2006-04-11,卖出创建,3788.81
2006-04-12,卖出执行,价格:3786.93,成本:3786.93,佣金:18.93
2006-04-12,操作利润,毛利 32.80,净利润 -4.91
2006-04-20,买入创建,3860.00
2006-04-21,买入执行,价格:3863.57,成本:3863.57,佣金:19.32
2006-04-28,卖出创建,3839.90
2006-05-02,卖出执行,价格:3839.24,成本:3839.24,佣金:19.20
2006-05-02,操作利润,毛利 -24.33,净利润 -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

累积影响可以从下面的图表中看出,同时也可以看出在全年末,期货产生了更大的利润,但也遭受了更大的回撤(承压较大)

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

期货佣金#

股票佣金#

代码#


class backtrader.CommInfoBase(*args, **kwargs)#

Base Class for the Commission Schemes.

Params:

  • commission (def: 0.0): base commission value in percentage or monetary units

  • mult (def 1.0): multiplier applied to the asset for value/profit

  • margin (def: None): amount of monetary units needed to open/hold an operation. It only applies if the final _stocklike attribute in the class is set to False

  • automargin (def: False): Used by the method get_margin to automatically calculate the margin/guarantees needed with the following policy

    • Use param margin if param automargin evaluates to False

    • Use param mult * price if automargin < 0

    • Use param automargin * price if automargin > 0

  • commtype (def: None): Supported values are CommInfoBase.COMM_PERC (commission to be understood as %) and CommInfoBase.COMM_FIXED (commission to be understood as monetary units)

    The default value of None is a supported value to retain compatibility with the legacy CommissionInfo object. If commtype is set to None, then the following applies:

    • margin is None: Internal _commtype is set to COMM_PERC and _stocklike is set to True (Operating %-wise with Stocks)

    • margin is not None: _commtype set to COMM_FIXED and _stocklike set to False (Operating with fixed rount-trip commission with Futures)

    If this param is set to something else than None, then it will be passed to the internal _commtype attribute and the same will be done with the param stocklike and the internal attribute _stocklike

  • stocklike (def: False): Indicates if the instrument is Stock-like or Futures-like (see the commtype discussion above)

  • percabs (def: False): when commtype is set to COMM_PERC, whether the parameter commission has to be understood as XX% or 0.XX

    If this param is True: 0.XX If this param is False: XX%

  • interest (def: 0.0)

    If this is non-zero, this is the yearly interest charged for holding a short selling position. This is mostly meant for stock short-selling

    The formula: days * price * abs(size) * (interest / 365)

    It must be specified in absolute terms: 0.05 -> 5%

    备注

    the behavior can be changed by overriding the method: _get_credit_interest

  • interest_long (def: False)

    Some products like ETFs get charged on interest for short and long positions. If ths is True and interest is non-zero the interest will be charged on both directions

  • leverage (def: 1.0)

    Amount of leverage for the asset with regards to the needed cash

- ``_stocklike``

Final value to use for Stock-like/Futures-like behavior

- ``_commtype``

Final value to use for PERC vs FIXED commissions

This two are used internally instead of the declared params to enable the
compatibility check described above for the legacy ``CommissionInfo``
object#
class backtrader.CommissionInfo(*args, **kwargs)#

Base Class for the actual Commission Schemes.

CommInfoBase was created to keep suppor for the original, incomplete, support provided by backtrader. New commission schemes derive from this class which subclasses CommInfoBase.

The default value of percabs is also changed to True

Params:

  • percabs (def: True): when commtype is set to COMM_PERC, whether the parameter commission has to be understood as XX% or 0.XX

    If this param is True: 0.XX If this param is False: XX%

get_leverage()#

Returns the level of leverage allowed for this comission scheme

getsize(price, cash)#

Returns the needed size to meet a cash operation at a given price

getoperationcost(size, price)#

Returns the needed amount of cash an operation would cost

getvaluesize(size, price)#

Returns the value of size for given a price. For future-like objects it is fixed at size * margin

getvalue(position, price)#

Returns the value of a position given a price. For future-like objects it is fixed at size * margin

get_margin(price)#

Returns the actual margin/guarantees needed for a single item of the asset at the given price. The default implementation has this policy:

  • Use param margin if param automargin evaluates to False

  • Use param mult * price if automargin < 0

  • Use param automargin * price if automargin > 0

getcommission(size, price)#

Calculates the commission of an operation at a given price

_getcommission(size, price, pseudoexec)#

Calculates the commission of an operation at a given price

pseudoexec: if True the operation has not yet been executed

profitandloss(size, price, newprice)#

Return actual profit and loss a position has

cashadjust(size, price, newprice)#

Calculates cash adjustment for a given price difference

get_credit_interest(data, pos, dt)#

Calculates the credit due for short selling or product specific

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

This method returns the cost in terms of credit interest charged by the broker.

In the case of size > 0 this method will only be called if the parameter to the class interest_long is True

The formulat for the calculation of the credit interest rate is:

The formula: days * price * abs(size) * (interest / 365)

Params:
  • 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

dt0 and dt1 are not used in the default implementation and are provided as extra input for overridden methods