Backtrader 文档学习- Observers

Backtrader 文档学习- Observers

1.概述

在backtrader中运行的策略主要处理数据源和指标。
数据源被加载到Cerebro实例中,并最终成为策略的一部分(解析和提供实例的属性),而指标则由策略本身声明和管理。
到目前为止,所有backtrader示例图表都有三个默认绘制的东西,因为它们没有在任何地方声明,默认执行:

  • 现金和价值(经纪人中的资金情况)
  • 交易(也称为操作)
  • 买入/卖出订单
    它们是Observers观察者,存在于子模块backtrader.observers中。它们存在是因为Cerebro支持一个参数来自动添加(或不添加)它们到策略中:
  • stdstats(默认值:True)
    如果默认值被使用,Cerebro将执行以下等效的用户代码:
import backtrader as bt...cerebro = bt.Cerebro()  # default kwarg: stdstats=Truecerebro.addobserver(bt.observers.Broker)
cerebro.addobserver(bt.observers.Trades)
cerebro.addobserver(bt.observers.BuySell)

观察带有这三个默认观察者的常规图表(即使没有下达订单,没有交易发生,现金和组合价值也没有变化)

from __future__ import (absolute_import, division, print_function,unicode_literals)
%matplotlib inline
import backtrader as bt
import backtrader.feeds as btfeedsif __name__ == '__main__':cerebro = bt.Cerebro() # stdstats=Falsecerebro.addstrategy(bt.Strategy)data = bt.feeds.BacktraderCSVData(dataname='./datas/2006-day-001.txt')cerebro.adddata(data)cerebro.run()cerebro.plot(iplot=False)

图示:
在这里插入图片描述
在创建Cerebro实例时将stdstats的值更改为False(也可以在调用run时完成):

cerebro = bt.Cerebro(stdstats=False)

在这里插入图片描述

2.Accesing the Observers

观察者在默认情况下已经存在,并收集可用于统计目的的信息,这就是为什么可以通过策略的一个属性来访问观察者:

  • stats

它只是一个占位符。如果回想一下如何添加默认的观察者:

...
cerebro.addobserver(backtrader.observers.Broker)
...

显然问题是如何访问Broker观察者。例如,如何从策略的next方法中执行此操作:

class MyStrategy(bt.Strategy):def next(self):if self.stats.broker.value[0] < 1000.0:print('WHITE FLAG ... I LOST TOO MUCH')elif self.stats.broker.value[0] > 10000000.0:print('TIME FOR THE VIRGIN ISLANDS ....!!!')

Broker观察者就像数据、指标和策略本身一样,也是一个Lines对象。在这种情况下,Broker有2条线:

  • cash
  • value

3.Observer Implementation

实现与指标非常相似:

class Broker(Observer):alias = ('CashValue',)lines = ('cash', 'value')plotinfo = dict(plot=True, subplot=True)def next(self):self.lines.cash[0] = self._owner.broker.getcash()self.lines.value[0] = value = self._owner.broker.getvalue()

步骤:

  • 从Observer(而不是Indicator)派生
  • 根据需要声明行和参数(Broker有2行但没有参数)
  • 将自动属性_owner,设置为持有观察者的策略

注意:_owner的属性

观察者开始工作:

  • 在所有指标计算完成后
  • 在策略next方法执行后
  • 意味着:在循环结束时…观察到发生了什么
    在Broker中,只是机械地记录在每个时间点上经纪人现金和组合价值。

4.Adding Observers to the Strategy

如上所指出的,Cerebro使用stdstats参数来决定是否添加3个默认的观察者,减轻了最终用户的工作。
添加其他观察者是可能的,无论是沿着stdstats还是删除它们。
让我们采用通常的策略,当close价格超过SimpleMovingAverage时购买,如果相反则卖出。
增加一个观察者:

  • DrawDown 回撤,它是backtrader 生态系统中已经存在的观察者
