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()

backtrader数据基础相关推荐

  1. 国家发改委就数据基础制度征求意见 鼓励互联网企业开放公共属性数据

    来源:人民网.人民数据 本文约2100字,建议阅读5分钟内容涉及数据产权制度.数据要素流通交易制度.数据要素收益分配制度以及数据要素安全治理制度等4个方面. 据国家发展改革委官网消息,国家发展改革委创 ...

  2. 「回顾」网易数据基础平台建设

    首先简单介绍一下网易杭州研究院情况简介,如下图所示: 我们公司主要从事平台技术开发和建设方面,工作的重点方向主要在解决用户在数据治理中的各种问题,让用户能更高效地管理自己的数据,进而产生更大的价值,比 ...

  3. 倾斜模型精细化处理_广州智迅诚单体化实景三维模型为智慧城市提供了平台数据基础...

    自然资源部国土测绘司司长武文忠表示,在落实"多规合一"建立国土空间规划体系.严守耕地保护红线.第三次全国国土调查等一系列重大工作中,都提出了对建立"一张图"&q ...

  4. 大数据基础技术和应用

    大数据概述 数据的表现形式: 线下数据信息化:数据库.文字记录.照片-- 互联网-移动互联网:网页数据.用户行为记录.数字图像-- 传感器:设备监控.智能家居.摄像头-- 大数据的4V特征: 大量化( ...

  5. 大数据基础系列 5:Hadoop 实验——熟悉常用的 HDFS 目录操作和文件操作

    文章目录 前言 一.实验目的 二.实验平台 三.实验内容和要求 3.1.HDFS 目录操作 3.1.1.创建用户目录 3.1.2.显示 HDFS 中与当前用户对应的目录内容 3.1.3.列出 HDFS ...

  6. 大数据基础系列 4:伪分布式 Hadoop 在 Ubuntu 上的安装流程完整步骤及易错点分析

    文章目录 前言 一.创建 Ubuntu 用户 二.安装 Java 2.1.查看本地 Java 版本 2.2.验证 Java 在本地的配置情况 三.安装 ssh 服务 3.1.安装 openssh-se ...

  7. 大数据基础学习三:Ubuntu下安装VMware Tools超详细步骤及需要注意的问题(以ubuntu-18.04.3、Mware Workstation 15.1.0 Pro为例)

    大数据基础学习三:Ubuntu下安装VMware Tools超详细步骤及需要注意的问题 (以ubuntu-18.04.3.Mware Workstation 15.1.0 Pro for Window ...

  8. 大数据基础学习二:在VMware虚拟机上安装Ubuntu完整步骤及需要注意的问题(以VMware Workstation 15.1.0 Pro和Ubuntu18.04.3优麒麟版为例)

    大数据基础学习二:在VMware虚拟机上安装Ubuntu完整步骤及需要注意的问题 (以VMware Workstation 15.1.0 Pro for Windows和Ubuntu18.04.3优麒 ...

  9. mybatis 依赖于jdbc_大数据基础:Mybatis零基础入门

    在Java企业级开发任务当中,持久层框架的选择,国内市场的主流选择一定有Mybatis的一席之地,从入门来说,Mybatis的学习难度不算高,但是要把Mybatis发挥出真正的效用,还是需要深入学习的 ...

最新文章

  1. ASP.NET中如何实现负载均衡
  2. oracle数据库【表复制】insert into select from跟create table as select * from 两种表复制语句区别...
  3. jQuery框架学习第一天:开始认识jQuery
  4. 8.2 TensorFlow实现KNN与TensorFlow中的损失函数,优化函数
  5. 5.16 Stacks and Queues
  6. 在 Win7 下运行 TC 2.0 / TC3.0 / BC 3.1 / QB 4.5 等 DOS 开发工具
  7. php截取字符串,带中文,多余的省略号代替
  8. springboot+layui从控制器请求至页面时js失效的解决方法
  9. codeforces 476B.Dreamoon and WiFi 解题报告
  10. 图解linux32位平台下进程线程长什么样子
  11. 【华为云技术分享】云图说|超赞!终于有人把云存储“三兄弟”讲清楚了!
  12. 【Elasticsearch】es 别名可写 索引可写 傻傻分不清
  13. php yii框架使用MongoDb
  14. javascript基础:Math对象
  15. leetcode/力扣 贪心算法总结,代码随想录PDF下载
  16. 【SQL】小CASE
  17. 对话V神:区块链跨链技术大规模应用将在一到两年内爆发
  18. Microsoft KMS Client Setup Keys ( Windows + Office )
  19. “Think Different”是个糟糕的想法
  20. 自动化测试 —— Pytest测试框架

热门文章

  1. 用Tomcat构建一个简单图片服务器
  2. html一个页面同时加载多个饼图,Html5饼图绘制实现统计图的方法
  3. php iis ajax 无效,IIS7中Ajax.AjaxMethod无效的原因及解决方法
  4. codeforces 50A-C语言解题报告
  5. 个人房贷为啥又贵又难贷 一个房贷银行有3套逻辑
  6. 我身边的手机应用开发者
  7. 安装 Git ( Windows、linux、Mac)
  8. 分布式消息中间件 : Rocketmq
  9. unexpected EOF while looking for matching ``‘
  10. Class is not a root resource. It, or one of its interfaces must be annotated with @Path: