失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Backtrader量化回测8——手续费

Backtrader量化回测8——手续费

时间:2021-03-24 14:22:43

相关推荐

Backtrader量化回测8——手续费

Backtrader官方文档:/docu/commission-schemes/commission-schemes/

手续费是交易中必不可少的,尤其当调试策略参数时,结果都差不多,但不同参数导致的换手次数不同,此时手续费的影响就很大了,因此在backtrader中需要在计算时添加手续费

Backtrader 手续费

Backtrader有两种手续费的设置方法:

常见于期货等

此时commission表示每一单位(每一手)的佣金,margin为保证金,mult为杠杆率,name代表是哪一个标的,不同标的可以设置不同的保证金或杠杆率

cerebro.broker.setcommission(commission=2.0, margin=2000.0, mult=10.0, name=None)

上面的代码表示:每一手要交2块钱佣金,2000的保证金,此时带的是10倍杠杆

常见于股票,按照交易金额的百分比收取手续费,如下为万2.5的手续费

cerebro.broker.setcommission(commission=0.0025)

在策略中获得手续费、保证金的各项数值

在策略中使用minfo[None].p得到setcommission()的各项数值在订单中使用m得到订单执行的手续费金额

示例代码

下面的代码会显示保证金(手续费)不足,订单状态是order.Margin

from datetime import datetimeimport backtraderfrom loguru import loggerimport matplotlib.pyplot as pltimport pandas as pdimport efinancedef get_k_data(stock_code, begin: datetime, end: datetime) -> pd.DataFrame:"""根据efinance工具包获取股票数据:param stock_code:股票代码:param begin: 开始日期:param end: 结束日期:return:"""# stock_code = '600519' # 股票代码,茅台k_dataframe: pd.DataFrame = efinance.stock.get_quote_history(stock_code, beg=begin.strftime("%Y%m%d"), end=end.strftime("%Y%m%d"))k_dataframe = k_dataframe.iloc[:, :9]k_dataframe.columns = ['name', 'code', 'date', 'open', 'close', 'high', 'low', 'volume', 'turnover']k_dataframe.index = pd.to_datetime(k_dataframe.date)k_dataframe.drop(['name', 'code', 'date'], axis=1, inplace=True)return k_dataframeclass MyStrategy1(backtrader.Strategy): # 策略def __init__(self):# 初始化交易指令、买卖价格和手续费self.close_price = self.datas[0].close # 这里加一个数据引用,方便后续操作self.sma = backtrader.indicators.SimpleMovingAverage(self.datas[0], period=5) # 借用这个策略,计算5日的均线def notify_order(self, order): # 固定写法,查看订单情况# 查看订单情况if order.status in [order.Submitted, order.Accepted]: # 接受订单交易,正常情况returnif order.status in [pleted]:if order.isbuy():logger.debug('已买入, 购入金额 %.2f' % order.executed.price)elif order.issell():logger.debug('已卖出, 卖出金额 %.2f' % order.executed.price)elif order.status in [order.Canceled, order.Margin, order.Rejected]:logger.debug('订单取消、保证金不足、金额不足拒绝交易')def next(self): # 固定的函数,框架执行过程中会不断循环next(),过一个K线,执行一次next()if self.close_price[0] > self.sma[0]:# 执行买入logger.debug("buy 500 in {}, 预期购入金额 {}, 剩余可用资金 {}", self.datetime.date(), self.data.close[0],self.broker.getcash())self.buy(size=self.broker.getcash() / self.datas[0].open[1], price=self.data.close[0])# 执行卖出条件已有持仓,且收盘价格跌破5日均线if self.position:if self.close_price[0] < self.sma[0]:# 执行卖出logger.debug("sell in {}, 预期卖出金额 {}, 剩余可用资金 {}", self.datetime.date(), self.data.close[0],self.broker.getcash())self.sell(size=500, price=self.data.close[0])if __name__ == '__main__':# 获取数据start_time = datetime(, 1, 1)end_time = datetime(, 1, 1)dataframe = get_k_data('600519', begin=start_time, end=end_time)# =============== 为系统注入数据 =================# 加载数据data = backtrader.feeds.PandasData(dataname=dataframe, fromdate=start_time, todate=end_time)# 初始化cerebro回测系统cerebral_system = backtrader.Cerebro() # Cerebro引擎在后台创建了broker(经纪人)实例,系统默认每个broker的初始资金量为10000# 将数据传入回测系统cerebral_system.adddata(data) # 导入数据,在策略中使用 self.datas 来获取数据源# 将交易策略加载到回测系统中cerebral_system.addstrategy(MyStrategy1)# =============== 系统设置 ==================# 设置启动资金为 100000start_cash = 1000000cerebral_system.broker.setcash(start_cash)# 设置手续费 万2.5cerebral_system.broker.setcommission(commission=0.00025)logger.debug('初始资金: {} 回测期间:from {} to {}'.format(start_cash, start_time, end_time))# 运行回测系统cerebral_system.run()# 获取回测结束后的总资金portvalue = cerebral_system.broker.getvalue()pnl = portvalue - start_cash# 打印结果logger.debug('净收益: {}', pnl)logger.debug("总资金: {}", portvalue)

