backtrader是基于Python的量化回测框架,功能丰富,操作方便。其优点是运行速度快,支持pandas的矢量运算;内置多种技术指标计算,还支持股票分析技术指标库talib;支持参数自动寻优运算;支持多品种(股票、期货、期权、外汇和数字货币)、多策略、多周期(Ticks、秒、分、日、周、月和年)的回测和交易;支持PyFlio、empyrica分析模块库、alphalens多因子分析模块库等;扩展灵活,可以集成TensorFlow、PyTorch和Keras等机器学习、神经网络分析模块。

一、安装

pip install backtrader

官网:Backtrader

安装需求:

Python 2.7

Python 3.2 / 3.3/ 3.4 / 3.5

pypy/pypy3

绘图需要用到Matplotlib,最新版本建议>=1.4.1。

包引用:import backtrader as bt

二、backtrader功能

backtrader包主要包括:框架(Cerebro)、数据加载(Data Feed)、交易策略(Strategies)、技术指标(Indicators)、订单(Orders)、观察者(Observers)、测量评估(Analyzers)、订单(Orders)、经纪人(Broker)、实盘交易(Live Trading)、结果可视化(Plotting)等部分

整体结构如下图所示:

下面对其中的关键部分进行详细说明。

1.数据类型

backtrader回测的数据类型是由一系列的点组成的Lines,通常包括以下类别的数据:Open(开盘价)、High(最高价)、Low(最低价)、 Close(收盘价)、Volume(成交量)、OpenInterest(未平仓权益)。Data Feeds(数据加载)、Indicators(技术指标)和Strategies(策略)都会生成 Lines。价格数据中的所有的开盘价按时间组成一条 Line,因此一组含有以上6个类别的价格数据,共有6条 Lines。如果算上DateTime(时间,可以看作是一组数据的主键),一共有7条 Lines。

一条Line数据的下标为0表示访问当前时刻数据,-1表示访问最后一个数据。因此,在回测过程中,无需知道已经处理了多少条/分钟/天/月,”0”一直指向当前值,下标 -1 来访问最后一个值。

2.交易策略(Strategy)

该模块是回测系统最核心的部分,需要设计交易决策,得出买入/卖出信号。策略类代码包含重要的参数和用于执行策略的功能,要定义的参数或函数名如下:

(1)params:全局参数,可选,用于更改交易策略中变量/参数的值,可用于参数调优。

(2)log:日志,可选,用于记录策略的执行日志,可以打印出该函数提供的日期时间和txt变量。

(3)__init__:用于初始化交易策略,在其中声明的任何指标都会在next()方法调用之前进行计算。部分python操作符不支持,需要使用bt内置函数来处理,例如bt.And, bt.Or, bt.All, bt.Any等。

(4)notify_order,可选,用于跟踪交易订单(order)的状态。order具有提交,接受,买入/卖出执行和价格,已取消/拒绝等状态。

(5)notify_trade,可选,用于跟踪交易的状态,任何已平仓的交易都将报告毛利和净利润。

(6)next,必选,用于制定交易策略的函数,策略模块最核心的部分。

3.技术指标(Indicators)

实际上,策略的构建都需要指标来实现,该部分包括很多已经实现的指标,下面是一些比较常用的指标:

Average:指定周期的算术平均值。

SimpleMovingAverage(SMA):简单移动平均

WeightedAverage:加权移动平均

MACD:滑动平均

ExponentialMovingAverage(EMA):指数移动平均

RSI_SMA/RSI_EMA:

BollingerBands(BOLL):布林线

DoubleExponentialMovingAverage(DEMA):双指数移动平均

WilliamsR(WR):威廉指标

在指标中也集成了TA-Lib库,实际使用中发现无法正常调用,不知道是不是跟我没有安装该库有关。另外,还可以通过继承Indicator或其它已存在的指标类来实现自定义指标,方便用户加入自己开发的指标。

# 继承自bt.Indicator或其他已存在的指标类
class DummyInd(bt.Indicator):# 定义持有的lines,至少需要1个linelines = ('dummyline',)# params参数可选params = (('value', 5),)# plotinfo可选,用来控制绘图行为plotinfo = dict(subplot=False)# __init__方法或next方法必选def __init__(self):self.lines.dummyline = bt.Max(0.0, self.params.value)

4.订单(Orders)

将策略中逻辑做出的决策转换为适合经纪人执行操作的消息,通常在交易策略中调用。

5.经纪人(Broker)

