Backtrader 文档学习- Analyzers

Backtrader 文档学习- Analyzers

1.概述

无论是回测还是交易,分析交易系统表现的关键,不仅是否仅获得利润,还是以高风险获得利润,或者与参考资产(或无风险资产)相比是否更值得努力。
这就是Analyzer对象系列的作用:提供对发生的情况或实际发生的情况分析。

2.分析器的特点

接口的模型是基于Lines对象的,例如具有next方法,但有一个主要区别:

  • Analyzers 不包括Line。
    意味着它们在内存方面开销不大,因为即使在分析了数千个价格bar之后,它们在内存中只保留一个结果。

3.系统中的定位

Analyzer分析器对象(如策略、观察者和数据)通过cerebro实例添加到系统中:
addanalyzer(ancls, *args, **kwargs)
但是,当在cerebro.run 期间进行操作时,对于系统中存在的每个策略,将发生以下情况:

  • 在cerebro.run 期间使用参数*args 和**kwargs 实例化ancls
  • ancls 实例将结合到策略

意味着:

  • 例如:如果回测运行包含3个策略,则将创建ancls 的3个实例,并且每个实例都将附加到不同的策略。策略与分析器一一对应。

底线原则:分析器分析单个策略的表现,而不是整个系统的表现

4.附属分析器

某些Analyzer 对象实际上可能使用其他分析器来完成其工作。例如: SharpeRatio 使用TimeReturn 的输出进行计算。
这些sub-analyzers子分析器或slave-analyzers从属分析器也将加入到与创建它们的分析器相同的策略中。但它们对用户完全不可见。

5.属性

为了执行预期的工作, Analyzer 对象提供了默认属性,这些属性会自动传递并在实例设置易于使用:

  • self.strategy :对analyzer对象在其中运行的策略子类的引用。分析器也可以访问策略可以访问的任何内容 。
  • self.datas[x] :策略中所使用数据源数组。虽然可以通过策略引用访问它,但是快捷方式使工作更加舒适。
  • self.data :指向self.datas[0] 的快捷方式,更加便捷。
  • self.dataX :快捷方式到不同的self.datas[x]
    还提供了一些其他别名,尽管它们可能过度简化:
 `self.dataX_Y` where X is a reference to `self.datas[X]` and `Y`
  refers to the line, finally pointing to: `self.datas[X].lines[Y]`

等价于:

self.dataX_Y = self.datas[X].lines[Y]

如果Lines具有名称,则还可用以下内容:

 `self.dataX_Name` which resolves to `self.datas[X].Name` returning
  the line by name rather than by index

等价于:

self.dataX_Name = self.datas[X].Name

对于第一个数据,前两个快捷方式可用,而不需要初始的X 数字引用。例如:

 `self.data_2` refers to `self.datas[0].lines[2]`

等价于:

self.data_2 = self.datas[0].lines[2]

 `self.data_close` refers to `self.datas[0].close`

等价于:

self.data_close = self.datas[0].close

6.返回分析

Analyzer 基类创建了一个self.rets (类型为collections.OrderedDict )成员属性,做返回分析的返回值。在方法create_analysis 中完成的,如果创建自定义分析器,则可以由子类覆盖。

7.操作模块

虽然Analyzer 对象不是Lines 对象,因此不会迭代Lines,但被设计为遵循相同的操作模式。(与处理Lines一样的操作模式)

  • 1.在系统启动之前实例化(因此调用__init__ )
  • 2.从start() 发出操作开始的信号
  • 3.在指标工作的最小周期之后,将调用prenext/ nextstart/ next 。
    prenext 和nextstart 的默认行为是触发next,因为分析器从系统存活的第一刻开始分析。
    在Lines 对象中调用len(self) 以检查实际的bar数。也适用于Analyzers ,通过返回self.strategy 的值来实现。
  • 4.通过notify_order 和notify_trade 通知订单和交易,就像策略一样。
  • 5.现金和价值也将像策略一样通过notify_cashvalue 方法通知
  • 6.现金、价值和基金价值和基金份额也将被通知,通过notify_fund方法使用策略一样
  • 7.stop 将被调用以表示操作的结束

完成常规操作周期后,分析器的附加方法提取/输出信息 。

  • get_analysis :理想情况下(不强制),返回包含分析结果的dict 类似对象。
  • print 使用标准的backtrader.WriterFile (除非被重写),从get_analysis 中写入分析结果。
  • pprint (美化打印)使用Python pprint 模块打印get_analysis 结果。

最后:

  • get_analysis 创建一个成员属性self.ret (类型为collections.OrderedDict ),分析器将分析结果写入其中。
    Analyzer的子类可以重写此方法以更改此行为 。

8.分析模式

在backtrader 平台上Analyzer对象有2种不同分析模式:

  • 1.通过在notify_xxx 和next 方法中收集信息,在next 中执行分析的当前信息
    例如, TradeAnalyzer 仅使用notify_trade 方法生成统计信息。
  • 2.收集(或不收集)上述信息,最后在stop 方法中一次性生成分析
    SQN (系统质量数字)在notify_trade 期间收集交易信息,但在stop 方法中生成统计信息。

9.简单示例

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

import backtrader as bt
import backtrader.analyzers as btanalyzers
import backtrader.feeds as btfeeds
import backtrader.strategies as btstrats

