量化交易-Backtrader回测

目录

一、基础篇-backtrader简介

二、backtrader回测应用实例

三、backtrader数据全解析

3.1 数据中必须包含

3.2 一切皆是数据源 

3.3 参数

3.4 Lines线群

四、交易篇 (上)

4.1 交易操作方式

4.2 资金管理

4.3 滑点管理

4.4 手续费

4.5 交易时机

五、交易篇(下)



一、基础篇-backtrader简介

如果将backtrader包分解为核心组件,主要包括以下组成部分:

  1. 数据加载(Data Feed):将交易策略的数据加载到回测框架中。
  2. 交易策略(Strategy):该模块是编程过程中最复杂的部分,需要设计交易决策,得出买入/卖出信号。
  3. 回测框架设置(Cerebro):需要设置,初始资金、佣金、数据馈送、交易策略、交易头寸大小。
  4. 运行回测:运行Crebro回测并打印出所有已执行的交易。
  5. 评估性能(Analyzers):以图形和风险收益等指标交易策略的回测结果进行评价。

"Lines"是backtrader回测的数据:

Open(开盘价),High(最高价),Low(最低价),Close(收盘价),Volume(成交量),OpenInterest(无得话设置为0)。

DataFeeds(数据加载)、Indicators(技术指标)和Strategies(策略)都会生成Lines.

价格数据中的所有“Open”(开盘价)按时间组成一条Line。所以,一组含有以上6个类别的价格数据,共6条Lines。如果算上“DataTime”(时间,可以看做是一组数据的主建),一共有7条Lines。

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

二、backtrader回测应用实例

代码如下(示例):

import pandas as pd
from datetime import datetime
import backtrader as bt
import matplotlib.pyplot as plt
import tushare as ts

def get_data(code='600519',starttime='2017-01-01',endtime='2020-01-01'):
    df = ts.get_k_data(code,start = starttime,end = endtime)
    print(df)
    df.index = pd.to_datetime(df.date)
    df['openinterest'] = 0;
    df = df[['open','high','low','close','volume','openinterest']]
    return df

stock_df =get_data()
fromdate = datetime(2017,1,1)
todate = datetime(2020,1,1)
data = bt.feeds.PandasData(dataname=stock_df,fromdate=fromdate,todate=todate)

class MyStrategy(bt.Strategy):
    params=(
        ('maperiod',20),
    )
    
    def __init__(self):
        self.order = None
        self.ma = bt.indicators.SimpleMovingAverage(self.datas[0],period=self.params.maperiod)
    def next(self):
        if(self.order):
            return
        if(not self.position):
            if self.datas[0].close[0] > self.ma[0]:
                self.order = self.buy (size=200)
            else:
                if self.datas[0].close[0] < self.ma[0]:
                    self.order = self.sell(size=200)

cerebro = bt.Cerebro()
cerebro.adddata(data)
cerebro.addstrategy(MyStrategy)
startcash = 100000
cerebro.broker.setcash(startcash)
cerebro.broker.setcommission(0.0002)

s = fromdate.strftime("%Y-%m-%d")
t = todate.strftime("%Y-%m-%d")
print(f"初始资金:{startcash}\n回测时间:{s}-{t}")
cerebro.run()
portval = cerebro.broker.getvalue()
print(f"剩余总资金:{portval}\n回测时间:{s}-{t}")

三、backtrader数据全解析

3.1 数据中必须包含

交易数据(Data Feeds)必须包含以下几个组成部分:开盘价(Open)、最高价(High)、最低价(Low)、收盘价(Close)、成交量(Volume)、持仓量(0penInterest)等。比如:所有的开盘价(Open)按时间组成一条折线(Line),那么一组交易数据(Data Feeds)就应该包含了6条线(Line)。

3.2 一切皆是数据源 

import backtrader as bt
# snip
class MyStrategy(bt.Strategy):
	params = dict(period1=20,period2=25,period3=10,period4=5)

	def __init__(self):
		sma1 = btind.SimpleMovingAverage(self.datas[0],period=self.p.period1)

		# 第二移动平均线使用sma1作为参数,均线的均线
		sma2 = btind.SimpleMovingAverage(sma1,period=self.p.period2)

		# 通过算数运算常见的新数据
		something = sma2-sma1+self.data.close