通过设置回测的初始自己、佣金费率、税收费率、滑点率等交易条件,模拟不同的订单类型,并根据现金检查订单,计算每次交易的现金和权益,保存交易数据。

6.策略评估(Analyzers)

用于分析交易策略的利润和风险,分析交易系统的绩效。

7.实盘交易(Live Trading)

从1.5.0开始支持实盘数据和实时交易。具体请参考:Live Trading。

8.观察者(Observers)

用于记录交易过程,包括现金、权益、费用以及交易动作、买卖订单等数据。

9.结果可视化(Plotting)

通过图形的方式显示交易测量回测的结果,绘图显示的结果包括三部分类型:现金及权益、交易损益、买卖动作。

绘图设置通过plotinfo来设置,其参数主要有:plot(是否绘图,默认为True),subplot(是否单独窗口绘图,默认为True,MA类指标该参数为False),plotname(指标图名,默认为指标类名),plotabove(绘图位置在数据上方,默认为False),plotlinelabels, plotymargin, plotyticks,plothlines, plotyhlines, plotforce。

注意:由于技术指标的不同,可视化结果中所包含的数据可能不同,因此需要根据技术指标来选择其所支持的参数进行设置。

三、系统流程

在backtrader内部通过对数据和指标的处理执行策略,并记录所有的交易过程和数据输出给用户。

backtrader的入口为Cerebro类,该类将所有输入(Data Feeds)、执行 (Stratgegies)、观察者(Observers)、评价(Analyzers) 和文档 (Writers)整合起来,实现回测以及交易,并返回结果和图表。

(1)创建实例

cerebro = bt.Cerebro()  # 创建回测系统实例

(2)关联输入数据

cerebro.adddata(data)  # 将数据加载至回测系统

(3)关联交易策略

cerebro.addstrategy(BollStrategy,nk=14,m=2,printlog=True)

(4)关联其他可选功能

addwriter():指定交易过程和数据保存的方式。

addanalyzer():增加策略评估。

addobserver():增加观察者。

addobservermulti()

(5)指定经纪人

broker = MyBroker()
cerebro.broker = broker

可以根据不同类型的交易对象设置经纪人模型。

(6)接收消息

接收回测消息有三种方式:在Cerebro类的实例中通过addnotifycallback(callback)增加回调函数、在Strategy子类中重载notify_store()方法、继承Cerebro类并重载notify_store()方法

(7)执行回测并返回结果

result=cerebro.run(maxcpus=1)

(8)记录交易信息

这个功能是通过观察者(Observers)实现,有三种类型:

经纪人观察者(Broker)保存现金和权益信息。交易观察者(Trades)记录交易的有效性。买卖观察者(Buy/Sell)记录所有交易执行的操。

(9)绘图显示

cerebro.plot()

绘图显示底层实际上是调用Matplotlib包实现的。

四、使用示例

下面以BOLL线指标为例,展示backtrader中策略的编写以及整个回测的流程。BOLL线指标的详细介绍可参考文章《BOLL指标计算》,本次回测采用的简易BOLL策略如下:

(1)当收盘价下跌跌破BOLL线通道下轨卖出;

(2)当收盘价上涨突破BOLL线通道上轨卖出。

本次将测试中采用招商银行的前复权日K线数据,将BOLL线的周期N设为13,倍数因子为默认值,并在交易回测中加入了交易过程打印功能。

示例代码如下:

