backtrader量化回测模块中cerebro.plot像不是很方便使用,所以测试了很多作相关的模块;总结:backtrader_bokeh这个应该是一种付费的模块,所以本人没有钱quantstatsquantstats这个模块最关键的是要做索引设置returns.index=returns.index.tz_convert
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)
backtrader_plotting是Bokeh专门针对backtrader开发的模块port端口没有办法改变,不方便做成相关服务被flaskapp调用,只能单独使用https://github.com/verybadsoldier/backtrader_plotting
btplotting这个模块是在backtrader_plotting模块下改进的,可以改变相关端口port,构建单独的新服务被flaskapp进行整合,但是不能够适应复杂策略需求,同时在backtraderBokeh模块下有个小bug需要在处理
backtrader_plotly这个模块没有进行相关测试,感觉不太被维护https://github.com/lamkashingpaul/backtrader_plotly
Bokeh这个是backtrader自带的作模块,上面这些都是基于此模型改进开发的
如果想要一个适合自己喜欢那就动手造吧!知乎上的大神做了Dashplotlyhttps://zhuanlan.zhihu.com/p/98775974
折腾案例学习和借鉴,量化大道溜达走起BTR-E2020https://github.com/klein203/BTR-E2020
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, pision, 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())
文章为作者独立观点,不代表 股票程序化软件自动交易接口观点