# snip

3.3 参数

import backtrader as bt
# snip
class MyStrategy(bt.Strategy):
	# 元组
	params = (('period',20),)
	# 字典
	params = dict(period=20)
	# 访问
	def __init__(self):
		self.params.period
		self.p.period
# snip

3.4 Lines线群

  • Lines(线群)对象可以容纳一个或多个线,可以通过data.lines.getlinealiases()查看
  • 线是由一组数据组成的数组
closelowhighopenvolumedatetime
默认索引[0][1][2][3][4][5]
linelinelinelinelineline
import backtrader as bt
# snip
class MyStrategy(bt.Strategy):
	params = dict(period=20)
	
	def __init__(self):
		self.movav = btind.SimpleMovingAverage(self.data,period=self.p.period)

	def next(self):
		if self.movav.lines.SMA[0] > self.data.lines.close[0]:
			print('移动平均线大于收盘价')
# snip

主要用法:

# snip
def next(self):
	# 都表示添加的第一个数据集
	self.data
	self.data0
	self.datas[0]
	# 都表示close的那条链条
	self.data.lines[0]
	self.data.lines.close
	self.data.close
# snip

四、交易篇 (上)

4.1 交易操作方式

调用broker中的“set_xxx”方法俩修改条件,还可以通过“get_xxx”方法查看当前设置的条件取值

4.2 资金管理

import backtrader as bt
# snip
cerebro = bt.Cerebro()
# 设置初始资金
# set_cash\setcash
cerebro.broker.set_cash(1000)
# 获取可用资金
# get_cash\getcash\getvalue
cerebro.broker.get_cash()
# 增加或减少资金
cerebro.broker.add_cash(1000)
cerebro.broker.add_cash(-1000)
# snip

4.3 滑点管理

import backtrader as bt
# snip
cerebro = bt.Cerebro()
# 方式1:通过BackBroker类中的slip_perc参数设置百分比滑点
cerebro.broker = bt.brokers.BackBroker(slip_perc=0.0001)
# 方式2:通过调用brokers的set_slippage_perc方法设置百分比滑点
cerebro.broker.set_slippage_perc(perc=0.0001)
# snip

4.4 手续费

import backtrader as bt
# snip
cerebro = bt.Cerebro()
# 手续费万分之二
cerebro.broker = bt.brokers.BackBroker(commission=0.0002)
# snip

4.5 交易时机

Backtrader还提供了一些cheating式的交易时机模式:Cheat-On-Open和Cheat-On-Close。

Backtrade默认是“当日收盘后下单,次日开盘价成交”,这种模式在回测过程中能有效避免使用未来数据。

Cheat-On-Open是“当日下单,当日以开盘价成交”模式

  • 方式1:bt.Cerebro(cheat_on_open=True)
  • 方式2:cerebro.broker_set_coo(True)
  • 方式3:BackBroker(coo=True)

Cheat-On-Close是“当日下单,当日以收盘价成交”模式

  • 方式:cerebro.broker_set_coc(True) 

五、交易篇(下)

import backtrader as bt
# snip
class TestStrategy(bt.Strategy):
	def next(self):
		# 买入,做多 long
		self.order = self.buy(...)
		# 卖出,做空 short
		self.order = self.sell(...)
		# 平仓 cover
		self.order = self.close(...)
# snip
  • data (默认:None):用于制定给哪个数据集(即哪个证券)创建订单,默认为None,表示给第1个数据集(self.datas[0]、self.data0对应的证券)创建订单。
  • size(默认:None):订单委托数量(正数),默认为None,表示会自动通过getsizer获取sizer。
  • price(默认:None):订单委托价,None表示不指定具体的委托价,而是由市场决定最终的成交价。
import backtrader as bt
# snip
class TestStrategy(bt.Strategy):
	def next(self):
		# 按目标数量下单
		self.order = self.order_target_size(target=size)
		# 按目标金额下单
		self.order = self.order_target_value(target=value)
		# 按目标百分比下单
		self.order = self.order_target_percent(target=percent)
# snip

  • 3
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值