所以在处理交易的时候需要预留一部分手续费,比如,修改购买的代码为:

size = self.broker.getcash() * (1 - minfo[None].mission) / self.datas[0].close

这样就可以用减去手续费后的钱购买

from datetime import datetimeimport backtraderfrom loguru import loggerimport pandas as pdimport efinancedef get_k_data(stock_code, begin: datetime, end: datetime) -> pd.DataFrame:"""根据efinance工具包获取股票数据:param stock_code:股票代码:param begin: 开始日期:param end: 结束日期:return:"""# stock_code = '600519' # 股票代码,茅台k_dataframe: pd.DataFrame = efinance.stock.get_quote_history(stock_code, beg=begin.strftime("%Y%m%d"), end=end.strftime("%Y%m%d"))k_dataframe = k_dataframe.iloc[:, :9]k_dataframe.columns = ['name', 'code', 'date', 'open', 'close', 'high', 'low', 'volume', 'turnover']k_dataframe.index = pd.to_datetime(k_dataframe.date)k_dataframe.drop(['name', 'code', 'date'], axis=1, inplace=True)return k_dataframeclass MyStrategy1(backtrader.Strategy): # 策略def __init__(self):# 初始化交易指令、买卖价格和手续费self.close_price = self.datas[0].close # 这里加一个数据引用,方便后续操作self.sma = backtrader.indicators.SimpleMovingAverage(self.datas[0], period=5) # 借用这个策略,计算5日的均线def notify_order(self, order): # 固定写法,查看订单情况# 查看订单情况if order.status in [order.Submitted, order.Accepted]: # 接受订单交易,正常情况returnif order.status in [pleted]:if order.isbuy():logger.debug('已买入, 购入金额 {} 手续费 {}', order.executed.value, m)elif order.issell():logger.debug('已卖出, 卖出金额 {} 手续费 {}', order.executed.value, m)elif order.status in [order.Canceled, order.Margin, order.Rejected]:logger.debug('订单取消、保证金不足、金额不足拒绝交易')def next(self): # 固定的函数,框架执行过程中会不断循环next(),过一个K线,执行一次next()if self.close_price[0] > self.sma[0]:# 执行买入# 获得默认的保证金:minfo[None].missionsize = self.broker.getcash() * (1 - minfo[None].mission) / self.datas[0].closeself.buy(size=size, price=self.data.close[0])# 执行卖出条件已有持仓,且收盘价格跌破5日均线if self.position:if self.close_price[0] < self.sma[0]:# 执行卖出self.sell(size=self.getpositionbyname(self.data._name).size, price=self.data.close[0])if __name__ == '__main__':# 获取数据start_time = datetime(, 1, 1)end_time = datetime(, 1, 1)dataframe = get_k_data('600519', begin=start_time, end=end_time)# =============== 为系统注入数据 =================# 加载数据data = backtrader.feeds.PandasData(dataname=dataframe, fromdate=start_time, todate=end_time)# 初始化cerebro回测系统cerebral_system = backtrader.Cerebro() # Cerebro引擎在后台创建了broker(经纪人)实例,系统默认每个broker的初始资金量为10000# 将数据传入回测系统cerebral_system.adddata(data) # 导入数据,在策略中使用 self.datas 来获取数据源# 将交易策略加载到回测系统中cerebral_system.addstrategy(MyStrategy1)# =============== 系统设置 ==================# 设置启动资金为 100000start_cash = 1000000cerebral_system.broker.setcash(start_cash)# 设置手续费 万2.5cerebral_system.broker.setcommission(commission=0.00025)logger.debug('初始资金: {} 回测期间:from {} to {}'.format(start_cash, start_time, end_time))# 运行回测系统cerebral_system.run()# 获取回测结束后的总资金portvalue = cerebral_system.broker.getvalue()pnl = portvalue - start_cash# 打印结果logger.debug('净收益: {}', pnl)logger.debug("总资金: {}", portvalue)

如果觉得《Backtrader量化回测8——手续费》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。