backtrader数据基础

cerebro = bt.Cerebro()
cerebro.addstrategy(TestStrategy2)
codes=['600862.SH','300326.SZ','300394.SZ']
#加载最近两日交易数据
for code in codes:feed = Addmoredata(dataname = get_data(code,'20200506'),name=code)cerebro.adddata(feed)
cerebro.run()

数据查看:

class TestStrategy(bt.Strategy):def __init__(self):# 打印数据集和数据集对应的名称print("-------------self.datas-------------")print(self.datas)print("-------------self.data-------------")print(self.data._name, self.data) # 返回第一个导入的数据表格,缩写形式print("-------------self.data0-------------")print(self.data0._name, self.data0) # 返回第一个导入的数据表格,缩写形式print("-------------self.datas[0]-------------")print(self.datas[0]._name, self.datas[0]) # 返回第一个导入的数据表格,常规形式print("-------------self.datas[1]-------------")print(self.datas[1]._name, self.datas[1]) # 返回第二个导入的数据表格,常规形式print("-------------self.datas[-1]-------------")print(self.datas[-1]._name, self.datas[-1]) # 返回最后一个导入的数据表格print("-------------self.datas[-2]-------------")print(self.datas[-2]._name, self.datas[-2]) # 返回倒数第二个导入的数据表格
data1 = pd.read_csv('111.csv')      
cerebro = bt.Cerebro()
st_date = datetime.datetime(2019,1,2)
ed_date = datetime.datetime(2021,1,28)
# 添加 600466.SH 的行情数据
datafeed1 = bt.feeds.PandasData(dataname=data1, fromdate=st_date, todate=ed_date)
cerebro.adddata(datafeed1, name='600466.SH')
# 添加 603228.SH 的行情数据
datafeed2 = bt.feeds.PandasData(dataname=data2, fromdate=st_date, todate=ed_date)
cerebro.adddata(datafeed2, name='603228.SH')
cerebro.addstrategy(TestStrategy)
rasult = cerebro.run()
# 访问第一个数据集的 close 线
self.data.lines.close # 可省略 lines 简写成:self.data.close
self.data.lines_close # 可省略 lines 简写成:self.data_close
# 访问第二个数据集的 open 线
self.data1.lines.close # 可省略 lines 简写成:self.data1.close
self.data1.lines_close # 可省略 lines 简写成:self.data1_close
# 注:只有从 self.datas 调用 line 时可以省略 lines,调用 indicators 中的 line 时不能省略

获取数据方法:

如果你能清楚的记住数据表格中每条线的位置,也可以通过索引位置(整数)来访问,同样支持简写形式:
1、完整形式:self.datas[X].lines[Y];

2、简写形式:self.dataX.lines[Y]、self.dataX_Y;

3、说明:X 对应单个数据表格在数据表格集合中的索引位置,Y 对应某条线在数据表格中的索引位置 。

class TestStrategy(bt.Strategy):def __init__(self):print("--------- 打印 self 策略本身的 lines ----------")print(self.lines.getlinealiases())print("--------- 打印 self.datas 第一个数据表格的 lines ----------")print(self.datas[0].lines.getlinealiases())# 计算第一个数据集的s收盘价的20日均线,返回一个 Data feedself.sma = bt.indicators.SimpleMovingAverage(self.datas[0].close, period=20)print("--------- 打印 indicators 对象的 lines ----------")print(self.sma.lines.getlinealiases())print("---------- 直接打印 indicators 对象的所有 lines -------------")print(self.sma.lines) print("---------- 直接打印 indicators 对象的第一条 lines -------------")print(self.sma.lines[0])def next(self):print('验证索引位置为 6 的线是不是 datetime')print(bt.num2date(self.datas[0].lines[6][0]))# num2date() 作用是将数字形式的时间转为 date 形式cerebro = bt.Cerebro()
st_date = datetime.datetime(2019,1,2)
ed_date = datetime.datetime(2021,1,28)
datafeed1 = bt.feeds.PandasData(dataname=data1, fromdate=st_date, todate=ed_date)
cerebro.adddata(datafeed1, name='600466.SH')
datafeed2 = bt.feeds.PandasData(dataname=data2, fromdate=st_date, todate=ed_date)
cerebro.adddata(datafeed2, name='603228.SH')
cerebro.addstrategy(TestStrategy)
rasult = cerebro.run()

