Backtrader 文档学习- Observers - Benchmarking

Backtrader 文档学习- Observers - Benchmarking

1.概述

backtrader包括两种不同类型的对象,可以帮助跟踪:

  • Observers 观察者
  • Analyzers 分析器

在分析器领域中,已有TimeReturn对象,用于跟踪整个组合价值(即包括现金)的回报率的演变。
显然作为观察者,在添加一些基准测试的同时,还可做一些工作,将观察者和分析器组合在一起,跟踪相同的对象指标。

Observers 和 Analyzers 之间的主要区别:

  • Observers 的lines特性,它记录每个值,更适合绘图和实时查询,当然会消耗更多的内存。
  • Analyzers 通过get_analysis方法返回一组结果,实现可能不会在运行结束之前提供任何结果,所以Analyzers记录最终结果,内存消耗小。

2.Analyzers - Benchmarking

标准的TimeReturn分析器已扩展为支持跟踪数据源。涉及的两个主要参数:

  • timeframe(默认值:None)
    如果为None,则将报告整个回测期间的完整回报
    传递TimeFrame.NoTimeFrame以考虑没有时间限制的整个数据集
  • data(默认值:None)
    跟踪参考资产而不是组合价值。

注意:
此数据必须已经使用addata、resampledata或replaydata将其添加到cerebro实例中

可以跟踪组合的年度回报率

import backtrader as btcerebro = bt.Cerebro()
#年度回报率
cerebro.addanalyzer(bt.analyzers.TimeReturn, timeframe=bt.TimeFrame.Years)...  # add datas, strategies ...results = cerebro.run()
strat0 = results[0]# If no name has been specified, the name is the class name lowercased
# 所有加载数据组合的分析结果
tret_analyzer = strat0.analyzers.getbyname('timereturn')
print(tret_analyzer.get_analysis())

如果跟踪单一数据的回报率:

import backtrader as btcerebro = bt.Cerebro()data = bt.feeds.OneOfTheFeeds(dataname='abcde', ...)
cerebro.adddata(data)
# 分析器指定数据
cerebro.addanalyzer(bt.analyzers.TimeReturn, timeframe=bt.TimeFrame.Years,data=data)...  # add strategies ...results = cerebro.run()
strat0 = results[0]# If no name has been specified, the name is the class name lowercased
# 分析指定数据的分析结果
tret_analyzer = strat0.analyzers.getbyname('timereturn')
print(tret_analyzer.get_analysis())在这里插入代码片

如果两者都要跟踪,最好是给分析器指定名称:

import backtrader as btcerebro = bt.Cerebro()data = bt.feeds.OneOfTheFeeds(dataname='abcde', ...)
cerebro.adddata(data)
#跟踪单一数据的分析器
cerebro.addanalyzer(bt.analyzers.TimeReturn, timeframe=bt.TimeFrame.Years,data=data, _name='datareturns')
#跟踪组合数据的分析器
cerebro.addanalyzer(bt.analyzers.TimeReturn, timeframe=bt.TimeFrame.Years)_name='timereturns')...  # add strategies ...results = cerebro.run()
strat0 = results[0]# If no name has been specified, the name is the class name lowercased
#跟踪组合数据的分析结果
tret_analyzer = strat0.analyzers.getbyname('timereturns')
print(tret_analyzer.get_analysis())
#跟踪单一数据的分析结果
tdata_analyzer = strat0.analyzers.getbyname('datareturns')
print(tdata_analyzer.get_analysis())

3.Observers - Benchmarking

可以参考前面分析器的基准,对比看区别。
由于后台机制允许在观察器内部使用分析器,增加了两个新的观察器:

  • TimeReturn
  • Benchmark

observers和analyzers,两者都使用 bt.analyzers.TimeReturn分析器来收集结果。

与上面的代码不同,完整的示例运行,展示它们的功能区别。

4.Observing TimeReturn

python ./observer-benchmark.py --plot --timereturn --timeframe notimeframe

在这里插入图片描述
注意选项:

  • timereturn 告诉样本只做这件事
  • timeframe notimeframe 告诉分析器考虑整个数据集,而不考虑时间范围。

