backtrader 量化回测模块中 cerebro.plot()图像不是很方便使用,所以测试了很多作图相关的模块;
总结:
1.backtrader_bokeh这个应该是一种付费的模块,所以本人没有钱
2. quantstats quantstats
这个模块最关键的是要做索引设置returns.index = returns.index.tz_convert(None)
cerebro.addanalyzer(bt.analyzers.PyFolio, _name='pyfolio')
back = cerebro.run(maxcpus=12,exactbars=True,stdstats=False)
strat = back[0]
portfolio_stats = strat.analyzers.getbyname('pyfolio')
returns, positions, transactions, gross_lev = portfolio_stats.get_pf_items()
returns.index = returns.index.tz_convert(None)
3.backtrader_plotting 是Bokeh专门针对backtrader开发的模块port端口没有办法改变,不方便做成相关服务被flask app调用,只能单独使用https://github.com/verybadsoldier/backtrader_plotting
4.btplotting 这个模块是在backtrader_plotting模块下改进的,可以改变相关端口port,构建单独的新服务被flask app 进行整合,但是不能够适应复杂策略需求,同时在backtrader Bokeh模块下有个小bug需要在处理
5.backtrader_plotly这个模块没有进行相关测试,感觉不太被维护 https://github.com/lamkashingpaul/backtrader_plotly
6.Bokeh这个是backtrader自带的作图模块,上面这些都是基于此模型改进开发的
7.如果想要一个适合自己喜欢那就动手造吧!知乎上的大神做了
Dash plotly https://zhuanlan.zhihu.com/p/98775974
8.折腾案例学习和借鉴,量化大道溜达走起
BTR-E2020 https://github.com/klein203/BTR-E2020
learn_backtrader
https://github.com/jrothschild33/learn_backtrader
from btplotting import BacktraderPlotting, BacktraderPlottingOptBrowser
from btplotting.schemes import Tradimo
def btplotting_results():
result = cerebro.run(optreturn=False)
strat = result[0]
btp = BacktraderPlotting(style='bar', multiple_tabs=True)
browser = BacktraderPlottingOptBrowser(btp, strat,port=9000)
browser.start()
return
from __future__ import (absolute_import, division, print_function,unicode_literals)
import datetime # 用于datetime对象操作
import os.path # 用于管理路径
import sys # 用于在argvTo[0]中找到脚本名称
import backtrader as bt # 引入backtrader框架
import backtrader.feeds as btfeeds
import pandas as pd
import quantstats
import warnings
warnings.filterwarnings('ignore')
import math
# 创建策略
class SmaCross(bt.Strategy):
# 可配置策略参数
params = dict(
pfast=10, # 短期均线周期
pslow=30, # 长期均线周期
poneplot=False, # 是否打印到同一张图
# pstake = 1000 # 单笔交易股票数目
)
def __init__(self):
# self.log_file = open('position_log.txt', 'w') # 用于输出仓位信息
self.inds = dict()
for i, d in enumerate(self.datas):
self.inds[d] = dict()
self.inds[d]['dataclose'] = d.close
self.inds[d]['sma1'] = bt.ind.SMA(d.close, period=self.p.pfast) # 短期均线
self.inds[d]['sma2'] = bt.ind.SMA(d.close, period=self.p.pslow) # 长期均线
self.inds[d]['cross'] = bt.ind.CrossOver(self.inds[d]['sma1'], self.inds[d]['sma2'], plot=False) # 交叉信号
# 跳过第一只股票data,第一只股票data作为主图数据
if i > 0:
if self.p.poneplot:
d.plotinfo.plotmaster = self.datas[0]
def next(self):
for i, d in enumerate(self.datas):
dt, dn = self.datetime.date(), d._name # 获取时间及股票代码
pos = self.getposition(d)
# 买入策略
if not len(pos): # 不在场内,则可以买入
if self.inds[d]['cross'] > 0: # 如果金叉
# self.buy(data = d, size = self.p.pstake) # 买买买
self.buy(data=d) # 买买买
# 止损策略
elif self.inds[d]['cross'] < 0: # 在场内,且死叉
self.close(data=d) # 卖卖卖
elif ((pos.price - pos.adjbase) > 0.3) or ((pos.adjbase - pos.price) > 0.4):
# print("code: {},pos_price:{},today_close:{},value_size{}".format(
# d._name, pos.price, pos.adjbase,pos.size))
self.close(data=d) # 卖卖卖
cerebro = bt.Cerebro()
import tushare as ts
# 初始化pro接口,写自己的免费token
pro = ts.pro_api('******************************')
data = pro.query('stock_basic', exchange='', list_status='L', fields='ts_code')
stk_pools = data.ts_code[:5]
def quantstats_cerebro_plot():
results = cerebro.run(stdstats=False, tradehistory=True) # execute
strat = results[0]
pyfoliozer = strat.analyzers.getbyname('pyfolio')
returns, positions, transactions, gross_lev = pyfoliozer.get_pf_items()
returns.index = returns.index.tz_convert(None)
quantstats.reports.html(returns,output='fstatss.html',download_filename='fstatss.html', title='Returns Sentiment')
return
def bokeh_cerebro_plot():
from backtrader_plotting import Bokeh, OptBrowser
from backtrader_plotting.schemes import Tradimo
from bokeh.io import show, save, output_file
cerebro.run(optreturn=False, tradehistory=True)
fnames = "bt_bokeh_plot.html"
b = Bokeh(style='bar', tabs='multi', filename=fnames) # 黑底,多页
# b=Bokeh(style='bar',scheme=Tradimo()) # 传统白底,单页
# b=Bokeh(style='bar',tabs='multi',scheme=Tradimo()) #传统白底,多页
output_file(fnames, mode='cdn', title='海龟交易策略')
cerebro.plot(b)
return
if __name__ == '__main__':
# 获取数据
for stk_code in stk_pools:
# 拉取数据
df = pro.daily(**{
"ts_code": stk_code,
"trade_date": "",
"start_date": "20180101",
"end_date": "20211231",
"offset": "",
"limit": ""
}, fields=[
"ts_code",
"trade_date",
"open",
"high",
"low",
"close",
"pre_close",
"change",
"pct_chg",
"vol",
"amount"
])
df = df.iloc[::-1]
# tushare数据存入excel后,trade_date变为int类型列,需变成string后转为datatime类型
df.trade_date = pd.to_datetime(df.trade_date.apply(str))
data = btfeeds.PandasData(
dataname=df,
fromdate=datetime.datetime(2018, 1, 1),
todate=datetime.datetime(2021, 12, 31),
timeframe=bt.TimeFrame.Days,
datetime='trade_date',
open='open',
high='high',
low='low',
close='close',
volume='vol',
openinterest=-1)
# 在Cerebro中添加股票数据
cerebro.adddata(data, name=str(stk_code))
# 设置启动资金
cerebro.broker.setcash(100000.0)
# 设置佣金为零
cerebro.broker.setcommission(commission=0.001)
idx = cerebro.addstrategy(SmaCross, poneplot=False) # 添加策略
cerebro.addsizer_byidx(idx, maxRiskSizer)
cerebro.addanalyzer(bt.analyzers.SharpeRatio)
cerebro.addobserver(bt.obs.Broker) # removed below with stdstats=False
cerebro.addobserver(bt.obs.Trades) # removed below with stdstats=False
cerebro.broker.set_coc(True)
cerebro.addanalyzer(bt.analyzers.PyFolio, _name='pyfolio')
cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='SharpeRatio')
cerebro.addanalyzer(bt.analyzers.DrawDown, _name='DW')
cerebro.addanalyzer(bt.analyzers.AnnualReturn, _name='AnnualReturn')
cerebro.addanalyzer(bt.analyzers.Returns, _name='Returns')
cerebro.addanalyzer(bt.analyzers.SQN, _name='SQN')
cerebro.addanalyzer(bt.analyzers.PyFolio, _name='pyfolio')
# 添加观测器observers
cerebro.addobserver(bt.observers.Broker)
cerebro.addobserver(bt.observers.Trades)
cerebro.addobserver(bt.observers.BuySell)
cerebro.addobserver(bt.observers.DrawDown)
cerebro.addobserver(bt.observers.TimeReturn)
cerebro.addobserver(bt.observers.Value)
print('初始资金: %.2f' % cerebro.broker.getvalue())
bokeh_cerebro_plot()
quantstats_cerebro_plot()
print('最终资金: %.2f' % cerebro.broker.getvalue())