==================
很多同学问如何用backtrader进行期货回测。以下给个例子,与普通股票回测不同的是佣金的设置方式。
1 佣金类设置
import datetime  # For datetime objects
import backtrader as bt
import backtrader.feeds as btfeeds
import backtrader.indicators as btind
import pandas as pd
import numpy as np
from datetime import datetime
class Par_SAR(bt.Strategy):
    params = (('period', 2), ('af', 0.02), ('afmax', 0.2))
    def __init__(self):
       pass
       
if __name__ == '__main__':
    # rb 15 min data 
    brf_min_bar = bt.feeds.GenericCSVData(
        dataname='E:/Quant/Backtrader/backtrader-master/China_Market/data/rb_15m.csv',
        timeframe=bt.TimeFrame.Minutes,
        #fromdate=datetime.datetime(2019, 5, 1),
        #todate=datetime.datetime(2020, 6, 1),
        nullvalue=0.0,
        dtformat=('%Y-%m-%d %H:%M:%S'),
        datetime=1,
        time=-1,
        high=4,
        low=5,
        open=3,
        close=6,
        volume=-1,
        # openinterest=-1
    )
    # Add the Data Feed to Cerebro
    cerebro.adddata(brf_min_bar)
    #cerebro.resampledata(brf_min_bar, timeframe=bt.TimeFrame.Days)
    # Add strategy
    cerebro.addstrategy(Par_SAR)
    # 设置初始资本为100,000
    cerebro.broker.setcash(1000000.0) 
    # 设置期货佣金模式
    cerebro.broker.setcommission(commission=0.0001, margin=2800.0, mult=10.0)
    cerebro.run()
以上佣金设置,实际上使用了backtrader内置的佣金类CommInfoBase,该类可设置的参数如下。当然,多数参数采用默认值即可,无需设置,如以上案例,只设置了3个参数,其他都是默认值。以下参数中的leverage,可能与期货也有关系。另外,该类也可以考虑借款利息。
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
 
 and use
 
 mult * price
 
 if
 
 automargin < 0
 
- 
       Use param
 
 automargin
 
 and use
 
 automargin * price
 
 if
 
 automargin > 0
 
 
- 
       Use param
- 
     
 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%
 
 Note
 
 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
可以从佣金基类派生自己的佣金类,以满足自己的要求,比如,有人期望佣金率不仅依赖交易金额,还依赖乘数mult,则可定义新的佣金类如下
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)2 拼接滚动合约
另外,backtrader还允许将不同到期日的期货合约滚动拼接起来形成连续期货(The RollOver Data Feed),例子如下
import backtrader as bt
cerebro = bt.Cerebro()
data0 = bt.feeds.MyFeed(dataname='Expiry0')
data1 = bt.feeds.MyFeed(dataname='Expiry1')
...
dataN = bt.feeds.MyFeed(dataname='ExpiryN')
drollover = bt.feeds.RollOver(data0, data1, ..., dataN, dataname='MyRoll', **kwargs)
cerebro.adddata(drollover)
cerebro.run()
    RollOver类有两个参数控制如何拼接合约,
    
     checkdate
    
    和
    
     checkcondition
    
    。详细描述参考
    
     Data Feeds – Rollover – Backtrader
    
   
 