最后绘制的值为-0.26。

  • 起始现金(从图表中可以明显看出)为50K货币单位,该策略最终为36970货币单位,因此价值下降了-26%。

与图示的回报率一致。

5.Observing Benchmarking

基准测试也将显示timereturn结果,所以让我们在基准测试处于活动状态时运行相同的操作:

python ./observer-benchmark.py --plot --timeframe notimeframe

没有timereturn参数
在这里插入图片描述

  • 策略优于资产:-0.26 vs -0.33
    值得庆祝,但至少清楚,这个策略没有资产那么糟糕。
    可惜上图的0.26 和 0.33 的图示重合了 ,不够清晰。

以年度为基础跟踪:

python ./observer-benchmark.py --plot --timeframe years

在这里插入图片描述

  • 策略最后值从-0.26到-0.27变化很小

  • 另一方面,资产显示的最终值为-0.35(与上面的-0.33相比)

价值如此接近的原因是,从2005年到2006年,策略和基准资产几乎都处于2005年初的起步水平。

切换到较低的时间框架,例如week,整个情况就会发生变化:

python ./observer-benchmark.py --plot --timeframe weeks

在这里插入图片描述
现在:

  • Benchmark观察者显示出紧张(波动)状态,因为现在跟踪组合和数据的每周回报率数字上下波动
  • 由于去年的最后一周没有交易活动,资产几乎没有变动,因此最后显示的值为0.00(最后一周之前的最后收盘价为25.54,样本数据收盘价为25.55,差异体现在第四个小数点上才能区分)

6.Observing Benchmarking - Another data

示例使用不同的数据进行基准测试。默认情况下,使用数据 benchdata1以Oracle公司为基准。考虑使用-time frame not time frame的整个数据集 。

python ./observer-benchmark.py --plot --timeframe notimeframe --benchdata1

在这里插入图片描述
现在就很清楚没有庆祝的理由:

  • 原yahoo数据,策略对于notimeframe没有改变,仍然为-26%(-0.26)
  • 但对oracle数据进行基准测试时,该数据在同一时期内增长了+23%(0.23)

既可以改变策略,也可以改变资产对象,才能更好地进行交易。
可以理解为:策略可能不适用于某个股票,股票可能也不适用于某个策略

7.Concluding

现在有两种使用相同的基础代码/计算来跟踪TimeReturn和Benchmark的方法 :

  • Observers 观察者(TimeReturn和Benchmark)
  • Analyzer分析器(带有data参数的TimeReturn和TimeReturn)
    当然,基准测试并不能保证盈利,只是比较。

代码的Help

usage: ipykernel_launcher.py [-h] [--data0 DATA0] [--data1 DATA1][--benchdata1] [--fromdate FROMDATE][--todate TODATE] [--printout] [--cash CASH][--period PERIOD] [--stake STAKE] [--timereturn][--timeframe {None,days,weeks,months,years,notimeframe}][--plot [kwargs]]Benchmark/TimeReturn Observers Sampleoptional arguments:-h, --help            show this help message and exit--data0 DATA0         Data0 to be read in (default:./datas/yhoo-1996-2015.txt)--data1 DATA1         Data1 to be read in (default:./datas/orcl-1995-2014.txt)--benchdata1          Benchmark against data1 (default: False)--fromdate FROMDATE   Starting date in YYYY-MM-DD format (default:2005-01-01)--todate TODATE       Ending date in YYYY-MM-DD format (default: 2006-12-31)--printout            Print data lines (default: False)--cash CASH           Cash to start with (default: 50000)--period PERIOD       Period for the crossover moving average (default: 30)--stake STAKE         Stake to apply for the buy operations (default: 1000)--timereturn          Use TimeReturn observer instead of Benchmark (default:None)--timeframe {None,days,weeks,months,years,notimeframe}TimeFrame to apply to the Observer (default: None)--plot [kwargs], -p [kwargs]Plot the read data applying any kwargs passed Forexample: --plot style="candle" (to plot candles)(default: None)

8.代码

