【PA交易】BackTrader: 讨论下分析器和评测指标

news2024/11/16 5:39:48

前言 

BackTrader的分析器主要使用的是analyzers模块,我们可以从Analyzers - Backtrader找到一个非常简单的示例。这个示例中使用方式很简单,其他分析器也可以通过如此简单封装方式进行装载。如果仅是复制粘贴官方教程,完全是制造互联网垃圾,更丝毫没必要写一篇博客来讨论。

但是,当我们关注微观时,我们的日线通常是通过Resample API(例如:多周期K线的Resampling)合并的,这时诸如PyFolio这样跟时序相关的分析器是否支持足够呢?同时,又有哪些框架内置的分析器?哪些分析器依赖于时序?哪些又需要哪些其他组件支持呢?如果我们定制Broker或者如前文所述基于Tick数据进行回测,那么应该如何使用框架提供的分析功能?

更进一步的,这些分析器是些个什么玩意?这些评测指标是什么?

本文将从这些问题出发,更包含了对一些框架提供的评测指标的文字解释和公式说明。阅读之前请参考官网示例实践几个分析器的挂载和使用。

Analyzer简述

要解答前面的问题,必不可少的是了解分析器内部的类关系,这是最简单但却重要的第一步。框架内部的内置分析器类层次结构如下所示:

而不同的分析器之间也存在相互依赖,比如PyFolio的结果则是另外三个分析器的汇总:

如下代码可以很简单的验证着点:

cerebro.addanalyzer(btanalyzers.Transactions, _name='mytran')
cerebro.addanalyzer(btanalyzers.PositionsValue, _name='mypos')
cerebro.addanalyzer(btanalyzers.GrossLeverage, _name='grosslv')
cerebro.addanalyzer(btanalyzers.PyFolio, _name='mypyfolio')

# ....

mytran = thestrat.analyzers.mytran.get_analysis()
series1 = ordered_dict_to_df('Transactions', mytran)
mypos = thestrat.analyzers.mypos.get_analysis()
series2 = ordered_dict_to_df('PositionsValue', mypos)
grosslv = thestrat.analyzers.grosslv.get_analysis()
series2 = ordered_dict_to_df('GrossLeverage', grosslv)
results = thestrat.analyzers.mypyfolio.get_analysis()
pyfolio_series = []
for key in results:
    series = ordered_dict_to_df(key, results[key])
    pyfolio_series.append(series)

如上代码使用Series对比:

分析器的next

上面的例子可以看到,多数分析器都会加入到策略的生命周期中,即使是直接继承自bt.Analyzer。以PositionsValue为例,在PositionsValue的实现中,分别会由框架调用start和next方法,如下调用堆栈:

start, positions.py:69
_start, analyzer.py:194
_start, strategy.py:397
runstrategies, cerebro.py:1269
run, cerebro.py:1132
<module>, MyAnalyzer.py:47

上述调用栈中,start, positions.py是PositionsValue分析器的实现,同样的也包括next方法实现。并且在方法中,调用了Broker的get_value和get_cash方法。而像杠杆率评测的GrossLeverage分析器则是直接在next方法中直接使用了data0的时间,而如果data0是tick级别考虑杠杆率这颗粒度显然太细了。

这对于本文开始的问题做出了一些解答:

  • 框架自身的一些基础分析器默认适配Tick级别数据的分析并不合适。
  • 分析器的很多实现需要调用Broker的接口方法。

虽然有一些计算器无法适配,但是前图中的bt.TimeFrameAnalyzerBase子类可以通过指定timeframe参数实现指定基于时间级别数据的分析。在TimeFrameAnalyzerBase的源码中可以看到:

class TimeFrameAnalyzerBase(with_metaclass(MetaTimeFrameAnalyzerBase,
                                           Analyzer)):
    params = (
        ('timeframe', None),
        ('compression', None),
        ('_doprenext', True),
    )

    def _start(self):
        # Override to add specific attributes
        self.timeframe = self.p.timeframe or self.data._timeframe

当然,一个成熟化的、准确的、产品级回测工具需要对这些分析指标进行充分的定制化的修改和拓展。这对于能够关注到这点的朋友来讲,从技术上解决起来是很容易的。本文不在过多赘述具体如何去定制化的细节实现。


分析器评测指标