from __future__ import (absolute_import, division, print_function,unicode_literals)import argparse
import datetime
import os.path
import time
import sysimport backtrader as bt
import backtrader.feeds as btfeeds
import backtrader.indicators as btind%matplotlib inlineclass MyStrategy(bt.Strategy):params = (('smaperiod', 15),)def log(self, txt, dt=None):''' Logging function fot this strategy'''dt = dt or self.data.datetime[0]if isinstance(dt, float):dt = bt.num2date(dt).date()print('%s, %s' % (dt.isoformat(), txt))def __init__(self):# SimpleMovingAverage on main data# Equivalent to -> sma = btind.SMA(self.data, period=self.p.smaperiod)sma = btind.SMA(period=self.p.smaperiod)# CrossOver (1: up, -1: down) close / smaself.buysell = btind.CrossOver(self.data.close, sma, plot=True)# Sentinel to None: new ordersa allowedself.order = Nonedef next(self):# Access -1, because drawdown[0] will be calculated after "next"self.log('DrawDown: %.2f' % self.stats.drawdown.drawdown[-1])self.log('MaxDrawDown: %.2f' % self.stats.drawdown.maxdrawdown[-1])# Check if we are in the marketif self.position:if self.buysell < 0:self.log('SELL CREATE, %.2f' % self.data.close[0])self.sell()elif self.buysell > 0:self.log('BUY CREATE, %.2f' % self.data.close[0])self.buy()def runstrat():cerebro = bt.Cerebro()data = bt.feeds.BacktraderCSVData(dataname='./datas/2006-day-001.txt')cerebro.adddata(data)cerebro.addobserver(bt.observers.DrawDown)cerebro.addstrategy(MyStrategy)cerebro.run()cerebro.plot(iplot=False)if __name__ == '__main__':runstrat()

图表的输出显示了回撤的演变
在这里插入图片描述
输出:

... ...
2006-12-12, DrawDown: 0.63
2006-12-12, MaxDrawDown: 2.62
2006-12-13, DrawDown: 0.63
2006-12-13, MaxDrawDown: 2.62
2006-12-14, DrawDown: 0.56
2006-12-14, MaxDrawDown: 2.62
2006-12-15, DrawDown: 0.22
2006-12-15, MaxDrawDown: 2.62
2006-12-18, DrawDown: 0.00
2006-12-18, MaxDrawDown: 2.62
2006-12-19, DrawDown: 0.00
2006-12-19, MaxDrawDown: 2.62
2006-12-20, DrawDown: 0.10
2006-12-20, MaxDrawDown: 2.62
2006-12-21, DrawDown: 0.39
2006-12-21, MaxDrawDown: 2.62
2006-12-22, DrawDown: 0.21
2006-12-22, MaxDrawDown: 2.62
2006-12-27, DrawDown: 0.28
2006-12-27, MaxDrawDown: 2.62
2006-12-28, DrawDown: 0.65
2006-12-28, MaxDrawDown: 2.62
2006-12-29, DrawDown: 0.06
2006-12-29, MaxDrawDown: 2.62

注意:
如文本输出和代码中所示,DrawDown观察者实际上有2条线:

  • drawdown
  • maxdrawdown
    选择不绘制最大回撤线,但使其可供用户使用。
    实际上maxdrawdown的最后一个值也可以通过一个直接属性(而不是一条线)来获得,该属性的名称为maxdd

5.Developing Observers

上面展示了Broker观察者的实现。为了产生有意义的观察者,实现可以使用以下信息:

  • self._owner是当前正在执行的策略
    策略中的任何内容都可以用于观察者

  • 策略中可用的默认内部内容可能有用:

    • broker-> 属性,提供对策略创建订单的broker实例的访问
      如在Broker中所见,通过调用方法getcash和getvalue收集现金和组合值
  • _orderspending-> 策略创建的订单列表,broker已向策略通知事件。
    BuySell观察者遍历列表,查找已执行(完全或部分)的订单,以创建给定时间点(索引0)的平均执行价格

  • _tradespending-> 交易列表(已完成的买入/卖出或卖出/买入对的集合),从买入/卖出订单编译而成
    观察者可以通过self._owner.stats路径访问其他观察者。

6.Custom OrderObserver

标准的BuySell观察者只关心已执行的操作。可以创建一个观察者,显示订单何时创建以及它们是否过期。
为了可见性,显示将不会沿价格轴上绘制,而是在单独的轴上绘制。

