Skip to content

分析者

原文: https://www.backtrader.com/docu/analyzers/analyzers/

无论是回溯测试还是交易,能够分析交易系统的性能对于理解是否不仅实现了利润,而且实现利润的风险是否太大,或者与参考资产(或无风险资产)相比是否真的值得付出努力至关重要

这就是Analyzer对象家族的用武之地:提供对发生了什么甚至实际发生了什么的分析。

分析仪的性质

该接口以对象的接口建模,特征为next方法,但有一个主要区别:

  • Analyzers请勿持线。

    这意味着它们在内存方面并不昂贵,因为即使在分析了数千个价格条之后,它们也可能仅仅在内存中保存一个结果。

生态系统中的位置

Analyzer对象是通过cerebro实例添加到系统中的策略观察者数据

  • addanalyzer(ancls, *args, **kwargs)

但是当在cerebro.run期间操作时,系统中存在的每个策略都会发生以下情况

  • cerebro.run期间ancls将被*args**kwargs实例化

  • ancls实例将附加到策略

这意味着:

  • 如果回溯测试运行包含例如3 个策略,则将创建ancls3 个实例,并且每个实例将附加到不同的策略。

底线:分析人员分析单个策略的性能,而不是整个系统的性能

附加位置

一些Analyzer对象实际上可能使用其他分析仪来完成其工作。例如:SharpeRatio使用TimeReturn的输出进行计算。

这些子分析器从属分析器也将插入到创建它们的策略中。但是用户完全看不见它们。

属性

为了执行预期的工作,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_Name` which resolves to `self.datas[X].Name` returning
  the line by name rather than by index 

对于第一个数据,最后两个快捷键不带初始X数字参考。例如:

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

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

返回分析

分析器基类创建self.rets(类型为collections.OrderedDict的)成员属性以返回分析。这是在方法create_analysis中完成的,如果创建自定义分析器,该方法可以被子类覆盖。

作案手法

尽管Analyzer对象不是对象,因此不会在行上迭代,但它们被设计为遵循相同的操作模式。

  1. 系统启动前实例化(因此调用__init__

  2. start表示开始操作

  3. 在计算出指标工作的策略的最短期限后,将调用prenext/nextstart/next

    prenextnextstart的默认行为是调用 next,因为分析仪可能从系统激活的第一刻就开始分析。

    通常在对象中调用len(self)来检查实际的条数。通过返回self.strategy的值,这也适用于Analyzers

  4. 订单和交易将通过notify_ordernotify_trade通知给策略

  5. 现金和价值也将被通知,就像在notify_cashvalue方法中使用策略一样

  6. 现金、价值和基金价值以及基金份额也将收到通知,就像在notify_fund方法中使用策略一样

  7. 将调用stop以发出操作结束的信号

一旦常规操作循环完成,分析仪具有提取/输出信息的附加方法

  • get_analysis:理想情况下(不强制)返回包含分析结果的类似dict的对象。

  • print使用标准backtrader.WriterFile(除非重写)写入get_analysis的分析结果。

  • pprintpretty print)使用 Pythonpprint模块打印get_analysis结果。

最后:

  • get_analysis创建一个成员属性self.ret(类型为collections.OrderedDict),分析器将分析结果写入该属性。

    Analyzer的子类可以重写此方法来更改此行为

分析器模式

backtrader平台中分析仪对象的开发揭示了生成分析的两种不同使用模式:

  1. 在执行过程中,通过在notify_xxxnext方法中收集信息,并在next中生成分析的当前信息

    例如,TradeAnalyzer只使用notify_trade方法生成统计数据。

  2. 收集(或不收集)上述信息,但在stop方法中一次生成分析

    SQN系统质量编号)在notify_trade期间收集交易信息,但在stop期间生成统计信息

一个简单的例子

尽可能简单:

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

执行(已存储在analyzer-test.py中:

$ ./analyzer-test.py
Sharpe Ratio: {'sharperatio': 11.647332609673256} 

没有绘图,因为SharpeRatio是计算结束时的单个值。

分析仪的法医学分析

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

笔记

SharpeRatio的代码已经演变为考虑年度化,此处的版本仅作为参考。

请检查分析仪参考

另外还有一个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声明

    尽管未使用声明的对象(作为示例),分析器backtrader中的大多数其他对象一样支持参数

  • __init__方法

    就像__init__中的策略声明指标一样,使用支持对象的分析器也是如此。

    在这种情况下,SharpeRatio是使用年收益率计算的。该计算将自动进行,并可供SharpeRatio自行计算。

    笔记

    SharpeRatio的实际实现使用了更通用、更晚开发的TimeReturn分析仪

  • next方法

    SharpeRatio不需要,但每次调用父策略next后都会调用此方法

  • start方法

    在回溯测试开始之前调用。可以用于额外的初始化任务。夏佩拉蒂奥不需要它

  • stop方法

    在回溯测试结束后立即调用。与SharpeRatio一样,可用于完成/进行计算

  • get_analysis方法(返回字典)

    外部调用方对生成的分析的访问权限

    返回:包含分析的字典。

参考

类 backtrader.Analyzer()

分析器基类。所有分析器都是这个分析器的子类

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]

这不是对象,但方法和操作遵循相同的设计

  • __init__在实例化和初始设置期间

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

  • prenext/nextstart/next方法家族,遵循对策略中相同方法的调用

  • notify_trade/notify_order/notify_cashvalue/notify_fund接收与策略等效方法相同的通知

操作模式为开放式,且无首选模式。因此,可以使用next调用、在stop期间的操作结束时生成分析,甚至可以使用notify_trade这样的单一方法生成分析

重要的是重写get_analysis以返回包含分析结果的类似dict 的对象(实际格式取决于实现)

开始()

调用以指示操作的开始,为分析器提供设置所需内容的时间

停止()

调用以指示操作的结束,为分析器提供关闭所需内容的时间

prenext()

在达到策略的最短期限之前,为策略的每次 prenext 调用调用调用

分析器的默认行为是调用next

nextstart()

在首次达到最短时间段时,为策略的下一次启动调用仅调用一次

下一个()

一旦达到策略的分钟周期,为策略的下一次调用调用调用

通知现金价值(现金、价值)

在每个下一个周期之前接收现金/价值通知

通知基金(现金、价值、基金价值、股份)

接收当前现金、价值、基金价值和基金份额

通知订单(订单)

在每个下一个周期之前接收订单通知

通知贸易部(贸易部)

在每个下一个周期之前接收交易通知

get_ 分析()

返回一个具有分析结果的类似dict 的对象

字典中分析结果的键和格式取决于实现。

甚至没有强制要求结果是一个类似dict 的对象,只是约定

默认实现返回默认create_analysis方法创建的默认 OrderedDictrets

创建 _ 分析()

意味着被子类覆盖。提供创建用于保存分析的结构的机会。

默认行为是创建一个名为retsOrderedDict

打印(args,*kwargs)

通过标准Writerfile对象打印get_analysis返回的结果,该对象默认为将内容写入标准输出

pprint(args,*kwargs)

使用 pretty print Python 模块(pprint打印get_analysis返回的结果)

len()

支持通过实际返回分析仪操作策略的当前长度,在分析仪上调用len


我们一直在努力

apachecn/AiLearning

【布客】中文翻译组