为了方便实现上述的处于是配合定制化目的的修改和拓展,有必要结合BackTrader的实现,对于几个经典评测指标进行一些讨论。

AnnualReturn

标准的年化收益率,在回测结束的stop阶段计算。计算公式没有太特殊的地方:

分别基于期初净值和期末净值以及年数做出计算。当数据不足一年时,参数特化为:

框架中的代码页基本实现了类似的逻辑。

DrawDown

回撤是简单直白的风险度指标,在BT中返回在回测结束时最终的:

  • 距离最高点的回撤比例和资金回撤
  • 回测过程中的最大回撤

这个计算不复杂,即使完全自主实现也难度不大。

Calmar

卡玛比率为年化收益率与最大回撤的比值,主要为了突出风险度,同时也是一个很重要的评测指标。实际上Calmar将年化使用回撤进行了单位化。高Calmar意味着以回撤为单位的年化收益率。虽然通常的算法交易CTA在5以上都是很厉害的了,但是有些大牛高频量化系统将Calmar率控制在10以上并不少见。

BackTrader中Calmar主要使用了TimeDrawDown类。框架示例代码:“calmar-test.py”展示了使用方式。在框架源码实现中,calmar的计算实现于on_dt_over中,由上层的TimeFrameAnalyzerBase在next中调用,也就是每个数据源周期中都会发生计算(但是可以通过timeframe参数指定要计算的周期)。

SharpeRatio

标准的夏普率计算,框架的夏普率的计算依赖于AnnualReturn。夏普率几乎是公认的最常用评测指标,虽然他的争议较大。夏普率计算公式为:

夏普率计算中主要是标准差的计算稍微有些难以理解,其实在源码中可以看到BT的实现方式主要是对年华收益率计算:

math.sqrt(average(variance(self.AnnualReturn.rets, \
    average([r - rate for r in returns])), \
    bessel=self.p.stddev_sample))

