Backtrader 策略实例,该部分内容通过使用backtrader对常用的策略实例的编写,提高和熟悉backtrader的实际场景的使用。
[Backtrader]实例:均线策略
[Backtrader] 实例:MACD策略
[Backtrader] 实例:KDJ 策略
[Backtrader] 实例:RSI 与 EMA 结合
[Backtrader] 实例:SMA自定义数据源
[Backtrader] 实例:海龟策略
[Backtrader] 实例:网格交易
[Backtrader] 实例: 配对交易
本系列是使用Backtrader在量化领域的学习与实践,着重介绍Backtrader的使用。Backtrader 中几个核心组件:
- Cerebro:BackTrader的基石,所有的操作都是基于Cerebro的。
- Feed:将运行策略所需的基础数据加载到Cerebro中,一般为K线数据。
- Indicator:BackTader自带的指标,并集成了talib中的指标。我们也可以选择继承一个Indicator实现自己的指标。
- Strategy:交易策略。这里是整个过程中最复杂的部分,需要我们计算买入/卖出信号。
- Analyzer:分析器,以图形和风险收益等指标对交易策略的回测结果进行分析评价。
- Order:订单,记录了与当前订单相关的所有数据。
- Trader:交易,记录了与当前交易相关的所有数据。
- Position:持仓,记录了与当前持仓相关的所有数据。
- Broker:可以理解成经纪人,整个策略的初始资金、交易费率、滑点等参数需要通过Broker进行设置。
- Observer:观察者,对数据进行监控观察,比如资金曲线等等。
- Plotting:可视化组件
本次介绍Backtrader中Commission Schemes 模块,其是Backtrader核心模块之一, 时通过Commission Schemes模块进行交易税费、佣金、手续费设置。
在使用Backtrader时,结合量化策略编写过程通常会考虑:
- Commission Schemes 交易税费如何设置?
- 支持哪些标的?不同标的设置差异在哪里?
- 对于策略回测,在多资产组合情况下如何设置交易税费?
- …
Commission Schemes 交易税费
Broker模拟经纪商交易系统相关功能,支持不同订单类型、对交易进行“验资验券”,并模拟交易所进行交易撮合。最常见的有初始资金、交易税费、滑点、期货保证金比率等。而期货保证金比率、佣金、手续费等在Commission Schemes模块中进行设置。
在 Backtrader 中,从数据准备、策略编制、策略回测到绩效分析,整个回测流程各个模块相互协调,从交易流程大致如下:
- step1:设置交易条件:初始资金、交易税费、滑点、成交量限制等;
- step2:在 Strategy 策略逻辑中下达交易指令 buy、sell、close,或取消交易 cancel;
- step3:Order 模块会解读交易订单,解读的信息将交由经纪商 Broker 模块处理;
- step4:经纪商 Broker 会根据订单信息检查订单并确定是否接收订单;
- step5:经纪商 Broker 接收订单后,会按订单要求撮合成交 trade,并进行成交结算;
- step6:Order 模块返回经纪商 Broker 中的订单执行结果。
在backtrader中做策略回测,在策略运行前,Broker实现账户资金、份额等信息初始化,同时通过Commission Schemes模块进行交易税费、佣金、手续费设置。
交易中的交易税费
在常规情况,交易过程总体金额包含交易费用还有佣金、手续费等,在不同市场不同的标的的费用收费规则不同,以股票、期货为例:
-
股票:沪深A股市场收费项包括:佣金、交易经手费、证券证管费、登记过户费、印花税;
- 佣金:采用双向收费(买卖),收取比例也存在一定的浮动,通常在不得超过成交金额的3‰;券商可以在此区间*调整,最低5元起,即单笔交易佣金不满5元按5元收取
- 交易经手费:由交易所收取,买卖双向收取,成交金额的万分之0.341(0.0341‰);
- 证券证管费:由券商代收后交给证监会,买卖双向收取。收费标准为成交金额的万分之0.2(0.02‰)
- 登记过户费:由券商代收后交给中国证券登记结算有限公司,买卖双向收取,收费标准为成交金额的万分之0.1(0.01‰)
- 印花税:仅在卖出时收取,税率万分之5(0.5‰);
假设沪市买入1万元:
- 券商全佣金 = 交易经手费(万分之0.341) + 证券证管费(万分之0.2) + 登记过户费(万分之0.1) + 佣金(万分之0.2)= 0.341 + 0.2 + 0.1 + 0.2 = 0.841元。由于不满5元,按5元收取。
- 印花税 = 0
假设沪市卖出1万元:
- 券商全佣金 = 交易经手费(万分之0.341) + 证券证管费(万分之0.2) + 登记过户费(万分之0.1) + 佣金(万分之0.2)= 0.341 + 0.2 + 0.1 + 0.2 = 0.841元。由于不满5元,按5元收取。
- 印花税 = 5
-
期货:期货总手续费=交易所手续费+期货公司手续费,交易所手续费一般固定不变,期货公司手续费弹性较大。除了交易费用外,期货交易时还需上交一定比例的保证金 。
-
交易所手续费一般固定不变,但不同期货品种的收取方式不相同,有的按照固定费用收取,有的按成交金额的固定百分比收取:合约现价 * 合约乘数 * 手续费费率 。例如:IF(沪深300指数) 采用双向收费,费率为万分之0.23;TL(30年期国债)采用单边收费,费用3元。
-
期货公司手续费弹性较大
-
税费模式
在Backtrader中,通过 Commission Schemes 进行交易费设置,也可以自定义费用函数。在Commission Schemes中,
- 根据交易品种:提供 股票(stocklike) 和 期货 两类的税费收取模式;
- 根据计算方式不同:提供 PERC百分比模式 和 FIXED固定收费模式;
目前Backtrader,品种(股票、期货)下可支持的模式:
-
股票
- 百分比 + 无保证金
-
期货
- 固定收费 + 保证金
- 百分比 + 保证金
# 期货品种,手续费/佣金为2.0,保证金为2000.0 ,乘数10.0 , stocklike = False 表示期货模式
cerebro.broker.setcommission(commission=2.0, margin=2000.0, mult=10.0,stocklike=False)
# 股票品种,佣金为:0.5%。
cerebro.broker.setcommission(commission=0.005,stocklike=True)
Backtrader中3种税费设置方式
在Backtrader中,提供了3种税费设置方式,分别为setcommission()、addcommissioninfo()、BackBroker():
setCommission()的参数
setCommission()中常用的参数:
def setcommission(self,
commission=0.0, margin=None, mult=1.0,
commtype=None, percabs=True, stocklike=False,
interest=0.0, interest_long=False, leverage=1.0,
automargin=False,
name=None):
-
commission(默认: 0.0) 手续费/佣金
股票:如果stocklike=True,则commission代表百分比值;
期货:如果stocklike=False,margin为0 或 None,则commission代表每份合约固定费用;
-
margin(默认: None) 保证金/保证金比例
如果 margin 为默认值,则commission代表百分比,否则代表固定费用,在双向操作(买入、卖出)计算相应费用;
-
mult(默认: 1.0) 乘数
mult 乘数 专用于期货品种的参数。
-
commtype(默认:None) 交易费用计算方式:COMM_PERC、COMM_FIXED
若赋值为COMM_PERC 百分比费用方式,COMM_FIXED 固定费用方式;若为None,bt将更加margin取值来确定类型
-
percabs(默认:True)
当交易费用以百分比模式下时,commission 是否以 % 形式。若为True,则表示不以% 为单位,采用0.xx形式;若False,则表示以 % 为单位,采用x% 形式;
-
stocklike(默认:False)是否为股票模式
是否为股票模式,该模式通常由margin和commtype参数决定。margin=None或COMM_PERC模式时,就会stocklike=True,对应股票手续费;margin设置了取值或COMM_FIXED模式时,就会stocklike=False,对应期货手续费
-
interest(默认:0.0)空头头寸的年化利息
计算持有的空头头寸的年化利息 = days * price * abs(size) * (interest / 365)
-
interest_long(默认:False)
计算持有的多头头寸的年化利息
-
leverage(默认1.0)杠杆比率
交易时按该杠杆调整所需现金
-
automargin(默认: False) 自动计算保证金
如果False,则通过margin参数确定保证金;如果automargin<0,通过mult * price 确定保证金;如果automargin>0,如果automargin * price 确定保证金
-
name(默认: None)
将佣金计划的适用范围限定为与名称匹配的工具,如果取值为None,则默认作用于所有数据集(也就是作用于所有assets)。
addcommissioninfo
通过继承CommInfoBase自定义交易费用子类,再通过addcommissioninfo方法实例
# 在继承 CommInfoBase 基础类的基础上自定义交易费用
class MyCommission(bt.CommInfoBase):
# 对应 setcommission 中介绍的那些参数,也可以增添新的全局参数
params = ((xxx, xxx),)
# 自定义交易费用计算方式
def _getcommission(self, size, price, pseudoexec):
pass
# 自定义佣金计算方式
def get_margin(self,price):
pass
...
# 实例化
mycomm = MyCommission(...)
cerebro = bt.Cerebro()
# 添加进 broker
cerebro.broker.addcommissioninfo(mycomm, name='xxx') # name 用于指定该交易费用函数适用的标的
BackBroker
在股票回测中,通过BackBroker全局设置交易佣金费用
# 设置 0.0002 = 0.02% 的手续费
cerebro.broker = bt.brokers.BackBroker(commission= 0.0002)
自定义税费函数
Backtrader 中默认配置了 2 种费用:“股票百分比费用”和“期货固定费用”。
通过继承CommInfoBase自定义交易费用子类,再定义相关税费参数,重写_getcommission方法,最后通过broker.addcommissioninfo方法。
- 继承CommInfoBase
-
期货固定费用
class CommInfo_Futures_Fixed(CommInfoBase): params = ( ('stocklike', False), ('commtype', CommInfoBase.COMM_FIXED), )
-
股票百分比费用
class CommInfo_Stocks_PercAbs(CommInfoBase): params = ( ('stocklike', True), ('commtype', CommInfoBase.COMM_PERC), ('percabs', True), # pass perc as 0.xx )
-
重写_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 '''
-
通过addcommissioninfo调用
comminfo = CommInfo_Stocks_PercAbs(commission=0.005) # 0.5% cerebro.broker.addcommissioninfo(comminfo)
import backtrader as bt
# 自定义期货百分比费用
class CommInfo_Fut_Perc_Mult(bt.CommInfoBase):
params = (
('stocklike', False), # 指定为期货模式
('commtype', bt.CommInfoBase.COMM_PERC), # 使用百分比费用
('percabs', False), # commission 以 % 为单位
)
def _getcommission(self, size, price, pseudoexec):
# 计算交易费用
return (abs(size) * price) * (self.p.commission/100) * self.p.mult
# pseudoexec 用于提示当前是否在真实统计交易费用
# 如果只是试算费用,pseudoexec=False
# 如果是真实的统计费用,pseudoexec=True
comminfo = CommInfo_Fut_Perc_Mult(
commission=0.1, # 0.1%
mult=10,
margin=2000) # 实例化
cerebro.broker.addcommissioninfo(comminfo)
# 上述自定义函数,也可以通过 setcommission 来实现
cerebro.broker.setcommission(commission=0.1, #0.1%
mult=10,
margin=2000,
percabs=False,
commtype=bt.CommInfoBase.COMM_PERC,
stocklike=False)