本文主要来自于官方文档的翻译,添加一些笔者在实践中的理解,来记录backtrader中的一些基本概念。
Data Feeds
backtrader(以下简称bt)进行回测或者交易需要有历史或者实时的数据源,这些数据源包括典型的开盘价、最高价、最低价、收盘价、成交量等等,也可以是用户自定义的指标、买卖信号等。Data Feeds就扮演着这个数据源的角色,需要用户提供给bt。用户通过以下方式将Data Feeds添加到bt内:
cerebro = bt.Cerebro() # 定义cerebro
...
data = btfeeds.MyFeed(...) # 定义Data Feeds
cerebro.adddata(data) # 添加Data Feeds
...
cerebro.addstrategy(MyStrategy, period=30) # 添加Strategy,在Strategy就可以访问Data Feeds
...
bt中主要靠Strategy来完成回测和交易,当Data Feeds通过上面代码的方式被添加到bt后,就可以在Strategy中访问这些数据了,示例如下:
class MyStrategy(bt.Strategy):
params = dict(period=20)
def __init__(self):
sma = btind.SimpleMovingAverage(self.datas[0], period=self.params.period)
...
其中,self.datas就是对Data Feeds的访问。在Strategy中,Data Feeds被赋值给self.datas这一成员变量,并以数组array的形式存在,数组中的每个元素代表1组数据,例如self.datas[0]表示第1只股票的数据,self.datas[1]表示第2只股票的数据,依次类推。
此外,Data Feeds会按照添加bt的顺序做顺序存储。
Data Feeds的快捷访问方式
self.datas数组有以下快捷访问的方式:
- self.data对应self.datas[0]
- self.dataX对应self.datas[X],其中X是0,1, 2,3 。。。
使用快捷方式self.data访问第1个 Data Feeds的示例如下:
class MyStrategy(bt.Strategy):
params = dict(period=20)
def __init__(self):
sma = btind.SimpleMovingAverage(self.data, period=self.params.period)
...
示例中,使用第1个Data Feeds来计算均线值。
省略Data Feeds
上面的代码示例可以做进一步简化:
class MyStrategy(bt.Strategy):
params = dict(period=20)
def __init__(self):
sma = btind.SimpleMovingAverage(period=self.params.period)
...
这里在调用SimpleMovingAverage计算均线值时,把参数self.data也省略了。在这种情况下,默认会使用第1个Data Feeds(即self.data,self.datas0,self.datas[0])来计算指标数据。
其他可以被当作Data Feeds的对象
在Strategy中,指标(Indicators)和运算符(Operations)计算结果都可以像Data Feeds一样,被用来当作data计算指标数据(如上面计算SimpleMovingAverage的例子),示例如下(解释请见代码中的注释):
class MyStrategy(bt.Strategy):
params = dict(period1=20, period2=25, period3=10, period4)
def __init__(self):
# 在计算SimpleMovingAverage时,使用self.datas[0]作为data
sma1 = btind.SimpleMovingAverage(self.datas[0], period=self.p.period1)
# 在计算SimpleMovingAverage时, 使用sma1(Indicators)作为data
sma2 = btind.SimpleMovingAverage(sma1, period=self.p.period2)
# 通过运算符(Operations)计算来创建新的data
something = sma2 - sma1 + self.data.close
# 在计算SimpleMovingAverage时, 使用something(Operations结果)作为data
sma3 = btind.SimpleMovingAverage(something, period=self.p.period3)
# 使用比较运算符(Operations)创建新的data
greater = sma3 > sma1
# 在计算SimpleMovingAverage时, 使用greater(Operations结果)作为data
sma3 = btind.SimpleMovingAverage(greater, period=self.p.period4)
...
通过示例可以看出,Data Feeds, Indicators,Operations结果都可以被用过data传递给Strategy中,来计算新的指标。
参数Parameters
bt支持使用元组的元组或者类字典对象来定义参数Parameters,参数被定义为类的成员变量,可以使用self.params或者self.p来进行访问,使用元组形式的示例如下:
class MyStrategy(bt.Strategy):
params = (('period', 20),)
def __init__(self):
sma = btind.SimpleMovingAverage(self.data, period=self.p.period)
使用字典形式的示例如下:
class MyStrategy(bt.Strategy):
params = dict(period=20)
def __init__(self):
sma = btind.SimpleMovingAverage(self.data, period=self.p.period)
bt采用这种方式定义参数,是为了后续在添加策略时修改参数,或者对参数进行优化(调参)做准备。
欢迎大家关注、点赞、转发、留言,感谢支持!
微信群用于学习交流,感兴趣的读者请扫码加微信!
QQ群(676186743)用于资料共享,欢迎加入!