==================
很多同学问如何用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