1、索引规则:索引位置编号结合了时间信息,
0 号位置永远指向当前时间点的数据,
-1 号位置指向前一个时间点的数据,
然后依次回退 (backwards)-2、-3、-4、-5、......;
1 号位置指向下一天的数据,然后依次向前(forwards)2、3、4、......;

2、切片方法:get(ago=0, size=1) 函数,
其中 ago 对应数据点的索引位置,即从 ago 时间点开始往前取 size 个数据点。
默认情况下是取当前最新时点(ago=0)的那一个数据(size=1);

3、在编写策略时,上面提到的对数据点的索引切片操作一般在 next() 函数中涉及较多,
而 __init__() 中涉及较少,
因为__init__() 中一般是对 一整条 line 进行操作(运算)。

class TestStrategy(bt.Strategy):def __init__(self):self.count = 0 # 用于计算 next 的循环次数# 打印数据集和数据集对应的名称print("------------- init 中的索引位置-------------")print("0 索引:",'datetime',self.data1.lines.datetime.date(0), 'close',self.data1.lines.close[0])print("-1 索引:",'datetime',self.data1.lines.datetime.date(-1),'close', self.data1.lines.close[-1])print("-2 索引",'datetime', self.data1.lines.datetime.date(-2),'close', self.data1.lines.close[-2])print("1 索引:",'datetime',self.data1.lines.datetime.date(1),'close', self.data1.lines.close[1])print("2 索引",'datetime', self.data1.lines.datetime.date(2),'close', self.data1.lines.close[2])print("从 0 开始往前取3天的收盘价:", self.data1.lines.close.get(ago=0, size=3))print("从-1开始往前取3天的收盘价:", self.data1.lines.close.get(ago=-1, size=3))print("从-2开始往前取3天的收盘价:", self.data1.lines.close.get(ago=-2, size=3))print("line的总长度:", self.data1.buflen())def next(self):print(f"------------- next 的第{self.count+1}次循环 --------------")print("当前时点(今日):",'datetime',self.data1.lines.datetime.date(0),'close', self.data1.lines.close[0])print("往前推1天(昨日):",'datetime',self.data1.lines.datetime.date(-1),'close', self.data1.lines.close[-1])print("往前推2天(前日)", 'datetime',self.data1.lines.datetime.date(-2),'close', self.data1.lines.close[-2])print("前日、昨日、今日的收盘价:", self.data1.lines.close.get(ago=0, size=3))print("往后推1天(明日):",'datetime',self.data1.lines.datetime.date(1),'close', self.data1.lines.close[1])print("往后推2天(明后日)", 'datetime',self.data1.lines.datetime.date(2),'close', self.data1.lines.close[2])print("已处理的数据点:", len(self.data1))print("line的总长度:", self.data0.buflen())self.count += 1cerebro = bt.Cerebro()
st_date = datetime.datetime(2019,1,2) # 起始时间
ed_date = datetime.datetime(2021,1,28) # 结束时间
datafeed1 = bt.feeds.PandasData(dataname=data1, fromdate=st_date, todate=ed_date)
cerebro.adddata(datafeed1, name='600466.SH')
datafeed2 = bt.feeds.PandasData(dataname=data2, fromdate=st_date, todate=ed_date)
cerebro.adddata(datafeed2, name='603228.SH')
cerebro.addstrategy(TestStrategy)
rasult = cerebro.run()

__init__() 中: 
访问的是整条 line,索引编号也是对整条 line 上所有数据点进行编号的,
所以 0 号位置对应导入的行情数据中最晚的那个时间点 2021-01-28,
然后依次 backwards;
1 号位置对应最早的那个时间点 2019-01-02,
然后依次 forwards ;

通过 get() 切片时,如果是从 ago=0 开始取,不会返回数据,从其他索引位置开始取,能返回数据 。

next() 中:
1、由于 next() 是按回测时间点依次循环运行的,
所以 next() 中数据点的索引位置是随着回测依次推进而动态变化的:backwards 时对应回测过的、已处理过的那部分 line, forwards 时对应还未回测的那部分 line ;