from __future__ import (absolute_import, division, print_function,unicode_literals)import datetimeimport backtrader as bt
import backtrader.feeds as btfeeds
import backtrader.indicators as btind#直接放在一个程序中。
#from backtrader.orderobserver import OrderObserver
%matplotlib inlineclass MyStrategy(bt.Strategy):params = (('smaperiod', 15),('limitperc', 1.0),('valid', 7),)def log(self, txt, dt=None):''' Logging function fot this strategy'''dt = dt or self.data.datetime[0]if isinstance(dt, float):dt = bt.num2date(dt).date()print('%s, %s' % (dt.isoformat(), txt))def notify_order(self, order):if order.status in [order.Submitted, order.Accepted]:# Buy/Sell order submitted/accepted to/by broker - Nothing to doself.log('ORDER ACCEPTED/SUBMITTED', dt=order.created.dt)self.order = orderreturnif order.status in [order.Expired]:self.log('BUY EXPIRED')elif order.status in [order.Completed]:if order.isbuy():self.log('BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %(order.executed.price,order.executed.value,order.executed.comm))else:  # Sellself.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %(order.executed.price,order.executed.value,order.executed.comm))# Sentinel to None: new orders allowedself.order = Nonedef __init__(self):# SimpleMovingAverage on main data# Equivalent to -> sma = btind.SMA(self.data, period=self.p.smaperiod)sma = btind.SMA(period=self.p.smaperiod)# CrossOver (1: up, -1: down) close / smaself.buysell = btind.CrossOver(self.data.close, sma, plot=True)# Sentinel to None: new ordersa allowedself.order = Nonedef next(self):if self.order:# pending order ... do nothingreturn# Check if we are in the marketif self.position:if self.buysell < 0:self.log('SELL CREATE, %.2f' % self.data.close[0])self.sell()elif self.buysell > 0:plimit = self.data.close[0] * (1.0 - self.p.limitperc / 100.0)valid = self.data.datetime.date(0) + \datetime.timedelta(days=self.p.valid)self.log('BUY CREATE, %.2f' % plimit)self.buy(exectype=bt.Order.Limit, price=plimit, valid=valid)class OrderObserver(bt.observer.Observer):lines = ('created', 'expired',)plotinfo = dict(plot=True, subplot=True, plotlinelabels=True)plotlines = dict(created=dict(marker='*', markersize=8.0, color='lime', fillstyle='full'),expired=dict(marker='s', markersize=8.0, color='red', fillstyle='full'))def next(self):for order in self._owner._orderspending:if order.data is not self.data:continueif not order.isbuy():continue# Only interested in "buy" orders, because the sell orders# in the strategy are Market orders and will be immediately# executedif order.status in [bt.Order.Accepted, bt.Order.Submitted]:self.lines.created[0] = order.created.priceelif order.status in [bt.Order.Expired]:self.lines.expired[0] = order.created.pricedef runstrat():cerebro = bt.Cerebro()data = bt.feeds.BacktraderCSVData(dataname='./datas/2006-day-001.txt')cerebro.adddata(data)cerebro.addobserver(OrderObserver)cerebro.addstrategy(MyStrategy)cerebro.run()cerebro.plot(iplot=False)if __name__ == '__main__':runstrat()

自定义观察者只关心买入订单,因为这是一种只买入以试图获利的策略。卖出订单是市价订单,将立即执行。
Close-SMA CrossOver策略规则更改为:

  • 创建一个价格低于此时刻收盘价1.0%以下的限价订单
  • 订单的有效期为7(日历)天
    在这里插入图片描述

如新子图(红色方块)所示,新增的Observer 对象,created 和 expired ,有几个订单已过期,还看到在创建和执行间隔了几天。

输出结果:

