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 bt

cerebro = 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 bt

cerebro = 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 bt

cerebro = 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 Sample

optional 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 For
                        example: --plot style="candle" (to plot candles)
                        (default: None)

8.代码

from __future__ import (absolute_import, division, print_function,
                        unicode_literals)


import argparse
import datetime
import random

import backtrader as bt


class 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 running
            txtfields = 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'] = fromdate

    if args.todate:
        todate = datetime.datetime.strptime(args.todate, '%Y-%m-%d')
        dkwargs['todate'] = todate

    data0 = 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 = data0
        if args.benchdata1:
            data1 = bt.feeds.YahooFinanceCSVData(dataname=args.data1, **dkwargs)
            cerebro.adddata(data1, name='Data1')
            benchdata = data1

        cerebro.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 True
            pkwargs = eval('dict(' + args.plot + ')')  # args were passed

        cerebro.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 options
    parser.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()

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue父子组件通讯的几种方式总结学习

一直都是公司前端在写组件&#xff0c;我想着自己也写一波&#xff0c;然后先看看父子组件传值的内容&#xff0c;想写一写小demo然后练习一下这个内容&#xff0c;也算是系统学习一下怎么处理这个内容 其实就是2种父传子和子传父 1.父组件传子组件数据 其实就是父在标签中可…

计算机网络-流量控制(数据链路层的流量控制及与传输层流量控制的区别 流量控制的方法 可靠传输,滑动窗口,流量控制三者关系)

文章目录 数据链路层的流量控制及与传输层流量控制的区别流量控制的方法各方法对应的发生窗口和接收窗口大小 可靠传输&#xff0c;滑动窗口&#xff0c;流量控制三者关系小结 数据链路层的流量控制及与传输层流量控制的区别 端到端&#xff1a;两个主机之间的 点对点&#xf…

恒创科技:服务器内存不足影响大吗?

​  服务器在为网站、应用程序和在线服务提供支持方面发挥着关键作用。这些服务器需要提供最佳性能&#xff0c;以确保正常无缝的用户体验&#xff0c;而RAM是显著影响服务器性能的关键配置之一。 RAM 是一种随机存取存储器&#xff0c;计算机和服务器使用它来临时存储正在使…

VM安装Centos7

目标&#xff1a; 一&#xff0c;安装Centos7 二&#xff0c;ssh可以连接 1 新建虚拟机 一直下一步 2 直到此处&#xff0c;选择稍后安装 一直下一步直到完成。 3 选中虚拟机&#xff0c;点击设置 选择CD/DVD&#xff0c;选取ISO映像文件。 4 等待安装 并且设置root密码 5…

苹果证书过期有什么影响

引言 苹果证书是一种数字签名&#xff0c;用于验证应用程序的身份和完整性。然而&#xff0c;若该证书过期&#xff0c;将会对用户和开发者带来一定的影响。在本文中&#xff0c;我们将详细介绍苹果证书过期的原理和影响&#xff0c;并提供一些解决方法。 苹果证书的原理 苹…

机器学习 | 探索朴素贝叶斯算法的应用

朴素贝叶斯算法是一种基于贝叶斯定理和特征条件独立假设的分类算法。它被广泛应用于文本分类、垃圾邮件过滤、情感分析等领域&#xff0c;并且在实际应用中表现出色。 朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法&#xff1a; 1&#xff09;对于给定的待分类项r…

Redis(十三)缓存双写一致性策略

文章目录 概述示例 缓存双写一致性缓存按照操作来分&#xff0c;细分2种读写缓存&#xff1a;同步直写策略读写缓存&#xff1a;异步缓写策略双检加锁策略 数据库和缓存一致性更新策略先更新数据库&#xff0c;再更新缓存先更新缓存&#xff0c;再更新数据库先删除缓存&#xf…

【el-tree 文字过长处理方案】

文字过长处理方案 一、示例代码二、关键代码三、效果图 一、示例代码 <divstyle"height: 600px;overflow: auto"class"text item"><el-treeref"tree":data"treeData":props"defaultProps"class"filter-tree&…

C++ 语法文件

程序运行时产生的数据都属于临时数据&#xff0c;程序结束就会被释放。 通过文件可以可以将数据持久化 c中对文件操作需要包含头文件fstream 文件的类型分为两种 1.文本文件 文件以文本的ASCII码形式存储在计算机中 2.二进制文件 稳重以文本的二进制形式存储在计算机中 用…

【云原生之kubernetes系列】--HPA自动伸缩