cerebro = bt.Cerebro()

# data
dataname = './datas/2005-2006-day-001.txt'
data = btfeeds.BacktraderCSVData(dataname=dataname)

cerebro.adddata(data)

# strategy
cerebro.addstrategy(btstrats.SMA_CrossOver)

# Analyzer
cerebro.addanalyzer(btanalyzers.SharpeRatio, _name='mysharpe')

thestrats = cerebro.run()
thestrat = thestrats[0]

print('Sharpe Ratio:', thestrat.analyzers.mysharpe.get_analysis())

计算夏普比率,执行结果:

 Sharpe Ratio: OrderedDict([('sharperatio', 11.647332609673251)])

没有绘图,因为夏普比率在计算结束时是一个的值。

10.分析器的详解

让我们重复说明一下Analyzers 不是Lines对象,但为了无缝地将它们集成到backtrader 生态系统中,遵循几个Lines对象的内部API约定(实际上是它们融合的)

注意: SharpeRatio 的代码已经发展到考虑年化收益等因素,本版本只是一个参考计算。
请检查:doc: …/analyzers-reference

此外,还有一个SharpeRatio_A ,它以年化形式直接提供值,而不考虑所查询的时间范围
作为基础的SharpeRatio 的代码(简化版本)

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

import operator

from backtrader.utils.py3 import map
from backtrader import Analyzer, TimeFrame
from backtrader.mathsupport import average, standarddev
from backtrader.analyzers import AnnualReturn


class SharpeRatio(Analyzer):
    params = (('timeframe', TimeFrame.Years), ('riskfreerate', 0.01),)

    def __init__(self):
        super(SharpeRatio, self).__init__()
        self.anret = AnnualReturn()

    def start(self):
        # Not needed ... but could be used
        pass

    def next(self):
        # Not needed ... but could be used
        pass

    def stop(self):
        retfree = [self.p.riskfreerate] * len(self.anret.rets)
        retavg = average(list(map(operator.sub, self.anret.rets, retfree)))
        retdev = standarddev(self.anret.rets)

        self.ratio = retavg / retdev

    def get_analysis(self):
        return dict(sharperatio=self.ratio)

代码可以分解为:

  • params 声明,虽然声明的参数没有使用(作为示例),但是Analyzers像backtrader 中的大多数其他对象一样支持参数

  • init 方法,就像Strategies在__init__ 中声明Indicators一样,分析器也使用支持对象。
    在这种情况下:使用年度回报率计算SharpeRatio 。计算将是自动的,并且将可用于SharpeRatio 自行进行计算。
    注意:实际的SharpeRatio 实现使用更通用和后开发的TimeReturn 分析器

  • next 方法,SharpeRatio 不需要它,但是在每次调用父策略next 后将调用此方法

  • start 方法,在回测开始之前调用。可用于额外的初始化任务。Sharperatio不需要它

  • stop 方法,在回测结束后立即调用。像SharpeRatio效果,可以用来完成/进行计算

  • get_analysis 方法,返回一个dict类型,外部调用方对生成的分析的访问, 返回:带有分析结果的字典。

11.参考

class backtrader.Analyzer()
分析器基类。所有分析器都是分析器的子类
分析器实例在策略的框架中运行,并为该策略提供分析。
属性:

  • self.strategy (提供可访问的策略,策略中任何可访问的内容)

  • self.datas[x] 系统加载的数据源,当前策略所使用的数据源

  • self.data 系统加载的默认数据源,self.datas[0]

  • self.dataX -> self.datas[X]

  • self.dataX_Y -> self.datas[X].lines[Y]

  • self.dataX_name -> self.datas[X].name

  • self.data_name -> self.datas[0].name

  • self.data_Y -> self.datas[0].lines[Y]
    虽然分析器不是一个Lines对象,但是方法和操作遵循相同的设计

  • init 在实例化初始化阶段设置

  • start / stop 发出开始和结束的信号

  • prenext / nextstart / next 遵循对策略中相同方法的调用的一系列方法

  • notify_trade / notify_order / notify_cashvalue / notify_fund 以上方法收到通知与该策略的等效方法相同

操作模式是开放的,没有首选模式。因此可以在next调用时,stop操作结束时生成分析,甚至可以使用和策略一样的notify_trade方法
重要的是重写get_analysis方法,返回包含分析结果的类似dict的对象(实际格式取决于实际重新的内容)

上述与Strategy一样的方法就不赘述。

方法:

  • get_analysis()
    返回一个类似dict的对象和分析结果
    字典中分析结果的关键字和格式取决于重写程序。
    甚至没有强制要求结果是类似dict的对象,只是习惯约定
    默认实现返回由默认create_analysis方法创建的orderedDict rets返回值。

  • create_analysis()
    被子类重写,提供了创建保存分析架构信息。
    默认行为是创建一个OrderedDict类型的rets变量。

  • print(*args, **kwargs)
    通过标准Writerfile对象打印get_analysis返回的结果,默认情况下将内容写入标准输出

  • pprint(*args, **kwargs)
    使用美化打印Python模块(pprint)打印get_analysis返回的结果

  • len()
    通过实际返回分析器操作的策略的当前长度,支持调用分析器上的len 。

你可能感兴趣的:(BackTrader,数据分析,服务器,量化,BackTrader)