from __future__ import (absolute_import, division, print_function,unicode_literals)import argparse
import datetime
import randomimport backtrader as btclass St(bt.Strategy):params = (('period', 10),('printout', False),('stake', 1000),)def __init__(self):sma = bt.indicators.SMA(self.data, period=self.p.period)self.crossover = bt.indicators.CrossOver(self.data, sma)def start(self):if self.p.printout:txtfields = list()txtfields.append('Len')txtfields.append('Datetime')txtfields.append('Open')txtfields.append('High')txtfields.append('Low')txtfields.append('Close')txtfields.append('Volume')txtfields.append('OpenInterest')print(','.join(txtfields))def next(self):if self.p.printout:# Print only 1st data ... is just a check that things are runningtxtfields = list()txtfields.append('%04d' % len(self))txtfields.append(self.data.datetime.datetime(0).isoformat())txtfields.append('%.2f' % self.data0.open[0])txtfields.append('%.2f' % self.data0.high[0])txtfields.append('%.2f' % self.data0.low[0])txtfields.append('%.2f' % self.data0.close[0])txtfields.append('%.2f' % self.data0.volume[0])txtfields.append('%.2f' % self.data0.openinterest[0])print(','.join(txtfields))if self.position:if self.crossover < 0.0:if self.p.printout:print('CLOSE {} @%{}'.format(size,self.data.close[0]))self.close()else:if self.crossover > 0.0:self.buy(size=self.p.stake)if self.p.printout:print('BUY   {} @%{}'.format(self.p.stake,self.data.close[0]))TIMEFRAMES = {None: None,'days': bt.TimeFrame.Days,'weeks': bt.TimeFrame.Weeks,'months': bt.TimeFrame.Months,'years': bt.TimeFrame.Years,'notimeframe': bt.TimeFrame.NoTimeFrame,
}def runstrat(args=None):args = parse_args(args)cerebro = bt.Cerebro()cerebro.broker.set_cash(args.cash)dkwargs = dict()if args.fromdate:fromdate = datetime.datetime.strptime(args.fromdate, '%Y-%m-%d')dkwargs['fromdate'] = fromdateif args.todate:todate = datetime.datetime.strptime(args.todate, '%Y-%m-%d')dkwargs['todate'] = todatedata0 = bt.feeds.YahooFinanceCSVData(dataname=args.data0, **dkwargs)cerebro.adddata(data0, name='Data0')cerebro.addstrategy(St,period=args.period,stake=args.stake,printout=args.printout)if args.timereturn:cerebro.addobserver(bt.observers.TimeReturn,timeframe=TIMEFRAMES[args.timeframe])else:benchdata = data0if args.benchdata1:data1 = bt.feeds.YahooFinanceCSVData(dataname=args.data1, **dkwargs)cerebro.adddata(data1, name='Data1')benchdata = data1cerebro.addobserver(bt.observers.Benchmark,data=benchdata,timeframe=TIMEFRAMES[args.timeframe])cerebro.run()if args.plot:pkwargs = dict()if args.plot is not True:  # evals to True but is not Truepkwargs = eval('dict(' + args.plot + ')')  # args were passedcerebro.plot(**pkwargs)def parse_args(pargs=None):parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter,description='Benchmark/TimeReturn Observers Sample')parser.add_argument('--data0', required=False,default='../../datas/yhoo-1996-2015.txt',help='Data0 to be read in')parser.add_argument('--data1', required=False,default='../../datas/orcl-1995-2014.txt',help='Data1 to be read in')parser.add_argument('--benchdata1', required=False, action='store_true',help=('Benchmark against data1'))parser.add_argument('--fromdate', required=False,default='2005-01-01',help='Starting date in YYYY-MM-DD format')parser.add_argument('--todate', required=False,default='2006-12-31',help='Ending date in YYYY-MM-DD format')parser.add_argument('--printout', required=False, action='store_true',help=('Print data lines'))parser.add_argument('--cash', required=False, action='store',type=float, default=50000,help=('Cash to start with'))parser.add_argument('--period', required=False, action='store',type=int, default=30,help=('Period for the crossover moving average'))parser.add_argument('--stake', required=False, action='store',type=int, default=1000,help=('Stake to apply for the buy operations'))parser.add_argument('--timereturn', required=False, action='store_true',default=None,help=('Use TimeReturn observer instead of Benchmark'))parser.add_argument('--timeframe', required=False, action='store',default=None, choices=TIMEFRAMES.keys(),help=('TimeFrame to apply to the Observer'))# Plot optionsparser.add_argument('--plot', '-p', nargs='?', required=False,metavar='kwargs', const=True,help=('Plot the read data applying any kwargs passed\n''\n''For example:\n''\n''  --plot style="candle" (to plot candles)\n'))if pargs:return parser.parse_args(pargs)return parser.parse_args()if __name__ == '__main__':runstrat()

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

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