2、在 next() 中,只要记住 0 是当前回测的时间点(今日),
然后站在当前时刻回首过往:-1 是昨日、-2 是前日,依次类推 ;或者站在当前时刻期盼未来:1 是明日、2 是明后日,以此类推 。
获取 line 长度:
1、self.data0.buflen() 返回整条线的总长度,固定不变;
2、在 next() 中调用 len(self.data0),返回的是当前已处理(已回测)的数据长度,会随着回测的推进动态增长。

DataFeeds 数据模块

默认的导入方式
step1:调用 DataFeeds 模块中的方法读取数据;

step2:将读取的数据传给大脑。

# 读取和导入 CSV 文件
data = bt.feeds.GenericCSVData(dataname='filename.csv', ...)
cerebro.adddata(data, name='XXX')
# 读取和导入 dataframe 数据框 - 方式1
data = bt.feeds.PandasData(dataname=df, ...)
cerebro.adddata(data, name='XXX')
# 读取和导入 dataframe 数据框 - 方式2
data = bt.feeds.PandasDirectData(dataname=df, ...)
cerebro.adddata(data, name='XXX')# 以 GenericCSVData 为例进行参数说明(其他导入函数参数类似)
bt.feeds.GenericCSVData(dataname='daily_price.csv', # 数据源,CSV文件名 或 Dataframe对象fromdate=st_date, # 读取的起始时间todate=ed_date, # 读取的结束时间nullvalue=0.0, # 缺失值填充dtformat=('%Y-%m-%d'), # 日期解析的格式# 下面是数据表格默认包含的 7 个指标,取值对应指标在 daily_price.csv 中的列索引位置datetime=0, # 告诉 GenericCSVData, datetime 在 daily_price.csv 文件的第1列high=3, low=4,open=2,close=5,volume=6,openinterest=-1) # 如果取值为 -1 , 告诉 GenericCSVData 该指标不存在

 Backtrader 中的数据表格默认情况下包含 7 条 line,这 7 条 line 的位置也是固定的,
依次为 ('close', 'low', 'high', 'open', 'volume', 'openinterest', 'datetime') ,
那导入的数据表格必须包含这 7 个指标吗?指标的排列顺序也必须一致吗?
当然不是!其实你只要告诉 GenericCSVData、PandasData 、PandasDirectData 这 7 个指标在数据源中位于第几列,如果没有这个指标,那就将位置设置为 -1 
(如果是dataframe, None 表示指标不存在,-1 表示按位置或名称自动匹配指标),所以你要做的是让 Backtrader 知道指标在数据源的哪个位置上 。 

自定义读取函数
如果你觉得每次都要设置这么多参数来告知指标位置很麻烦,那你也可以重新自定义数据读取函数,
自定义的方式就是继承数据加载类 GenericCSVData、PandasData 再构建一个新的类,然后在新的类里统一设置参数:

class My_CSVData(bt.feeds.GenericCSVData):params = (('fromdate', datetime.datetime(2019,1,2)),('todate', datetime.datetime(2021,1,28)),('nullvalue', 0.0),('dtformat', ('%Y-%m-%d')),('datetime', 0),('time', -1),('high', 3),('low', 4),('open', 2),('close', 5),('volume', 6),('openinterest', -1)
)
cerebro = bt.Cerebro()
data = My_CSVData(dataname='daily_price.csv')
cerebro.adddata(data, name='600466.SH')
rasult = cerebro.run()    

 新增指标
在回测时,除了常规的高开低收成交量这些行情数据外,还会用到别的指标,
比如选股回测时会用到很多选股因子(PE、PB 、PCF、......),那这些数据又该如何添加进 Backtrader 的数据表格呢?
往 Backtrader 的数据表格里添加指标,就是给数据表格新增列,也就是给数据表格新增 line:
以导入 DataFrame 为例,
在继承原始的数据读取类 bt.feeds.PandasData 的基础上
,设置 lines 属性和 params 属性,
新的 line 会按其在 lines 属性中的顺序依次添加进数据表格中,具体对照下面例子的输出部分:

class PandasData_more(bt.feeds.PandasData):lines = ('pe', 'pb', ) # 要添加的线# 设置 line 在数据源上的列位置params=(('pe', -1),('pb', -1),) # -1表示自动按列明匹配数据,也可以设置为线在数据源中列的位置索引 (('pe',6),('pb',7),) 
class TestStrategy(bt.Strategy):def __init__(self):print("--------- 打印 self.datas 第一个数据表格的 lines ----------")print(self.data0.lines.getlinealiases())print("pe line:", self.data0.lines.pe)print("pb line:", self.data0.lines.pb)data1['pe'] = 2 # 给原先的data1新增pe指标(简单的取值为2)
data1['pb'] = 3 # 给原先的data1新增pb指标(简单的取值为3)
# 导入的数据 data1 中
cerebro = bt.Cerebro()
st_date = datetime.datetime(2019,1,2)
ed_date = datetime.datetime(2021,1,28)
datafeed1 = PandasData_more(dataname=data1, fromdate=st_date, todate=ed_date)
cerebro.adddata(datafeed1, name='600466.SH')
cerebro.addstrategy(TestStrategy)
rasult = cerebro.run()

 

扩展PandasData类,加载更多列数据
#pandas的数据格式
from backtrader.feeds import PandasData
class Addmoredata(PandasData):lines = ('turnover_rate','pe','pb',)params = (('turnover_rate',7),('pe',8),('pb',9),)
扩展GenericCSVData加载csv格式数据
from backtrader.feeds import GenericCSVData
class AddCsvData(GenericCSVData):lines = ('turnover_rate','pe','pb',)params = (('turnover_rate',7),('pe',8),('pb',9),)
import backtrader as bt
from datetime import datetime
class TestStrategy1(bt.Strategy):def log(self, txt, dt=None):dt = dt or self.datas[0].datetime.date(0)print('%s, %s' % (dt.isoformat(), txt))def next(self):self.log(f"换手率:{self.datas[0].turnover_rate[0]},\市净率:{self.datas[0].pb[0]},市盈率:{self.datas[0].pe[0]}")
cerebro = bt.Cerebro()
cerebro.addstrategy(TestStrategy1)
feed = Addmoredata(dataname = get_data('300002.SZ','20200420'))
#如果是读取csv数据使用下式
#feed = AddCsvData(dataname = 'test.csv',dtformat=('%Y-%m-%d'))
cerebro.adddata(feed)
cerebro.run()
多只股票数据加载测试:
class TestStrategy2(bt.Strategy):def log(self, txt, dt=None):dt = dt or self.datas[0].datetime.date(0)print('%s, %s' % (dt.isoformat(), txt))def next(self):for data in self.datas:print(data._name)self.log(f"换手率:{data.turnover_rate[0]},\市净率:{data.pb[0]},市盈率:{data.pe[0]}")
cerebro = bt.Cerebro()
cerebro.addstrategy(TestStrategy2)
codes=['600862.SH','300326.SZ','300394.SZ']
#加载最近两日交易数据
for code in codes:feed = Addmoredata(dataname = get_data(code,'20200506'),name=code)cerebro.adddata(feed)
cerebro.run()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/449511.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

谈判学:三招了解对方底线

导读:谈判者都希望能了解对方的底线,最直接的一招就是将对手变成“朋友”,只是这种“内奸法”毕竟不是常规之法。大多数情况下,谈判双方也不可能像《无间道》一样在对方阵营安放卧底,但是我们完全可以通过一些办法来揣…

JSLint检测Javascript语法规范

前端javascript代码编写中,有一个不错的工具叫JSLint,可以检查代码规范化,压缩JS,CSS等,但是他的语法规范检查个人觉得太“苛刻”了,会提示各种各样的问题修改建议,有时候提示的信息我们看的莫名…

Apt 命令解说(apt-get update、apt-cache search package、apt-get install package、apt-get remove )

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 高级打包工具(英语:Advanced Packaging Tools,缩写为APT)是Debian及其派生发行版的软件包…

SQL SERVER 2012 AlwaysOn - 维护篇 03

搭建 AlwaysOn 是件非常繁琐的工作,需要从两方面考虑,操作系统层面和数据库层面,AlwaysOn 非常依赖于操作系统,域控,群集,节点等概念; DBA 不但要熟悉数据库也要熟悉操作系统的一些概念&#xf…

指标研究与多周期

哪些地方会用到指标 ? 回顾一下 Backtrader 的主要功能模块和回测流程(见:Backtrader 来了!)可以发现,只有在编写策略Strategy 时才会涉及到指标的计算和使用,而且是 Strategy 中的 __init__()…

区块链BAAS平台:公共或私人区块链编程以用于各种用途

2019独角兽企业重金招聘Python工程师标准>>> 人们可以为公共或私人区块链编程以用于各种用途。理论上,我认为牺牲权力下放的方面可以解决区块链技术背后的许多当前问题。区块链仍然可以包容,而不是分散。这如何解决当前的一些问题&#xff1f…

CURL 是什么

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 cURL是一个利用URL语法在命令行下工作的文件传输工具,1997年首次发行。 它支持文件上传和下载,所以是综合传输工…

易用性问题回复

针对淘宝网为例,以一次完整的购物流程为背景,我们分析了在淘宝网中的一些易用性的体现,主要场景如下图所示: 在本场景中,新用户下载淘宝app时,第一次打开应用,淘宝app会出现新手指引,教会用户如…

易盛极星期货量化教学

我目前量化实盘做期货交易用的是这个软件。主要就是因为它可以做套利合约,还有就是国企的外包,安全(vnpy的狗咬狗害怕)。 策略模板: 设置全局参数变量: #导入包 import talib #选择合约代码 code1 #设…

eBay是如何进行大数据集元数据发现的

很多大数据系统每天都会收集数PB的数据。这类系统通常主要用于查询给定时间范围内的原始数据记录,并使用了多个数据过滤器。但是,要发现或识别存在于这些大型数据集中的唯一属性可能很困难。 在大型数据集上执行运行时聚合(例如应用程序在特定…

职业发展 先“立功”还是先“安内”?

导读:职业生涯更上一层楼,章良踌躇满志,想在短期内建功立业,奠定江湖地位。但他清楚,自己运筹中的分公司服务升级计划,对公司整体和自己的职业生涯都非常有利,却将不可避免地转移老将掌握的部分…

网关 Kong 折腾笔记 - 相关技术清单

背景 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 公司准备更好的实现微服务架构,我前期的任务主要是 API 开发相关的技术学习,微服务会随着业务的增加不断增加…

Quantaxis更新数据到最新

登录QQ群:563280067 安装方法: 1.进入命令界面, 2.pip install pytdx-1.72r2-py3-none-any.whl 3. pip install quantaxis-1.10.19r1-py3-none-any.whl 之后输入save save all 即可看到所有的数据全部安装到位

Java各进制之间的转换

十进制转成十六进制: Integer.toHexString(int i) 十进制转成八进制 Integer.toOctalString(int i) 十进制转成二进制 Integer.toBinaryString(int i) 十六进制转成十进制 Integer.valueOf("FFFF",16).toString() 八进制转成十进制 Integer.valueOf("…

mingW与cygwin 异同

首先MingW和cygwin都可以用来跨平台开发。 MinGW是Minimalistic GNU for Windows的缩写,也就是Win版的GCC。 Cygwin则是全面模拟了Linux的接口,提供给运行在它上面的的程序使用,并提供了大量现成的软件,更像是一个平台。 相…

shell字符串的用法

shell字符串的用法 注意:shell4.2和shell4.1会有差别,较低版本的shell可能不支持某些功能 获取字符串长度:${#string}获取子串: 注:(左边的第一个字符是用 0 表示,右边的第一个字符用 0-1 表示&…

backtrader期权回测框架

使用backtrader数据进行回测,数据源来自于交易所爬取。 效果还行,我相信各位通过这个的框架学习,会对backtrader的应用有更深的领悟。包括数据的连接,新指标的加入。 导入框架: __future__ import (absolute_import…

kong入门实战

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 安装kong-database docker run -d --name kong-database \-p 5432:5432 \-e "POSTGRES_USERkong" \-e "POSTGRES_DBkong&…

PAT A1048

示例思想中提到了二分以及two point概念,这个需要后面进行总结;这个示例也给出了一个新的思路。对于两个数字和m,查找两个加数,可以进行i和m-i的枚举,通过遍历数组查看两个加数是否存在,来进行遍历&#xf…

linux 32位平台,文件大小受限于2G的解决方法

公司的asterisk系统已经发生了两次crash,检查日志,都是在日志文件写满到2G后自动执行转储时,日志还在写继续写入而导致的。google以后,发现了下面这边文章,赞!解决了文件大小限于2G的问题,转帖到…