from datetime import datetime
import akshare as ak
import pandas as pd
import backtrader as btclass BollStrategy(bt.Strategy): #BOLL策略程序params = (("nk", 13), #求均值的天数('printlog', False),)  #打印logdef __init__(self): #初始化self.data_close = self.datas[0].close  # 指定价格序列        # 初始化交易指令、买卖价格和手续费self.order = Noneself.buy_price = Noneself.buy_comm = None#Boll指标计算self.top=bt.indicators.BollingerBands(self.datas[0],period=self.params.nk).topself.bot=bt.indicators.BollingerBands(self.datas[0],period=self.params.nk).bot# 添加移动均线指标self.sma = bt.indicators.SimpleMovingAverage(self.datas[0], period=self.params.nk )def next(self): #买卖策略if self.order:  # 检查是否有指令等待执行return# 检查是否持仓"""if not self.position:  # 没有持仓if self.data_close[0] > self.sma[0]:  # 执行买入条件判断:收盘价格上涨突破20日均线self.order = self.buy(size=100)  # 执行买入else:if self.data_close[0] < self.sma[0]:  # 执行卖出条件判断:收盘价格跌破20日均线self.order = self.sell(size=100)  # 执行卖出"""if not self.position:  # 没有持仓if self.data_close[0] < self.bot[0]: # 收盘价格跌破下轨self.log("BUY CREATE, %.2f" % self.data_close[0])self.order = self.buy() #执行买入else:if self.data_close[0] > self.top[0]: # 收盘价格上涨突破上轨self.log("SELL CREATE, %.2f" % self.data_close[0])self.order = self.sell() #执行卖出def log(self, txt, dt=None, do_print=False): #日志函数if self.params.printlog or do_print:dt = dt or self.datas[0].datetime.date(0)print('%s, %s' % (dt.isoformat(), txt))def notify_order(self, order): #记录交易执行情况# 如果order为submitted/accepted,返回空if order.status in [order.Submitted, order.Accepted]:return# 指令为buy/sell,报告价格结果if order.status in [order.Completed]:if order.isbuy():self.log(f"买入:\n价格:{order.executed.price},\成本:{order.executed.value},\手续费:{order.executed.comm}")self.buyprice = order.executed.priceself.buycomm = order.executed.commelse:self.log(f"卖出:\n价格:{order.executed.price},\成本: {order.executed.value},\手续费{order.executed.comm}")self.bar_executed = len(self)elif order.status in [order.Canceled, order.Margin, order.Rejected]:self.log("交易失败") #指令取消/交易失败, 报告结果self.order = Nonedef notify_trade(self, trade): #记录交易收益情况if not trade.isclosed:returnself.log(f"策略收益:\n毛收益 {trade.pnl:.2f}, 净收益 {trade.pnlcomm:.2f}")def stop(self): #回测结束后输出结果self.log("(BOLL线: %2d日) 期末总资金 %.2f" % (self.params.nk, self.broker.getvalue()), do_print=True)code="600036" #股票代码
start_cash=1000000 #初始自己为1000000
stake=100 #单次交易数量为1手
commfee=0.0005 #佣金为万5
sdate='20210101' #回测时间段
edate='20220930'
cerebro = bt.Cerebro()  # 创建回测系统实例
# 利用AKShare获取股票的前复权数据的前6列
df_qfq = ak.stock_zh_a_hist(symbol=code, adjust="qfq", start_date=sdate, end_date=edate).iloc[:, :6]
# 处理字段命名,以符合Backtrader的要求
df_qfq.columns = ['date','open','close','high','low','volume',]
# 把date作为日期索引,以符合Backtrader的要求
df_qfq.index = pd.to_datetime(df_qfq['date'])
start_date = datetime.strptime(sdate,"%Y%m%d")  #转换日期格式
end_date = datetime.strptime(edate,"%Y%m%d")
#start_date=datetime(2022,1,4)
#end_date=datetime(2022,9,16)
data = bt.feeds.PandasData(dataname=df_qfq, fromdate=start_date, todate=end_date)  #规范化数据格式
cerebro.adddata(data)  #加载数据
cerebro.addstrategy(BollStrategy,nk=13,printlog=True) #加载交易策略
cerebro.broker.setcash(start_cash)  # broker设置资金
cerebro.broker.setcommission(commission=commfee)  # broker手续费
cerebro.addsizer(bt.sizers.FixedSize, stake=stake)  # 设置买入数量
print("期初总资金: %.2f" % start_cash)
cerebro.run() #运行回测
end_value=cerebro.broker.getvalue() # 获取回测结束后的总资金
print("期末总资金: %.2f" % end_value)
cerebro.plot()

注意:

1.backtrader的输入数据需要遵循其标准。对于pandas的标准就是这些列的名字是open、close、high、low、volume。

2.backtrader要求pandas下的DataFrame的index是时间,所以设置要将date设置为索引。

3.backtrader的回测日期参数类型为datetime。

结果和交易记录如下图所示:

以上只是对的一个简单BOLL策略进行了回测演示,只是回测中万里长征的第一步。实际使用中还需要做大量的测试工作,例如不同交易费率、不同时间段、不同头寸大小等进行测试,加入止损和止盈等等,最后还要根据结果来修改交易策略。

-----------------------------------

原创不易,请多支持!