其中贝塞尔方程可以通过参数指定(具体参考SharpeRatio - Backtrader)。除了贝塞尔以外,还要考虑配置若干参数,比如无风险利率、timeframe等。参数的不同配置可能会造成结果有较大出入,也容易产生争议(争论策略的夏普率之前最好双方Sync一下夏普率参数

关于BackTrader夏普率的讨论和介绍在CSDN有大量专题讨论,此处不再过多赘述。

GrossLeverage

当我们讨论回测的时候,毛杠杆率主要目的还是体现资金的利用率。“Gross Leverage”的原始定义为:

从源码中可以看到GrossLeverage的实现相对简单。即:

lev = (self._value - self._cash) / self._value

不过需要注意的是,杠杆率的计算是逐数据帧的,并且没有提供timeframe参数,如果想要考虑这个指标可能需要有一个最终汇总操作,给策略一个整体的杠杆率评价。否则如果在微观中逐tick的评价意义不大,并且观测难度也很大(可能画图是个办法)。

几点结论

对于前言中的一些问题:

  • 诸如PyFolio这样跟时序相关的分析器是否支持足够呢?
  • 如果我们定制Broker或者如前文所述基于Tick数据进行回测,那么应该如何使用框架提供的分析功能?

继承自TimeFrameAnalyzerBase的分析器可以支持指定timeframe,但是如果考虑定制化和细颗粒度,以及从性能优化角度,特别是针对tick源数据,这些基于timeframe的分析器尚显不足。

  • 又有哪些框架内置的分析器?哪些分析器依赖于时序?

我们列出了分析器的完整框架,同时可以看出哪些分析器支持timeframe。如果这些内置分析器,则可以根据自己回测评测的需求去定制对应的分析器。

  • 哪些又需要哪些其他组件支持呢?

首先分析器多数需要Broker支持。Broker提供了标准接口,如果是自定义Broker,实现对应接口即可。同时分析器互相之间存在大量依赖,例如文中提到过得Calmar对TimerDrawDown和AnnualReturn的依赖,以及类似于前面提到的PyFolio就是对几个分析器的汇总。

  • 这些分析器是些个什么玩意?这些评测指标是什么?

本文第二部分介绍了一些常用的评测指标是什么。处于篇幅原因,没有过度展开。实际上不少指标如果微调一些参数会有很大出入。所以如果是自己的回测系统大可以根据自己需要去定制,不必过分追求指标好看。除非为了忽悠资金或者抬杠,否则纠结这些指标意义很小。

最后,愿点赞的朋友早日打造出Calmar大于20甚至50的策略。

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

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

相关文章

qt开发-14_QListwidget 仿qq好友列表制作

QListWidget 继承 QListView。QListWidget 类提供了一个基于项的列表小部件。QListWidg et 是一个便捷的类&#xff0c;它提供了一个类似于 QListView&#xff08;下一小节将讲到&#xff09;提供的列表视图&#xff0c;但 是提供了一个用于添加和删除项目的基于项目的经典接口…

Pycharm执行打印console中print数据打印显示不全的解决办法?

#设置显示窗口数据显示完整 pd.set_option(display.max_rows, 500) pd.set_option(display.max_columns, 100) pd.set_option(display.width, 1000)

API-事件类型

学习目标&#xff1a; 掌握事件类型 学习内容&#xff1a; 事件类型鼠标事件焦点事件键盘事件文本事件focus选择器案例 事件类型&#xff1a; 鼠标事件&#xff1a; <title>事件类型-鼠标事件</title><style>div {width: 200px;height: 200px;background-c…

three.js - 置换贴图(displacementMap)、凹凸贴图(bumpMap)、法线贴图(normalMap)

这就是个灰度图 瞅瞅下面的贴图们&#xff0c;加深一下印象吧 说一下灰度图 在灰度图中&#xff0c; 黑色&#xff1a;代表最低的深度&#xff08;或最低的置换&#xff09; 白色&#xff1a;代表最高的深度&#xff08;或最高的置换&#xff09; 中间的灰度值&#xff0c;则…

链在一起联机存档同步教程 教你如何学会链在一起联机同存档

双人成行&#xff0c;四人更行了&#xff0c;说的就是新游戏链在一起&#xff0c;多人合作冒险游戏&#xff0c;一个是和兄弟四人一起玩的游戏&#xff0c;游戏中四个人被铁链绑在一起&#xff0c;大型节目之好兄弟到底谁是脑瘫正在上演&#xff0c;甚至有些玩家感觉链子牵的不…

SAP消息号 VF028

客户在VF11冲销发票之后&#xff0c;没有生成正式的财务凭证&#xff0c;然后VF02的时候出现如下报错&#xff1a; “自动清算出具发票凭证XXXXXXX&#xff08;被冲销凭证号&#xff09;且不可能取消凭证XXXXXXX&#xff08;冲销凭证号&#xff09; 原因&#xff1a;销售订单2…

归并排序和计数排序

目录 1.归并排序1.1递归1.1基本思想1.2算法描述1.3画图解释1.4代码实现 1.2非递归 2.计数排序2.1基本思想2.2算法描述3.画图解释 1.归并排序 1.1递归 1.1基本思想 归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法&#xff08;Divide and Conquer&#xf…

毫米波移动通信系统中的波束赋形—基于AOD估计的波束赋形

基于AOD估计的波束赋形依据压缩感知理论&#xff0c;利用毫米波信道的稀疏特性[18][19]&#xff0c;提出对信号的AOA和AOD进行估计&#xff0c;根据估计方向进行波束赋形。由于毫米波信道的稀疏特性&#xff0c;假设有L条多径分量时&#xff0c;公式1中的信道矩阵H可以表示为下…

软件质量保证与测试

目录 一、测试流程 二、测试用例 2.1概念 2.2用例编写格式 三、设计测试点 3.1等价类 3.1.1概念 3.1.2案例 3.1.3适用场景 3.1.4执行用例 3.2边界值 3.2.1概念 3.2.2案例 3.2.3使用场景 3.3判定表 3.3.1判定表使用原因 3.3.2概念 3.3.3案例 3.3.4使用场景 …

宏定义__FILE__,__LINE__,__VA_ARGS__等介绍与应用

ANSIC标准定义中常见的预定义宏 __LINE__&#xff1a;在源代码中插入当前源代码行号&#xff1b; __FILE__&#xff1a;在源代码中插入当前源代码路径及文件名&#xff1b; __DATE__&#xff1a;在源代码中插入当前编译日期&#xff1b; __TIME__&#xff1a;在源代码中插入…

全域运营系统是如何做好全平台运营?

当前&#xff0c;全域运营的热度持续上涨&#xff0c;多篇分析全域运营平台优缺点的帖子也在多个创业者交流群中风靡一时。综合来看&#xff0c;在众多的全域运营平台中&#xff0c;属后面我们说的这家全域运营平台的分析最为详尽。 其中&#xff0c;对于我们的全域运营平台的优…

Diffusion Mamba:用于CT到MRI转换的Mamba扩散模型

Diffusion Mamba&#xff1a;用于CT到MRI转换的Mamba扩散模型 提出背景拆解左侧&#xff1a;整体框架中间&#xff1a;Mamba块的细节右侧&#xff1a;螺旋扫描的细节 提出背景 论文&#xff1a;https://arxiv.org/pdf/2406.15910 代码&#xff1a;https://github.com/wongzbb…

macOS Sequoia 15 beta 2 (24A5279h) Boot ISO 原版可引导镜像下载 (iPhone Mirroring 现已支持)

macOS Sequoia 15 beta 2 (24A5279h) Boot ISO 原版可引导镜像下载 (iPhone Mirroring 现已支持) iPhone 镜像、Safari 浏览器重大更新、备受瞩目的游戏和 Apple Intelligence 等众多全新功能令 Mac 使用体验再升级 请访问原文链接&#xff1a;https://sysin.org/blog/macOS-…

有没有品质高的开放式蓝牙耳机推荐,这几款开放式耳机非常值得

随着科技的发展&#xff0c;越来越多的人选择开放式蓝牙耳机&#xff0c;对比传统的耳机&#xff0c;开放式蓝牙耳机可以提供更加自然的听觉体验&#xff0c;减少外部环境隔绝感&#xff0c;增强安全性&#xff0c;透气设计舒适度更高&#xff0c;也更加的干净卫生。深受运动爱…

如何挑选护眼灯?一分钟带你了解挑选护眼灯的六大准则!

小时候&#xff0c;对正确用眼知识一无所知&#xff0c;也不明白何种光线环境对眼睛最为友善&#xff0c;结果如今的近视度数已濒临千度大关。虽然早已习惯佩戴眼镜的生活&#xff0c;但近视所带来的诸多不便仍旧在日常生活中无处不在。因此&#xff0c;对于家中孩子的视力健康…

echarts+vue2实战(二)

目录 一、WebSocket【双向通信】的使用 1.1、前端 1.2、后端 二、前端组件的合并与优化 三、全屏切换 3.1、单页面切换 3.2、同页面多端联动 四、主题切换 4.1、单页面切换 4.2、同页面多端联动 一、WebSocket【双向通信】的使用 1.1、前端 在utils文件夹里创建soc…

【漏洞复现】华测监测预警系统——SQL注入漏洞

声明&#xff1a;本文档或演示材料仅供教育和教学目的使用&#xff0c;任何个人或组织使用本文档中的信息进行非法活动&#xff0c;均与本文档的作者或发布者无关。 文章目录 漏洞描述漏洞复现测试工具 漏洞描述 华测监测预警系统2.2版本存在sql注入&#xff0c;UserEdit接口S…

用构造函数为对象的数据成员实现输入和输出时间

在C程序中&#xff0c;对象的初始化是一个不可缺少的重要问题。不应该让程序员在这个问题上花过多的精力&#xff0c;C在类的设计中提供了较好的处理方法。 为了解决这个问题&#xff0c;C提供了构造函数&#xff08;constructor&#xff09;来处理对象的初始化。构造函…

【前端】HTML+CSS复习记录【1】

文章目录 前言一、p、br&#xff08;段落、换行&#xff09;二、短语标签&#xff08;用来呈现为被强调的文本&#xff09;三、sub、sup&#xff08;下标、上标&#xff09;四、b&#xff08;加粗文本&#xff09;五、块级元素与行内元素六、元素嵌套七、html注释系列文章目录 …

axios全局封装AbortController取消重复请求

为什么&#xff1f; 问题&#xff1a;为什么axios要配置AbortController&#xff1f;防抖节流不行吗&#xff1f; 分析&#xff1a; 防抖节流本质上是用延时器来操作请求的。防抖是判断延时器是否存在&#xff0c;如果存在&#xff0c;清除延时器&#xff0c;重新开启一个延…