2006-01-26, BUY CREATE, 3605.01
2006-01-26, ORDER ACCEPTED/SUBMITTED
2006-01-26, ORDER ACCEPTED/SUBMITTED
2006-02-02, BUY EXPIRED
2006-03-10, BUY CREATE, 3760.48
2006-03-10, ORDER ACCEPTED/SUBMITTED
2006-03-10, ORDER ACCEPTED/SUBMITTED
2006-03-17, BUY EXPIRED
2006-03-30, BUY CREATE, 3835.86
2006-03-30, ORDER ACCEPTED/SUBMITTED
2006-03-30, ORDER ACCEPTED/SUBMITTED
2006-04-05, BUY EXECUTED, Price: 3835.86, Cost: 3835.86, Comm 0.00
2006-04-07, SELL CREATE, 3823.11
2006-04-07, ORDER ACCEPTED/SUBMITTED
2006-04-07, ORDER ACCEPTED/SUBMITTED
2006-04-10, SELL EXECUTED, Price: 3822.35, Cost: 3835.86, Comm 0.00
2006-04-20, BUY CREATE, 3821.40
2006-04-20, ORDER ACCEPTED/SUBMITTED
2006-04-20, ORDER ACCEPTED/SUBMITTED
2006-04-27, BUY EXPIRED
2006-05-04, BUY CREATE, 3804.65
2006-05-04, ORDER ACCEPTED/SUBMITTED
2006-05-04, ORDER ACCEPTED/SUBMITTED
2006-05-11, BUY EXPIRED
2006-06-01, BUY CREATE, 3611.85
2006-06-01, ORDER ACCEPTED/SUBMITTED
2006-06-01, ORDER ACCEPTED/SUBMITTED
2006-06-05, BUY EXECUTED, Price: 3611.85, Cost: 3611.85, Comm 0.00
2006-06-05, SELL CREATE, 3604.33
2006-06-05, ORDER ACCEPTED/SUBMITTED
2006-06-05, ORDER ACCEPTED/SUBMITTED
2006-06-06, SELL EXECUTED, Price: 3598.58, Cost: 3611.85, Comm 0.00
2006-06-21, BUY CREATE, 3491.57
2006-06-21, ORDER ACCEPTED/SUBMITTED
2006-06-21, ORDER ACCEPTED/SUBMITTED
2006-06-28, BUY EXPIRED
2006-07-24, BUY CREATE, 3596.60
2006-07-24, ORDER ACCEPTED/SUBMITTED
2006-07-24, ORDER ACCEPTED/SUBMITTED
2006-07-31, BUY EXPIRED
2006-09-12, BUY CREATE, 3751.07
2006-09-12, ORDER ACCEPTED/SUBMITTED
2006-09-12, ORDER ACCEPTED/SUBMITTED
2006-09-19, BUY EXPIRED
2006-09-20, BUY CREATE, 3802.90
2006-09-20, ORDER ACCEPTED/SUBMITTED
2006-09-20, ORDER ACCEPTED/SUBMITTED
2006-09-22, BUY EXECUTED, Price: 3802.90, Cost: 3802.90, Comm 0.00
2006-11-02, SELL CREATE, 3974.62
2006-11-02, ORDER ACCEPTED/SUBMITTED
2006-11-02, ORDER ACCEPTED/SUBMITTED
2006-11-03, SELL EXECUTED, Price: 3979.73, Cost: 3802.90, Comm 0.00
2006-11-06, BUY CREATE, 4004.77
2006-11-06, ORDER ACCEPTED/SUBMITTED
2006-11-06, ORDER ACCEPTED/SUBMITTED
2006-11-13, BUY EXPIRED
2006-12-11, BUY CREATE, 4012.36
2006-12-11, ORDER ACCEPTED/SUBMITTED
2006-12-11, ORDER ACCEPTED/SUBMITTED
2006-12-18, BUY EXPIRED

最后,应用新的观察者的策略代码,见前。

7.Saving/Keeping the statistics

保存/保持统计信息到目前为止,backtrader尚未实现任何机制来跟踪观察者的值并将其存储到文件中。最好的方法是:

  • 在策略的start方法中打开文件
  • 在策略的next方法中将值写入
    考虑到DrawDown观察者,可以做:
class MyStrategy(bt.Strategy):def start(self):self.mystats = open('mystats.csv', 'wb')self.mystats.write('datetime,drawdown, maxdrawdown\n')def next(self):self.mystats.write(self.data.datetime.date(0).strftime('%Y-%m-%d'))self.mystats.write(',%.2f' % self.stats.drawdown.drawdown[-1])self.mystats.write(',%.2f' % self.stats.drawdown.maxdrawdown-1])self.mystats.write('\n')

要保存索引0的值,一旦处理完所有观察者,可以将自定义观察者添加为系统中的最后一个观察者,以将值保存到csv文件中。

注意:Writer的功能可以自动化此任务。

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

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

相关文章

LabVIEW多功能接口卡驱动

LabVIEW多功能接口卡驱动 随着自动化测试系统的复杂性增加&#xff0c;对数据采集与处理的需求不断提高。研究基于LabVIEW开发平台&#xff0c;实现对一种通用多功能接口卡的驱动&#xff0c;以支持多通道数据采集及处理功能&#xff0c;展现LabVIEW在自动化和测量领域的强大能…

如何部署Docker Registry并实现无公网ip远程连接本地镜像仓库

文章目录 1. 部署Docker Registry2. 本地测试推送镜像3. Linux 安装cpolar4. 配置Docker Registry公网访问地址5. 公网远程推送Docker Registry6. 固定Docker Registry公网地址 Docker Registry 本地镜像仓库,简单几步结合cpolar内网穿透工具实现远程pull or push (拉取和推送)…

IPv4的公网地址不够?NAT机制可能是当下最好的解决方案

目录 1.前言 2.介绍 3.NAT机制详解 1.前言 我们都知道IPv4的地址范围是32个字节,这其中还有很多地址是不可用的.比如127.*,这些都是环回地址.那么在网路发展日新月异的今天,互联网设备越来越多,我们该如何解决IP地址不够用的问题呢?目前有一种主流的解决方案,也是大家都在用…

Visual Studio 2022 查看类关系图

这里写自定义目录标题 右键要查看的项目 -“查看”-“查看类图”效果展示&#xff1a; 原文地址 www.cnblogs.com 步骤1&#xff1a;勾选扩展开发 步骤2: 勾选类设计器 右键要查看的项目 -“查看”-“查看类图” 效果展示&#xff1a;

操作系统-02-Ubuntu 常用命令等汇总

Ubuntu Ubuntu是一个开源软件平台&#xff0c;可以在从智能手机、平板电脑和个人电脑到服务器和云端等各种设备上运行。 ubuntu Title: Desktop Ubuntu desktop->command: CtrlAltF2~F6 command->desktop: CtrlAltF7 Login Change to root user $ sudu suLogin to al…

AI嵌入式K210项目(27)-条形码识别

文章目录 前言一、什么是条形码&#xff1f;二、实验准备三、实验过程四、API接口总结 前言 本章介绍基于机器视觉实现条形码识别&#xff0c;主要包含两个过程&#xff0c;首先检测图像中是否有条形码&#xff0c;如果有则框出并打印条形码信息&#xff1b; 一、什么是条形码…

ShardingSphere实现openGauss分布式架构

本文档采用openGauss结合ShardingSphere中间件的架构&#xff0c;实现openGauss数据库分布式OLAP场景的环境部署。 术语说明&#xff1a; 开源数据库引擎&#xff1a;openGauss shardingsphere Proxy&#xff1a;定位为透明化的数据库代理端&#xff0c;提供封装了数据库二进…

示波器的电压怎么和测量的电压不一样,空比增加以后 示波器显示的电压反而降低了?

这两天在调电机&#xff0c;发现我用pwm信号&#xff0c;发送给示波器&#xff0c;但是示波器测量的电压和万用表测量的完全不一样&#xff0c;而有奇怪的现象&#xff0c;空比增加以后 示波器显示的电压反而降低了。 最后发现是通道没有设置&#xff0c;要设置成直流模式 点ch…

docker之程序镜像的制作

目录 一、每种资源的预安装&#xff08;基础&#xff09; 安装 nginx安装 redis 二、dockerfile文件制作&#xff08;基础&#xff09; 打包 redis 镜像 创建镜像制作空间制作dockerfile 打包 nginx 镜像 三、创建组合镜像&#xff08;方式一&#xff09; 生成centos容器并…