HPA自动伸缩 HorizontalPodAutoscaler&#xff08;简称 HPA &#xff09;自动更新工作负载资源&#xff08;例如Deployment或者Statefulset)&#xff0c;目的是让pod可以自动扩缩工作负载以满足业务需求。 水平扩缩意味着对增加的负载的响应是部署更多的Pod。这与“垂直&…

MIT_线性代数笔记:第 34 讲 总复习

目录 试题1试题2试题3试题4试题5 本讲为线性代数课程总复习&#xff0c;复习的方法就是做往年试题。 试题1 1&#xff09;已知 Ax [ 1 0 0 ] \begin{bmatrix} 1\\0\\0 \end{bmatrix} ​100​ ​ 无解&#xff0c;Ax [ 0 1 0 ] \begin{bmatrix} 0\\1\\0 \end{bmatrix} ​010​ …

锐捷VSU和M-LAG介绍

参考网站 堆叠、级联和集群的概念 什么是堆叠&#xff1f; 框式集群典型配置 RG-S6230[RG-S6501-48VS8CQ]系列交换机 RGOS 12.5(4)B1005版本 配置指南 总结 根据以上的几篇文章总结如下&#xff1a; 级联&#xff1a;简单&#xff0c;交换机相连就叫级联&#xff0c;跟搭…

2-1 动手学深度学习v2-Softmax回归-笔记

回归 VS 分类 回归估计一个连续值分类预测一个离散类别 从回归到多类分类 回归 单连续数值输出输出的区间&#xff1a;自然区间 R \mathbb{R} R损失&#xff1a;跟真实值的区别 分类 通常多个输出&#xff08;这个输出的个数是等于类别的个数&#xff09;输出的第 i i i…

0-MQTT基础使用教程【学习】

文件路径 MQTT基础使用教程1. MQTT1.1 MQTT简介1.1.1 什么是MQTT1.1.2 设计原则1.1.3 应用领域1.2 MQTT协议相关概念1.2.1 MQTT协议实现方式1.2.2 MQTT协议中的方法1.3 消息服务质量QoS1.3.1 消息服务质量QoS三个等级1.3.2 发布与订阅QoS1.4 Topic通配符匹配规则2. EMQX2.1 EMQ…

工程机械设备通讯如何选?CAN控制器 以太网控制器

在工程机械设备的通讯世界中&#xff0c;有四种主流的通讯方式各领风骚。它们各有特色&#xff0c;适用于不同的场景和需求。让我们一起来深入了解它们&#xff0c;看看如何为自己的设备选择最合适的通讯方式吧&#xff01; 以太网通讯 特点速览&#xff1a;高速、稳如磐石、…

IP代理在网络中解决了哪些问题?代理IP使用时效是什么意思?

随着互联网的普及和发展&#xff0c;IP代理作为一种网络工具&#xff0c;被广泛应用于各种场景。IP代理的使用可以解决很多网络中的问题&#xff0c;提高网络访问的速度和安全性。本文将详细介绍IP代理在网络中解决的问题&#xff0c;以及代理IP使用时效的含义。 一、IP代理在网…

用python实现pdf按页切割,以及将pdf转成图片

我们经常遇到需要切割pdf的时候&#xff0c;但是常规手段很难做到 我们可以利用python脚本来实现 需要安装几个库 tk PyPDF2 PyMuPDF pyinstaller 上图&#xff01; 查看结果 切割pdf转存成图像 那我们来详细说一下使用方法 1.输入PDF位置:这里没什么好说的&#xff0c…

vue3:24—组件通信方式

1、props 子组件也可以如下调用父组件的方法 2、自定义事件 &#xff08;emit&#xff09; 3、mitt&#xff08;任意组件的通讯&#xff09; 1. pubsub 2. $bus 3. mitt 接收数据的:提前绑定好事件(提前订阅消息)提供数据的:在合适的时候触发事件发布消息) 安装mitt npm i…

NLP深入学习:《A Survey of Large Language Models》详细学习(三)

文章目录 1. 前言2. 预训练2.1 数据搜集与准备2.1.1 数据源2.1.2 数据预处理2.1.3 数据调度 2.2 架构设计2.2.1 典型架构2.2.2 详细配置2.2.3 预训练任务2.2.4 长上下文建模2.2.5 解码策略 2.3 模型训练2.3.1 优化设置2.3.2 可扩展&#xff08;Scalable&#xff09;的训练技术 …

线性代数:矩阵的初等变换

目录 一、初等行变换 行阶梯 / 行最简 性质 二、矩阵的标准型 三、矩阵的等价 四、初等矩阵 五、重要性质与定理 一、初等行变换 行阶梯 / 行最简 性质 二、矩阵的标准型 三、矩阵的等价 四、初等矩阵 五、重要性质与定理