backtrader回测框架实例相关推荐

  1. 量化策略——准备3 数据、Backtrader回测框架与quantstats评价指标

    我们一般使用AKShare这个库来获取股票数据或策略中用得到的数据: AKShare github主页:https://github.com/akfamily/akshare 使用Backtrader ...

  2. 量化交易-Backtrader回测

    目录 一.基础篇-backtrader简介 二.backtrader回测应用实例 三.backtrader数据全解析 3.1 数据中必须包含 3.2 一切皆是数据源 3.3 参数 3.4 Lines线 ...

  3. 期权回测框架设计思路

    期权回测,博主已经研究了很长时间,也接触了不少平台,如真格,以及这位博主提供的思路(https://blog.csdn.net/luoqingyong/article/details/10752393 ...

  4. python量化回测框架_股票量化交易回测框架pyalgotrade源码阅读(一)

    PyAlgoTrade是什么呢? 一个股票量化交易的策略回测框架. 而作者的说明如下. To make it easy to backtest stock trading strategies. 简单 ...

  5. 《Python股票量化交易从入门到实践》随书赠送“回测框架”的使用帮助

    点击:QTYX最新版本使用指南[文字版] 点击:QTYX最新版本使用指南[视频版] 点击: QTYX历史版本更新说明 赠送"回测框架"的目的 为了帮助读者再建立一座从书本知识到实战 ...

  6. 【python量化】国内外基于python开发的量化回测框架

    文章目录 写在前面 Zipline PyAlgoTrade BackTrader Catalyst Vn.py 总结 写在前面 在进行量化策略开发时,必不可少的就是策略回测,虽然有很多量化回测平台如三 ...

  7. 6款优秀的量化交易回测框架!VNPY位居第一

    一个策略从想法,到测试,在到实盘,然后改进,进入另一个循环,需要很多的时间和精力.这时候选择一款高效.灵活的测试系统就是当务之急了.即使最后你可能需要写自己的系统,但是这些框架的软工架构还是很值得借鉴 ...

  8. python量化策略源码_Python量化交易进阶讲堂-创建自定义量化回测框架

    欢迎大家订阅<Python实战-构建基于股票的量化交易系统>小册子,小册子会陆续推出与小册内容相关的专栏文章,对涉及到的知识点进行更全面的扩展介绍,并且会有选择地收录至小册中,更便于广大读 ...

  9. 用Python徒手撸一个股票回测框架

    通过纯Python完成股票回测框架的搭建. 什么是回测框架? 无论是传统股票交易还是量化交易,无法避免的一个问题是我们需要检验自己的交易策略是否可行,而最简单的方式就是利用历史数据检验交易策略,而回测 ...

最新文章

  1. 一、Cocos2dx在visualStudio或者vc++中环境搭建(入门篇)
  2. 如何让PHP以root权限执行系统命令
  3. 复习(三)—— 进程管理详解
  4. 设计模式总结 (1)模式分类
  5. 苹果怎么换行打字_停课不停学!推荐苹果电脑学习类软件,丰富您的假期生活...
  6. SpringIOC容器介绍
  7. 面试官系统精讲Java源码及大厂真题 - 10 Map源码会问哪些面试题
  8. python实现不重复排列组合_python之itertools的排列组合相关
  9. aws平台中为ec2实例添加双网卡
  10. 在Debian 6 安装pptpd ×××。
  11. 幻想西游php源码,如何搭建幻想西游服务器
  12. 习惯了的几个火狐插件
  13. 如何使用视频转换器将kux格式转换成mp4格式
  14. win7系统更换锁屏壁纸
  15. 复权不复权,天差与地别 | 量化投资中如何最准确的计算股票前后复权价(附代码)
  16. 本学期计算机课总结,大学生计算机基础学期总结
  17. RNN(pytorch)的维度问题——用GRU实现文本分类(参考刘二大人)
  18. 高德视觉技术中心招聘计算机视觉研发(社招/校招/实习岗位)
  19. Android几种定时任务实现方式汇总
  20. 拼多多校招内推编程题1 最大乘积

热门文章

  1. CityMaker学习教程01 模块说明
  2. 如何多个进程监听同一个端口
  3. IDEA两种方式设置类注释模板
  4. Vulkan 简介及其特点
  5. 什么是JAVA中的强制类型转换
  6. 人工智能( AI )将如何颠覆项目管理?看看这六大关键领域
  7. 三峡大学计算机与信息工程学院,三峡大学计算机与信息学院.doc
  8. 原来工业互联网和工业物联网是两个东西啊
  9. 守护永恒服务器维护,2月24日5点-10点游戏停服维护公告
  10. 梯度下降算法原理 神经网络(Gradient Descent)