相关文章

黑马Java——集合进阶(List、Set、泛型、树)

一、集合的体系结构 1、单列集合&#xff08;Collection&#xff09; 二、Collection集合 1、Collection常见方法 1.1代码实现&#xff1a; import java.util.ArrayList; import java.util.Collection;public class A01_CollectionDemo1 {public static void main(String[] a…

Token、CAS、JWT和OAuth 2.0认证系统认证中心系统设计对比与实践总结

在现代应用开发中&#xff0c;身份认证是一个关键的问题。为了解决身份认证的需求&#xff0c;开发人员可以选择不同的认证系统&#xff0c;如Token、CAS&#xff08;Central Authentication Service&#xff09;和JWT&#xff08;JSON Web Token&#xff09;OAuth 2.0认证系统…

大厂聚合支付系统架构演进(上)

点击下方“JavaEdge”&#xff0c;选择“设为星标” 第一时间关注技术干货&#xff01; 关注我&#xff0c;紧跟本系列专栏文章&#xff0c;咱们下篇再续&#xff01; 作者简介&#xff1a;魔都国企技术专家兼架构&#xff0c;多家大厂后端一线研发经验&#xff0c;各大技术社区…

1.0 Zookeeper 分布式配置服务教程

ZooKeeper 是 Apache 软件基金会的一个软件项目&#xff0c;它为大型分布式计算提供开源的分布式配置服务、同步服务和命名注册。 ZooKeeper 的架构通过冗余服务实现高可用性。 Zookeeper 的设计目标是将那些复杂且容易出错的分布式一致性服务封装起来&#xff0c;构成一个高…

GPTs保姆级教程之实践

GPTs什么 使用GPTs的前提&#xff1a;ChatGPT Plus帐号 GTPs的作用&#xff1a;把我们和GPT对话的prompt&#xff0c;封装起来成为一个“黑匣子”。 主要有两个作用&#xff1a; 1、避免反复输入prompt&#xff0c;“黑匣子”打开&#xff0c;输入问题即可使用 2、在别人可以…

pycharm deployment 灰色 一直无法点击

我的development的配置如下&#xff0c;我看了很多教程一直不知道为什么一直是灰色的&#xff0c; 文件夹配置&#xff1a; 如果你这里 Autodect&#xff0c;那么你Mapping 的文件夹应该是应该省略这个前缀的&#xff0c;例如我下面&#xff0c;我应该将本地文件夹映射到/home…

项目经理怎么处理客户提出的不合理请求?

一、客户不合理请求的定义和特点 客户不合理请求是指客户在项目执行过程中提出的与项目需求、合同约定或者实际情况不符的要求&#xff0c;通常表现为追加要求、频繁的变更、过度的要求等。这些请求可能会导致项目范围膨胀、成本增加、工期延长、甚至影响项目进度和质量。客户…

【HTML】MDN

文章目录 一、html元素1.1 <a>1.2 <abbr>1.3 <address>1.4<area>1.5 <article>1.6 <aside>1.7 <audio>1.8 <b>1.9 <base>1.10<bdi>1.11 <bdo>1.12 <blockquote>1.13 <body>1.14 <br>1.15…

人工智能(pytorch)搭建模型24-SKAttention注意力机制模型的搭建与应用场景

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能(pytorch)搭建模型24-SKAttention注意力机制模型的搭建与应用场景&#xff0c;本文将介绍关于SKAttention注意力机制模型的搭建&#xff0c;SKAttention机制具有灵活性和通用性&#xff0c;可应用于计算机视…

一个Vivado仿真问题的debug