补题:leetcode第382场周赛 3022. 给定操作次数内使剩余元素的或值最小

3022. 给定操作次数内使剩余元素的或值最小 - 力扣&#xff08;LeetCode&#xff09; 拆位 n个数进行或运算的结果最小&#xff0c;每次操作可以对相邻的两个数进行与运算&#xff0c;至多进行k次操作 n个数进行或运算&#xff0c;可以对每个数进行拆解&#xff0c;拆解成最小…

分享springboot框架的一个开源的本地开发部署教程(若依开源项目开发部署过程分享持续更新二开宝藏项目PostgresSQL数据库版)

1首先介绍下若依项目&#xff1a; 若依是一个基于Spring Boot和Spring Cloud技术栈开发的多租户权限管理系统。该开源项目提供了一套完整的权限管理解决方案&#xff0c;包括用户管理、角色管理、菜单管理、部门管理、岗位管理等功能。 若依项目采用前后端分离的架构&#xf…

使用代理IP有风险吗?如何安全使用代理IP?

代理IP用途无处不在。它们允许您隐藏真实IP地址&#xff0c;从而实现匿名性和隐私保护。这对于保护个人信息、绕过地理受限的内容或访问特定网站都至关重要。 然而&#xff0c;正如任何技术工具一样&#xff0c;代理IP地址也伴随着潜在的风险和威胁。不法分子可能会滥用代理IP…

ue5 蓝图内修改组件附加的插槽

Target是目标,Parent是要加到哪个骨骼上,socketName是骨骼对应的插槽

基于Springboot的考编论坛网站的设计与实现(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的考编论坛网站的设计与实现&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层…

【华为云】云上两地三中心实践实操

写在前面 应用上云之后&#xff0c;如何进行数据可靠性以及业务连续性的保障是非常关键的&#xff0c;通过华为云云上两地三中心方案了解相关方案认证地址&#xff1a;https://connect.huaweicloud.com/courses/learn/course-v1:HuaweiXCBUCNXI057Self-paced/about当前内容为华…

vulnhub中Beelzebub靶机

渗透思路 一.信息收集1.网段探测2.端口探测3.常见漏洞扫描4.目录扫描5.web页面分析 二.渗透继续目录扫描ssh连接提权提权&#xff0c;flag 一.信息收集 1.网段探测 ┌──(root㉿kali)-[~] └─# nmap -Pn 192.168.0.0/24 --min-rate 10000 Starting …

awd总结

总结&#xff1a; 由于是第一次参加AWD比赛&#xff0c;各方面经验都不足&#xff0c;在参赛的前几天也是疯狂搜集各种脚本、框架、工具等&#xff0c;同时也参考b站的视频进行学习&#xff0c;我发现就是还是实操才能更快的学习 我觉得就是我前期的准备工作不足&#xff0c;…

【sentinel流量卫兵配置持久化到Nacos】

sentinel流量卫兵配置持久化到Nacos 概述&#xff1a; 一、添加配置二、配置说明限流规则配置&#xff1a;降级规则配置&#xff1a;热点规则配置&#xff1a;授权规则配置&#xff1a;系统规则配置&#xff1a; 三、服务整合 概述&#xff1a; 控制台配置的参数&#xff0c;默…

STM32WLE5JC

Sub-GHz 无线电介绍 sub-GHz无线电是一种超低功耗sub-GHz无线电&#xff0c;工作在150-960MHz ISM频段。 在发送和接收中采用LoRa和&#xff08;G&#xff09;FSK调制&#xff0c;仅在发送中采用BPSK/(G)MSK调制&#xff0c;可以在距离、数据速率和功耗之间实现最佳权衡。 这…

Maven的安装以及配置(超级详细版)

前言 至于什么是Maven&#xff0c;大家可以理解为之前的Vue一样&#xff0c;也是通过操控对象映射来使用的 他内部还有很多的插件用于实现对应的功能&#xff0c;例如打包插件&#xff0c;或是测试 maven下载 Maven – Download Apache Maven apache下的开源项目&#xff0c…