我最近在看Synopsys的MPHY仿真代码&#xff0c;想以此为参考写个能实现PWM-G1功能的MPHY&#xff0c;并应用于ProFPGA原型验证平台。我从中抽取了一部分代码&#xff0c;用Vivado自带的仿真器进行仿真&#xff0c;然后就遇到了一个莫名其妙的问题&#xff0c;谨以此文作为debug…

ROS2 CMakeLists.txt 和 package.xml

这里记录一下ROS2中功能包package.xml和CMakeLists.txt的格式。以LIO-SAM的ROS2版本为例&#xff1a; 一&#xff1a;CMakeLists.txt cmake_minimum_required(VERSION 3.5) project(lio_sam)if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)set(CMAKE_BUILD_TYPE…

C语言之自定义类型:联合和枚举

目录 1. 联合体类型的声明2. 联合体的特点3. 联合体大小的计算联合的一个练习 4. 枚举类型的声明5. 枚举类型的优点6. 枚举类型的使用 1. 联合体类型的声明 像结构体一样&#xff0c;联合体也是由一个或者多个成员构成&#xff0c;这些成员可以不同的类型 但是编译器只为最大…

vCenterServer部署

一、硬件配置 vCenterServer本身最低的硬件要求是14GB&#xff0c;而vCenterServer则是以虚拟机的形式安装在ESXi中的虚拟机&#xff0c;所以ESXi的最低硬件要求是15.5GB&#xff0c;就是15872MB 二、安装vCenterServer 直接解压VMware-VCSA-all-8.0.0-20920323.iso&#xf…

TDengine用户权限管理

Background 官方文档关于用户管理没有很详细的介绍&#xff0c;只有零碎的几条&#xff0c;这里记录下方便后面使用。官方文档&#xff1a;https://docs.taosdata.com/taos-sql/show/#show-users 1、查看用户 show users;super 1&#xff0c;表示超级用户权限 0&#xff0c;表…

python实现飞书群机器人消息通知

python实现飞书群机器人消息通知&#xff08;消息卡片&#xff09; 直接上代码 """ 飞书群机器人发送通知 """ import time import urllib3 import datetimeurllib3.disable_warnings()class FlybookRobotAlert():def __init__(self):self.web…

一道sql注入的ctf题目致使用phpmyadmin上传 webshell 拿后台权限

以下均为靶场测试环境渗透&#xff0c;非正式环境。 遇见登录框&#xff0c;直接万能密码’or(11)or’/1 直接登录成功并返回结果: 既然存在sql注入&#xff0c;那就用sqlmap跑一下吧&#xff1a; 输出所有的数据库&#xff1a; sqlmap -u <目标URL> --dbs 要输出数据库…

Android Button background 失效

问题 Android Button background 失效 详细问题 笔者开发Android项目&#xff0c;期望按照 android:background中所要求的颜色展示。 实际显示按照Android 默认颜色展示 解决方案 将xml的Button 组件修改为<android.widget.Button> 即将代码 <Buttonandroid:l…

「云原生可观测团队」获选「InfoQ 年度技术内容贡献奖」

随着云原生、人工智能逐渐成为各行各业的创新生产力工具。可以预见&#xff0c;我们即将进入全新的智能化时代。随着数据成为新型生产要素&#xff0c;云和 AI 正走向深度融合。云原生通过提供大规模多元算力的高效供给&#xff0c;可观测成为业务创新的核心基础设施&#xff0…

CSS伸缩盒模型

CSS伸缩盒模型 伸缩盒模型是CSS中的一种布局手段&#xff0c;可以使元素具有弹性&#xff0c;让元素可以跟随页面大小的改变而改变。 1. 伸缩容器 给元素设置display:flex 或 display:inline-flex &#xff0c;就是伸缩容器。 2. 主轴与侧轴 主轴&#xff1a; 伸缩项目沿着…

python coding with ChatGPT 打卡第17天| 二叉树:找树左下角的值、路径总和

相关推荐 python coding with ChatGPT 打卡第12天| 二叉树&#xff1a;理论基础 python coding with ChatGPT 打卡第13天| 二叉树的深度优先遍历 python coding with ChatGPT 打卡第14天| 二叉树的广度优先遍历 python coding with ChatGPT 打卡第15天| 二叉树&#xff1a;翻转…