量化交易backtrader实践(四)_评价统计篇(1)_内置评价

背景

通过对基础的学习和不断深入的实践,当我们已经能够制作出快速获取数据,以及制作出多个股票 乘上多种策略进行回测的部分的时候,我们就会明显发现数据有点多了,比如10支股票都用了3种策略就得到30段数据,一页显示不下,眼睛看不过来,也不知道怎么对比策略哪个好。所以这个时候我们就需要添加评价指标。

我们可以先看一下可能大家比较熟悉的对于基金进行PK时所展现的一些内容:

首先是业绩表现,即不同阶段的涨跌幅,能在一张图上画不同基金的线以看到它们之间的差别

  • 近一周
  • 近一月
  • 近半年
  • 近1年
  • 今年来 等

然后有风险数据对比,包括

  • 波动率
  • 夏普比率
  • 最大回撤
  • 收益回撤比等

以上,就可以生成基本的对比和评价,我们也可以通过这个对于评价指标有一个简单的印象。后续我们再对评价指标的原理和定义进行细致的学习,我先把一些参考的资源列在这里

  • Backtrader快速入门——2. 策略表现评估_backtrader 最大回撤-CSDN博客

股票软件评测系统

大部分的商用的股票及交易软件都会有类似交易评测系统的功能。在这个评测系统中,会有几个页面,包括

  • 评测公式的选择(以MACD交易系统为例),
  • 建仓规则(时间段和资金),
  • 交易方式(手续费,多头/空头价,滑点),
  • 平仓规则(止损,止盈,目标周期平仓),
  • 评测品种(选择哪些股票)

在进行评测后,会出具报告,一些评价指标就会列举出来,比如 盈利数,胜率,净利润,收益率,最大回撤等,还有一些细节的数据例如平均盈利,盈亏比,连涨次数......

其实,大多数时候,大多数人只关心胜率和收益率,连回撤都懒得看,盈亏比也并不关心。对于单支或几支股票在单策略上的回测的确可以这样,注意力可能直接放在K线图上,这里买,那里应该卖,策略是否可以优化等。但如果股票数量很多,策略也很多,某些股票走势反常,有些股票就不适应某些策略等,那就需要得到更简洁、有效的评价指标,通过对这些评价进行分析处理(例如排序,加权计算等)来筛选出合适的股票以及合适的应用策略甚至合适的时机。

Backtrader内置评价

有哪些内置评价

我们已经看到了基金PK有模板式的评价指标,股票软件评价也有模板式的评价指标,那么我们在backtrader中也是有内置的评价指标的。

我们可以通过在spyder或其他IDE中按Ctrl+左键点击进入相关.py文件

# CTRL + 点击bt.analyzers的analyzers
cerebro.addanalyzer(bt.analyzers.TimeReturn, _name='pnl')# 跳到 \site-packages\backtrader\analyzers\__init__.py###############################################################################
from __future__ import (absolute_import, division, print_function,unicode_literals)# The modules below should/must define __all__ with the objects wishes
# or prepend an "_" (underscore) to private classes/variablesfrom .annualreturn import *
from .drawdown import *
from .timereturn import *
from .sharpe import *
from .tradeanalyzer import *
from .sqn import *
from .leverage import *
from .positions import *
from .transactions import *
from .pyfolio import *
from .returns import *
from .vwr import *from .logreturnsrolling import *from .calmar import *
from .periodstats import *

我们现在有AI助手了,直接把这些代码扔给AI,它就返回一个清楚的解释

您提供的代码片段看起来像是一个Python模块的导入语句,其中包含了多个与金融分析和交易策略相关的库。这些库涉及多种金融指标和分析工具,如年化收益率、最大回撤、时间收益率、夏普比率、交易分析、系统质量数(SQN)、杠杆率、持仓分析、交易记录分析、Pyfolio(一个金融分析库)、收益率分析、变异权重回报(VWR)和卡马尔比率等。

这些库和模块通常用于量化交易策略的开发和评估。例如:

  • annualreturn: 用于计算年化收益率。
  • drawdown: 用于计算最大回撤。
  • timereturn: 用于计算时间收益率。
  • sharpe: 用于计算夏普比率。
  • tradeanalyzer: 用于分析交易策略的表现。
  • sqn: 用于计算系统质量数。
  • leverage: 用于计算杠杆率。
  • positions: 用于分析持仓情况。
  • transactions: 用于分析交易记录。
  • pyfolio: 用于金融分析和投资组合优化。
  • returns: 用于分析收益率。
  • vwr: 用于计算变异权重回报。
  • logreturnsrolling: 用于计算对数收益率的滚动统计。
  • calmar: 用于计算卡马尔比率。
  • periodstats: 用于计算特定时间周期的统计数据。

这些工具和库可以帮助投资者评估策略的表现,识别潜在的风险,并进行有效的策略优化。

了解了这个评价指标大概的信息后,我们要一步一步实践,看看这些评价指标具体是什么,哪些需要用,哪些看不懂,哪些不能用。

内置评价实践

00_评价程序

首先,Analyzer在哪里添加;然后,结果在哪里输出。

# 创建和配置Cerebro引擎
cerebro = Cerebro()# 添加策略和分析器
cerebro.addstrategy(MyStrategy)
cerebro.addanalyzer(xxxxx)# 运行回测
results = cerebro.run()# 获取分析结果
strat = results[0]
analysis = strat.analyzers.xxxx.get_analysis()

由于我们有15个评价指标要实践,而我又不希望每次都把上面的部分重写一遍,所以做了一个函数来简化我们的工作量,这里的df_list是自选股列表,run_strategy是策略,i是自选股列表中的第i支股票,sdate1,sdate2分别是起始日期和结束日期,然后禁止了绘图,且不输出交易的log,防止它们占用屏幕空间,这样把焦点都只放到评价指标的输出上来。

def run_main_analyser1 (df_list,run_strategy,i, sdate1,sdate2, myplot=False, logoff=1): iSel = icode_ = df_list.iloc[iSel,0]df1 = get_bt_feed_data(code_)sdate = sdate1edate = sdate2cerebro = bt.Cerebro()cerebro = bt.Cerebro(stdstats=False)    cerebro.addobserver(bt.observers.Broker)cerebro.addobserver(my_Trades)cerebro.addobserver(my_BuySell)cerebro.addobserver(bt.observers.DrawDown)add_analyzer_all(cerebro)                # 加入---------analyzer -------------cerebro.addstrategy(run_strategy, log_off= logoff)         data = bt.feeds.PandasData(dataname=df1, fromdate=sdate, todate=edate) cerebro.adddata(data, name=code_)   cerebro.broker.setcash(100000.0)    mycomm = StockCommission(commission=0.0002)  cerebro.broker.addcommissioninfo(mycomm)     cerebro.addsizer(bt.sizers.PercentSizer,percents=40) cerebro.broker.set_coc(True)        result = cerebro.run()     strat = result[0]analyzer_output(strat)                   # 输出--------analyzer -------------if logoff !=1:print('最终资产价值: %.2f' % cerebro.broker.getvalue()) # 打印最终结果if myplot:cerebro.plot(style='candle')

这样我们这个函数就不需要每次进行更改,只要更新与Analyzer相关的两个函数就可以了。

01_年化收益率-annualreturn

年化收益率就是字面上的意思,以自然年(例如2023,2024)计算其年化收益率。

def add_analyzer_all(cerebro):cerebro.addanalyzer(bt.analyzers.AnnualReturn, _name='_AnnualReturn') # 年化收益率def analyzer_output(result):print("--------------- AnnualReturn -----------------")sout = result.analyzers._AnnualReturn.get_analysis()print(sout)

接着我们在notebook中再运行一下,这句每次都要运行一遍,后面就偷懒省略了:

run_main_analyser1(df,St_MACD_class,3,d2,d1,myplot=False, logoff=1)

 如果myplot=True,就会在notebook中绘制图形

得到的结果如下:

策略为 经典MACD , 期末总资金 111569.09  盈利为 11569.09 总共交易次数为 11 ,交易成功率为 36.4%
--------------- AnnualReturn -----------------
OrderedDict([(2023, 0.167391800396119), (2024, -0.04428752311724082)])

这里得到的数据是OrderedDict()类型,我们可以使用几种不同的方式来处理它。

# 第一种方式  key,value处理
for key, value in sout.items():print(f'{key}: {value}')# 第二种方式 -- 使用pandas处理
series1 = pd.Series(sout))
print(series1)# 第三种方式 -- 转为dict再处理
dict1 = dict(sout)
print(dict1)-------------------------2023: 0.167391800396119       # 第一种
2024: -0.044287523117240822023    0.167392              # 第二种
2024   -0.044288
dtype: float64{2023: 0.167391800396119, 2024: -0.04428752311724082}  # 第三种

02_回撤-Drawdown

def add_analyzer_all(cerebro):cerebro.addanalyzer(bt.analyzers.DrawDown, _name='_DrawDown') # 回撤def analyzer_output(result):print("--------------- DrawDown -----------------")sout = result.analyzers._DrawDown.get_analysis()print(sout)

运行后得到结果为:

策略为 经典MACD , 期末总资金 111569.09  盈利为 11569.09 总共交易次数为 11 ,交易成功率为 36.4%
--------------- DrawDown -----------------
AutoOrderedDict([('len', 80), ('drawdown', 13.72833873324972), 
('moneydown', 17753.89797314338), 
('max', AutoOrderedDict([('len', 150), ('drawdown', 14.18411680845229), ('moneydown', 18343.32380264625)]))])

 很明显,这里的输出结果是个多重字典,我们直接用dict(sout)是得不到最终要的结果的,这里可以用pd.DataFrame(sout),但出来的表现形式并不是我们想要的。

于是,用了一个笨方法来进行输出,通过函数递归调用把每一层字典都遍历,先转成一个标准的字典类型,然后再按层级缩进进行打印输出:

from collections import OrderedDictdef convert_to_regular_dict(odict):if isinstance(odict, OrderedDict):return {k: convert_to_regular_dict(v) for k, v in odict.items()}else:return odictdef print_dict(d, indent=0):"""打印字典,按层级缩进。    """for key, value in d.items():print('  ' * indent + str(key) + ':', end=' ')if isinstance(value, dict):print()print_dict(value, indent + 1)else:print(value)

这样能得到结果:

len: 80
drawdown: 13.72833873324972
moneydown: 17753.89797314338
max: len: 150drawdown: 14.18411680845229moneydown: 18343.32380264625

 所以Drawdown得到的结果是2组,1是当前的回撤周期+回撤百分比+回撤金额;2是最大回撤的周期+回撤百分比+回撤金额,这些数据是我们最常用的评价指标之一。

03_timerun(时间序列收益 - 历史收益)

可以理解为基金信息中的历史收益,每天的收益率。这里偷懒直接用pandas.Series()处理得到Series类型的数据。

def add_analyzer_all(cerebro):cerebro.addanalyzer(bt.analyzers.TimeReturn, _name='_pnl') # 返回收益率时序数据def analyzer_output(result):print("--------------- pnl -----------------")sout = result.analyzers._pnl.get_analysis()
#     print(sout)s = pd.Series(result.analyzers._pnl.get_analysis()) print(s.tail(15))
策略为 经典MACD , 期末总资金 111569.09  盈利为 11569.09 总共交易次数为 11 ,交易成功率为 36.4%
--------------- pnl -----------------
2024-06-26    0.008373
2024-06-27   -0.007266
2024-06-28   -0.001046
2024-07-01    0.005233
2024-07-02    0.009371
2024-07-03    0.013410
2024-07-04   -0.022394
2024-07-05    0.002082
2024-07-08   -0.012469
2024-07-09    0.003156
2024-07-10   -0.012586
2024-07-11    0.019120
2024-07-12   -0.003127
2024-07-15   -0.008365
2024-07-16   -0.002109
dtype: float64

04_夏普比率-SharpRatio

夏普比率是描述股票或组合在单位风险下的所能获得超额收益的程度。它将一只标的或组合的风险归一化,便于更好的比较组合之间的有效性。数值越高代表考虑风险的情况下股票或组合表现越好。这里我们先不探讨它是怎么得到的,我们先实践内置评价看它的输出是什么。

从下面的结果看,这里输出是只有1项的字典,key是"sharperatio",value为数值 0.487

def add_analyzer_all(cerebro):cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='_SharpeRatio') # 夏普比率def analyzer_output(result):print("--------------- Sharp Ratio -----------------")sout = result.analyzers._SharpeRatio.get_analysis()print(sout)for key, value in sout.items():print(f'{key}: {value}')
策略为 经典MACD , 期末总资金 111569.09  盈利为 11569.09 总共交易次数为 11 ,交易成功率为 36.4%
--------------- Sharp Ratio -----------------
OrderedDict([('sharperatio', 0.4870776964306147)])
sharperatio: 0.4870776964306147

05_tradeanalyzer 交易分析 

def add_analyzer_all(cerebro):cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _name='_TradeAnalyzer')def analyzer_output(result):print("---------------_TradeAnalyzer -----------------")sout = result.analyzers._TradeAnalyzer.get_analysis()
#     print(sout)sdict = convert_to_regular_dict(sout)print_dict(sdict)

 在这里先说明一下交易分析的结构

total - 交易总次数/ open / closed次数

streak - 连胜/最高连胜次数 , 连败/最高连败次数

pnl - 毛利率(总,平均);净利率(总,平均)

won - 盈利(次数,总盈利,平均,最大盈利)

lost - 亏损(次数,总亏损,平均,最大亏损)

long - 买多 (次数,pnl, won, lost)   -- A股只能做多,所以long有数据

short- 买空 (次数,pnl, won, lost)  -- short没有数据,都是0

len - 各种情况的周期数(略)

---------------------------------------------------------------------

策略为 经典MACD , 期末总资金 111569.09  盈利为 11569.09 总共交易次数为 11 ,交易成功率为 36.4%
---------------_TradeAnalyzer -----------------
total: total: 11open: 1closed: 10
streak: won: current: 0longest: 1lost: current: 2longest: 2
pnl: gross: total: 15641.388419738887average: 1564.1388419738887net: total: 15232.749667811115average: 1523.2749667811115
won: total: 4pnl: total: 32567.260408578655average: 8141.815102144664max: 16320.18708936759
lost: total: 6pnl: total: -17334.51074076754average: -2889.0851234612564max: -7116.267063844403
long: total: 10pnl: total: 15232.749667811115average: 1523.2749667811115won: total: 32567.260408578655average: 8141.815102144664max: 16320.18708936759lost: total: -17334.51074076754average: -2889.0851234612564max: -7116.267063844403won: 4lost: 6
short: total: 0pnl: total: 0.0average: 0.0won: total: 0.0average: 0.0max: 0.0lost: total: 0.0average: 0.0max: 0.0won: 0lost: 0
len: total: 132average: 13.2max: 29min: 3won: total: 93average: 23.25max: 29min: 15lost: total: 39average: 6.5max: 11min: 3long: total: 132average: 13.2max: 29min: 3won: total: 93average: 23.25max: 29min: 15lost: total: 39average: 6.5max: 11min: 3short: total: 0average: 0.0max: 0min: 9223372036854775807won: total: 0average: 0.0max: 0min: 9223372036854775807lost: total: 0average: 0.0max: 0min: 9223372036854775807

06_SQN(System Quality Number)

SQN(System Quality Number)是一个由 Van Tharp 提出的评价指标,用于衡量交易系统的性能。<br>SQN 数值是基于交易结果的期望值、标准差和交易次数计算出来的。

  • SQN 值大于 1.6 表示交易系统可能具有正期望值。
  • SQN 值在 1.6 到 2.0 之间表示交易系统很好。
  • SQN 值在 2.0 到 2.5 之间表示交易系统非常好。
  • SQN 值大于 2.5 表示交易系统非常出色。

SQN的结果是有2个项的字典,分别是 'sqn' : 0.735 和 ’trades':10 

def add_analyzer_all(cerebro):cerebro.addanalyzer(bt.analyzers.SQN, _name='_SQN') def analyzer_output(result):print("---------------SQN -----------------")sout = result.analyzers._SQN.get_analysis()print(sout)print(f'SQN: {sout["sqn"]}, Trades: {sout["trades"]}')------------------------------
策略为 经典MACD , 期末总资金 111569.09  盈利为 11569.09 总共交易次数为 11 ,交易成功率为 36.4%
---------------SQN -----------------
AutoOrderedDict([('sqn', 0.7349808981765108), ('trades', 10)])
SQN: 0.7349808981765108, Trades: 10

 

 07_杠杆-leverage

毛杠杆率(Gross Leverage)的分析器,
输出的结果就是对应每个交易日,买了股票的那部分占净资产的比重,也可以简单理解为仓位;
这里我们用的是当前资金的40%左右(买100整数倍的股票会略有偏差),所以出来的数据基本上都是0.4上下,并且如果股票涨了,值会增加,跌了值会减小。

def add_analyzer_all(cerebro):cerebro.addanalyzer(bt.analyzers.GrossLeverage, _name='_leverage') def analyzer_output(result):print("---------------_leverage -----------------")sout = result.analyzers._leverage.get_analysis()
#     print(sout)
#     for dt, leverage in sout.items():
#         print(f'Datetime: {dt}, Gross Leverage: {leverage}')dfout = pd.Series(sout)print(dfout.iloc[40:60])
策略为 经典MACD , 期末总资金 111569.09  盈利为 11569.09 总共交易次数为 11 ,交易成功率为 36.4%
---------------_leverage -----------------
2023-03-15    0.000000
2023-03-16    0.000000
2023-03-17    0.000000
2023-03-20    0.000000
2023-03-21    0.000000
2023-03-22    0.000000
2023-03-23    0.401787
2023-03-24    0.396490
2023-03-27    0.397676
2023-03-28    0.397676
2023-03-29    0.395300
2023-03-30    0.403532
2023-03-31    0.407565
2023-04-03    0.401787
2023-04-04    0.395896
2023-04-06    0.388062
2023-04-07    0.000000
2023-04-10    0.000000
2023-04-11    0.000000
2023-04-12    0.000000
dtype: float64

08_ 持仓-positions

  • positionsValue 就是持仓的值
  • 一旦买入就有持仓,涨了则这个值会增大,跌了则这个值会减小
  • 这样看positions与上面的leverage其次是非常类似的,它们都是每日的数据记录,不是直接的打分评价
def add_analyzer_all(cerebro):cerebro.addanalyzer(bt.analyzers.PositionsValue, _name='_PositionsValue') def analyzer_output(result):print("---------------PositionsValue -----------------")sout = result.analyzers._PositionsValue.get_analysis()
#     print(sout)for dt, v in sout.items():print(f'Datetime: {dt}, Value: {v}')
策略为 经典MACD , 期末总资金 111569.09  盈利为 11569.09 总共交易次数为 11 ,交易成功率为 36.4%
---------------PositionsValue -----------------
Datetime: 2023-01-11, Value: [0.0]
Datetime: 2023-01-12, Value: [0.0]Datetime: 2023-03-21, Value: [0.0]
Datetime: 2023-03-22, Value: [0.0]
Datetime: 2023-03-23, Value: [40293.39853300734]
Datetime: 2023-03-24, Value: [39413.20293398534]
Datetime: 2023-03-27, Value: [39608.801955990224]
Datetime: 2023-03-28, Value: [39608.801955990224]
Datetime: 2023-03-29, Value: [39217.60391198044]
Datetime: 2023-03-30, Value: [40586.797066014675]
Datetime: 2023-03-31, Value: [41271.393643031784]
Datetime: 2023-04-03, Value: [40293.39853300734]
Datetime: 2023-04-04, Value: [39315.40342298288]
Datetime: 2023-04-06, Value: [38044.009779951106]
Datetime: 2023-04-07, Value: [0.0]
Datetime: 2023-04-10, Value: [0.0]
Datetime: 2023-04-11, Value: [0.0]

 09_交易记录-transaction

transaction在这里就表示交易的意思,它记录了每笔交易的数据。包括日期,金额,价格,sid是导入backtrader的股票的ID,symbol是股票代号,以及值。

我们的数据回测这里输出总共21条,从前面的tradeanalyzer可知 close的交易数为10,则有10对买和卖共20笔,open的1笔即还有一笔开仓但没卖,加起来总共21笔。

def add_analyzer_all(cerebro):cerebro.addanalyzer(bt.analyzers.Transactions, _name='_Transactions') def analyzer_output(result):print("---------------Transactions -----------------")sout = result.analyzers._Transactions.get_analysis()
#     print(sout)print(len(sout))for date, transactions in sout.items():print(f'Date: {date}')for x in transactions:print(x)print(f'  Amount: {x[0]}, Price: {x[1]}, Sid: {x[2]}, Symbol: {x[3]}, Value: {x[4]}')

 

策略为 经典MACD , 期末总资金 111569.09  盈利为 11569.09 总共交易次数为 11 ,交易成功率为 36.4%
---------------Transactions -----------------
21
Date: 2023-03-23 00:00:00
[9779.9511002445, 4.09, 0, '601086', -40000.0]Amount: 9779.9511002445, Price: 4.09, Sid: 0, Symbol: 601086, Value: -40000.0
Date: 2023-04-07 00:00:00
[-9779.9511002445, 3.89, 0, '601086', 38044.009779951106]Amount: -9779.9511002445, Price: 3.89, Sid: 0, Symbol: 601086, Value: 38044.009779951106
Date: 2023-05-04 00:00:00
[10454.333757131215, 3.75, 0, '601086', -39203.751589242056]Amount: 10454.333757131215, Price: 3.75, Sid: 0, Symbol: 601086, Value: -39203.751589242056

......

 

 10_金融投资组合分析库-pyfolio

我在学习和实践的过程中,看到很多关于pyfolio的文章,列了一些如下:

  • Backtrader快速入门——3. 使用pyfolio进行可视化分析-CSDN博客
  • backtrader:终于可以集成pyfolio了_qlib如何集成quantstats和pyfolio的-CSDN博客

从上面的文章,了解到一些信息

  • 本来,backtrader可以集成PyFolio这个第三方库,方便地以可视化方法输出这些指标。
  • 但是,由于PyFolio后来变更了接口,两者就没有集成了。
  • 好在,还有一个第三方库quantstats,可以非常方便地与backtrader集成。

不过这些提到的pyfolio应该是另外一个库,而并非我们这里的backtrader内置评价指标,我们后续再去研究pyfolio库和quantstats库的使用,当前先把内置指标输出看看它做了哪些工作。

打开\backtrader\analyzers\pyfolio.py文件,如下

class PyFolio(bt.Analyzer):'''This analyzer uses 4 children analyzers to collect data and transforms itin to a data set compatible with ``pyfolio``Children Analyzer- ``TimeReturn``Used to calculate the returns of the global portfolio value- ``PositionsValue``Used to calculate the value of the positions per data. It sets the``headers`` and ``cash`` parameters to ``True``- ``Transactions``Used to record each transaction on a data (size, price, value). Setsthe ``headers`` parameter to ``True``- ``GrossLeverage``Keeps track of the gross leverage (how much the strategy is invested)

由此可知,这里的pyfolio使用四个子分析器来收集数据,并将其转换为与 pyfolio 兼容的数据集。

PyFolio 包含以下四个子分析器:

  • TimeReturn:用于计算全球投资组合价值的回报。               -- 03
  • PositionsValue:用于计算每个数据的持仓价值。                 -- 08
  • Transactions:用于记录每个数据的交易(数量、价格、价值)。 -- 09
  • GrossLeverage:用于跟踪毛杠杆率(策略的投资水平)。 -- 07
def add_analyzer_all(cerebro):cerebro.addanalyzer(bt.analyzers.PyFolio, _name='_PyFolio')  def analyzer_output(result):print("---------------_PyFolio -----------------")sout = result.analyzers._PyFolio.get_analysis()
#     print(sout)for k,v in sout.items():print(f'key: {k}, Value: ...')------------------------------------------
策略为 经典MACD , 期末总资金 111569.09  盈利为 11569.09 总共交易次数为 11 ,交易成功率为 36.4%
---------------_PyFolio -----------------
key: returns, Value: ...
key: positions, Value: ...
key: transactions, Value: ...
key: gross_lev, Value: ...

放到函数中运行,的确是得到四组多重字典,这四组在前面都分别实践过了,就不重复了。

11_回报-returns

该分析器名为 Returns,用于计算总复合回报率、平均回报率、复合回报率和年化回报率。
返回的字典包含以下键:

  •  rtot:总复合回报率
  •  ravg:整个期间(时间框架特定)的平均回报率
  •  rnorm:年化/标准化回报率
  •  rnorm100:年化/标准化回报率,以100%表示

这里我们同样打开文件 \backtrader\analyzers\returns.py ,里面有参数的说明

- ``tann`` (default: ``None``)Number of periods to use for the annualization (normalization) of thenamely:- ``days: 252``- ``weeks: 52``- ``months: 12``- ``years: 1``

于是我们把这四个参数都试了一遍,并参考某文章中对年化收益率的计算公式

ri = (1+Ri)^\frac{250}{period} - 1

def add_analyzer_all(cerebro):cerebro.addanalyzer(bt.analyzers.Returns, _name='_Returns_day', tann=252) # 计算252日度收益cerebro.addanalyzer(bt.analyzers.Returns, _name='_Returns_week', tann=52) # 计算52周度收益cerebro.addanalyzer(bt.analyzers.Returns, _name='_Returns_month', tann=12) # 计算12月度收益cerebro.addanalyzer(bt.analyzers.Returns, _name='_Returns_year', tann=1) # 计算1年度收益def analyzer_output(result):print("---------------_PyFolio -----------------")sout1 = result.analyzers._Returns_day.get_analysis()sout2 = result.analyzers._Returns_week.get_analysis()sout3 = result.analyzers._Returns_month.get_analysis()sout4 = result.analyzers._Returns_year.get_analysis()print(sout1)print(sout2)print(sout3)print(sout4)
策略为 经典MACD , 期末总资金 111569.09  盈利为 11569.09 总共交易次数为 11 ,交易成功率为 36.4%
---------------_PyFolio -----------------
OrderedDict([('rtot', 0.10947386238015983), ('ravg', 0.00029992839008262964), ('rnorm', 0.07851161276138774), ('rnorm100', 7.8511612761387735)])
OrderedDict([('rtot', 0.10947386238015983), ('ravg', 0.00029992839008262964), ('rnorm', 0.015718532957296315), ('rnorm100', 1.5718532957296316)])
OrderedDict([('rtot', 0.10947386238015983), ('ravg', 0.00029992839008262964), ('rnorm', 0.003605625365242038), ('rnorm100', 0.3605625365242038)])
OrderedDict([('rtot', 0.10947386238015983), ('ravg', 0.00029992839008262964), ('rnorm', 0.0002999733730993339), ('rnorm100', 0.02999733730993339)])

 

12_变异加权回报率-VWR

VWR (Variability-Weighted Return)是一种改进的夏普比率计算方法,它考虑了回报的变异性来加权回报,从而提供了一个更好的风险调整后收益的衡量标准。

同上,我们暂不考虑它的原理和计算,先把内置评价看输出结果。

def add_analyzer_all(cerebro):cerebro.addanalyzer(bt.analyzers.VWR, _name='_VWR') def analyzer_output(result):print("---------------_VWR -----------------")sout = result.analyzers._VWR.get_analysis()print(sout)--------------------------------
策略为 经典MACD , 期末总资金 111569.09  盈利为 11569.09 总共交易次数为 11 ,交易成功率为 36.4%
---------------_VWR -----------------
OrderedDict([('vwr', 4.415307366076662)])

结果也是只有一项的字典结构,即 VWR的值。

13_滚动回报率-logreturnsrolling

# 分析器名为 LogReturnsRolling,用于计算给定时间框架和压缩的滚动回报。
def add_analyzer_all(cerebro):cerebro.addanalyzer(bt.analyzers.LogReturnsRolling, _name='_LogReturnsRolling') def analyzer_output(result):print("---------------_LogReturnsRolling -----------------")sout = result.analyzers._LogReturnsRolling.get_analysis()
#     print(sout)for key, value in sout.items():print(f'{key}: {value}')
策略为 经典MACD , 期末总资金 111569.09  盈利为 11569.09 总共交易次数为 11 ,交易成功率为 36.4%
---------------_LogReturnsRolling -----------------
2023-01-11 00:00:00: 0.0
2023-01-12 00:00:00: 0.02023-03-21 00:00:00: 0.0
2023-03-22 00:00:00: 0.0
2023-03-23 00:00:00: 0.002849920446183877
2023-03-24 00:00:00: -0.008815650741360098
2023-03-27 00:00:00: 0.0019657606321923085
2023-03-28 00:00:00: 0.0
2023-03-29 00:00:00: -0.003935393091582192
2023-03-30 00:00:00: 0.013706647466756726
2023-03-31 00:00:00: 0.006783509431897122
2023-04-03 00:00:00: -0.00970487369790382
2023-04-04 00:00:00: -0.009799982039630341
2023-04-06 00:00:00: -0.012885266481896753
2023-04-07 00:00:00: -0.00027168001429825724
2023-04-10 00:00:00: 0.0

 

14_卡马尔比率-Calmar

Calmar 分析器用于计算Calmar比率,这是一个衡量投资组合风险调整后收益的指标
Calmar = 最大回撤期间前的高峰回报率 / 最大回撤期间的回撤百分比
不知道为什么出来的值都是NaN,这个评价指标就暂时不用了

def add_analyzer_all(cerebro):cerebro.addanalyzer(bt.analyzers.Calmar, _name='_Calmar') def analyzer_output(result):print("---------------_Calmar -----------------")sout = result.analyzers._Calmar.get_analysis()print(sout)for key, value in sout.items():print(f'{key}: {value}')
策略为 经典MACD , 期末总资金 111569.09  盈利为 11569.09 总共交易次数为 11 ,交易成功率为 36.4%
---------------_Calmar -----------------
OrderedDict([(datetime.datetime(2023, 1, 31, 0, 0), nan), (datetime.datetime(2023, 2, 28, 0, 0), nan), (datetime.datetime(2023, 3, 31, 0, 0), nan), (datetime.datetime(2023, 4, 30, 0, 0), nan), (datetime.datetime(2023, 5, 31, 0, 0), nan), (datetime.datetime(2023, 6, 30, 0, 0), nan), (datetime.datetime(2023, 7, 31, 0, 0), nan), (datetime.datetime(2023, 8, 31, 0, 0), nan), (datetime.datetime(2023, 9, 30, 0, 0), nan), (datetime.datetime(2023, 10, 31, 0, 0), nan), (datetime.datetime(2023, 11, 30, 0, 0), nan), (datetime.datetime(2023, 12, 31, 0, 0), nan), (datetime.datetime(2024, 1, 31, 0, 0), nan), (datetime.datetime(2024, 2, 29, 0, 0), nan), (datetime.datetime(2024, 3, 31, 0, 0), nan), (datetime.datetime(2024, 4, 30, 0, 0), nan), (datetime.datetime(2024, 5, 31, 0, 0), nan), (datetime.datetime(2024, 6, 30, 0, 0), nan), (datetime.datetime(2024, 7, 31, 0, 0), nan)])
2023-01-31 00:00:00: nan
2023-02-28 00:00:00: nan
2023-03-31 00:00:00: nan
2023-04-30 00:00:00: nan
2023-05-31 00:00:00: nan
2023-06-30 00:00:00: nan
2023-07-31 00:00:00: nan
2023-08-31 00:00:00: nan ...

15_周期统计-periodstats

这是内置的最后一个指标了,我们直接读.py里的说明

get_analysis 方法返回一个字典,其中包含以下键:
average:平均回报率。
stddev:回报率的标准差。
positive:正回报率的数量。
negative:负回报率的数量。
nochange:无变化回报率的数量。
best:最佳回报率。
worst:最差回报率。
def add_analyzer_all(cerebro):cerebro.addanalyzer(bt.analyzers.PeriodStats, _name='_PeriodStats')  def analyzer_output(result):print("---------------_PeriodStats -----------------")sout = result.analyzers._PeriodStats.get_analysis()
#     print(sout)for key, value in sout.items():print(f'{key}: {value}')
策略为 经典MACD , 期末总资金 111569.09  盈利为 11569.09 总共交易次数为 11 ,交易成功率为 36.4%
---------------_PeriodStats -----------------
average: 0.06155213863943909
stddev: 0.10583966175667991
positive: 1
negative: 1
nochange: 0
best: 0.167391800396119
worst: -0.04428752311724082

内置评价实践小结 

总体看下来,可以把这些内置评价的类分为2个大类:
第1个是直接打分统计结果的类

  •  01_AnnualReturn - 以自然年为分组的,比如 2023年 年化收益% , 2024年 年化收益%
  •  02_drawdown  - 当前回撤(周期,值,百分比) + 最大回撤(周期,值,百分比)
  •  04_Sharp Ratio - 夏普比率,直接给出回测周期的夏普率
  •  05_TradeAnalyzer - 交易分析,多重字典,包括交易次数(完成的,open),毛利率,净利率,连胜,连败,这里的Long short应该是开多,开空
  •  06_SQN or SystemQualityNumber - 交易系统的性能得分
  •  11_Returns - 回报 有4个数值,分别是总收益,平均收益,年化收益,年化收益百分比, 这个跟01的自然年不同,应该是计算近1年的(验证下?)
  •  12_VMR Variability-Weighted Return, 是一种改进的夏普比率计算方法,可变加权回报率 
  •  15_PeriodStats 基本统计数据,包括回报率,标准差,正/负数量,最佳回报率和最差回报率

第2个其实是数据存贮

  •  03_TimeReturn 相当于每天的涨跌幅记录
  •  07_GrossLeverage 类似每天的仓位%
  •  08_PositionsValue 每天持仓数据
  •  09_Transactions 每笔交易的数据
  •  10_pyfolio ,这个是前面4个数据存贮的合集(03,07,08,09)
  •  13_LogReturnsRolling 滚动回报率,好像还是对数形式的

简单的与股票软件的评价系统对比起来看一下,大部分的都有
对于某些可以自己根据数据存贮那几个类取数据再进行相关的运算,甚至还可以自己写继承自bt.Analyzer的类...

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

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

相关文章

亲测好用,ChatGPT 3.5/4.0新手使用手册,最全论文指令手册~ 【2024年 更新】

本以为遥遥领先的GPT早就普及了&#xff0c;但小伙伴寻找使用的热度一直高居不下&#xff0c;其实现在很简单了&#xff01; 国产大模型快200家了&#xff0c;还有很多成熟的国内AI产品&#xff0c;跟官网一样使用&#xff0c;还更加好用~ ① 3.5 大多数场景是够用的&#xff…

Mix|使用VS2017CMake构建Qt工程 仿照MVS(仅用于学习)

MVS下载链接&#xff1a;https://www.hikrobotics.com/cn/machinevision/service/download/?module0 CMake工程构建参考&#xff1a;CMake|VS2017CMake3.8搭建Qt项目 文章目录 效果图整体结构实现代码最外层CMakeLists.txt代码实现及CMakeLists.txt搭建CMakeLists.txt搭建主函…

[创业之路-141] :产品经理 - NPDP概述

目录 一、产品经理以及主要职责 1.1 概述 1、市场调研与需求分析 2、产品规划与设计 3、项目管理与协调 4、产品推广与销售支持 5、产品运营与维护 6、其他职责 1.2 产品经理与项目经理的职责分工 1.2.1 职责区别 产品经理 项目经理 1.2.2 合作方式 二、什么是NP…

EXCEL——Vlookup17个高级用法

大纲 一、基本语法 1、参数详解 二、入门篇 1、单条件查找 2、屏蔽查找返回的错误值 三、进阶篇 1、反向查找 2、包含查找 3、区间查找 4、含通配符查找 5、多列查找 6、多区域查找 四、高级篇 1、多条件查找 2、合并单元格查找 3、带合并单元格的多条件查找 …

[数据集][目标检测]夜间老鼠检测数据集VOC+YOLO格式316张1类别+视频文件1个

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;316 标注数量(xml文件个数)&#xff1a;316 标注数量(txt文件个数)&#xff1a;316 标注类别…

MATLAB进阶:矩阵代数

今天我们学习矩阵在MATLAB中的运算。 运算符 与数组运算相同&#xff1a; A. ’转罝 A’&#xff08;共轭&#xff09;转罝 共轭转置&#xff08;A’或A†&#xff09;&#xff1a; 对于一个复数矩阵A&#xff0c;其共轭转置记作A’或A†。共轭转置不仅将矩阵A的行和列互…

大话C语言:第46篇 C语言项目工程化之Makefile详解

1 Makefile概述 Makefile是一种用于自动化构建和管理程序的工具&#xff0c;以文本文件的形式存在。它主要记录了程序的编译规则、依赖关系和操作指令&#xff0c;使得在开发过程中能够轻松地进行代码的编译、链接和部署。 Makefile文件中的命令有一定规范&#xff0c;一旦该文…

Unity--XLua调用C#

Unity–XLua调用C# 由于Unity/C# 和lua是两种语言&#xff0c;两种语言的特性不一样&#xff0c;因此&#xff0c;如果要互相调用的话&#xff0c;需要第三方作桥梁. 因此&#xff0c;为了在Unity中/C#中使用lua的特性&#xff0c;需要在Unity中安装插件&#xff0c;Xlua/toLu…

【学习笔记】8、脉冲波形的变换与产生

本章简略记录。 8.1 单稳态触发器&#xff08;脉冲触发&#xff09; 单稳态触发器 应用于 &#xff1a;&#xff08;1&#xff09;脉冲整型&#xff08;2&#xff09;脉冲延时 &#xff08;3&#xff09;定时 单稳态触发器的工作特性&#xff1a; 没有触发脉冲作用时&#xf…

Flink入门(五)--Flink算子

Map DataStream → DataStream 一个接受一个元素并产生一个元素的函数。 示例 dataStream.map { x > x * 2 } FlatMap DataStream → DataStream 一个接受一个元素并产生零个、一个或多个元素的函数。 例如 dataStream.flatMap { str > str.split(" ") }…

besier打断和升阶,高阶性质

欢迎关注更多精彩 关注我&#xff0c;学习常用算法与数据结构&#xff0c;一题多解&#xff0c;降维打击。 问题描述 对besier曲线在u处打断&#xff0c;生成两条besier曲线对besier曲线升阶处理 bezier高阶性质 求导推导 P ( t ) ∑ i 0 n B i n ( t ) b i \boldsymbol …

Python 爬虫入门(十二):正则表达式「详细介绍」

Python 爬虫入门&#xff08;十二&#xff09;&#xff1a;正则表达式 前言一、正则表达式的用途二、正则表达式的基本组成元素2.1 特殊字符2.2 量词2.3 位置锚点2.4 断言2.5 字符集2.6 字符类2.6.1 基本字符类2.6.2 常见字符类简写2.6.3 POSIX字符类2.6.4 组合使用 三、 正则表…

Datawhale X 李宏毅苹果书 AI夏令营 学习笔记(二)

自适应学习率 我们梯度下降在参数更新上&#xff0c;公式是 W t W t − 1 − η g t &#xff0c; η 是学习率&#xff0c; g t 是梯度 W_tW_{t-1}-\eta g_t&#xff0c;\eta是学习率&#xff0c;g_t是梯度 Wt​Wt−1​−ηgt​&#xff0c;η是学习率&#xff0c;gt​是梯度…

03_React 收集表单数据和 组件生命周期

React 收集表单数据和 组件生命周期 一、收集表单数据1、例子1.1 需求&#xff1a;定义一个包含表单的组件&#xff0c;输入用户名密码后&#xff0c;点击登录提示输入信息 2、理解&#xff1a;包含表单的组件分类2.1 受控组件2.2 非受控组件 二、高阶函数\_函数柯里化1、复习-…

9 正则表达式:Java爬虫和正则表达式、String中的正则表达式方法(基本语法7)

文章目录 前言一、正则表达式1 [ ] 语法(1)[ABC] 和 [^ABC](2)[A-Z]和[a-zA-Z]小总结2 特殊字符语法(\w 这些)3 数量符4 \ 、()、 |5 锚点 ^ 和 $,\b,\B6 (?i) : 忽略其后面的大小写 ---- 这个Java是可以的,其他语言我不知道(正则表达式虽然大多通用,但也有部分是…

zabbix5.0与7.0版本区别 切换建议

Zabbix5.0和Zabbix7.0的区别 1. 性能和扩展性优化 1.1 高效的数据处理和存储 优化的数据库性能&#xff1a; Zabbix 7.0 在数据库层面进行了多项优化&#xff0c;以减少查询延迟和提高数据处理速度。这包括对数据库结构的改进和索引优化&#xff0c;使得大规模数据的读取和写…

Spark-driver和executor启动过程

一、上下文 《Spark-SparkSubmit详细过程》详细分析了从脚本提交任务后driver是如何调用到自己编写的Spark代码的&#xff0c;而我们的Spark代码在运行前必须准备好分布式资源&#xff0c;接下来我们就分析下资源是如何分配的 二、Spark代码示例 我们以一个简单的WordCount程…

打卡学习Python爬虫第五天|Xpath解析的使用

什么是Xpath&#xff1f;是在XML文档中搜索内容的一门语言&#xff0c;HTML可以看作是xml的一个子集。 目录 1、安装lxml模块 2、导入lxml中的etree子模块 3、Xpath使用方法 3.1.选择节点 3.2.选择属性 3.3.选择文本内容 3.4.使用通配符*过滤节点 3.5.使用中括号[]索引…

Java学习_20_File以及IO流

文章目录 前言一、FileFile中常见的成员方法判断和获取创建和删除获取和遍历 二、IO流IO流体系结构字节流字节输出流&#xff1a;FileOutputStream字节输入流FileInputStrea文件拷贝try……catch异常处理中文乱码现象 字符流字符流读取FileReader字符流输出FileWriter底层原理 …

Linux 命令集合

1. linux 系统版本 1.1 linux系统的分类 linux系统&#xff0c;主要分Debian系和RedHat系&#xff0c;还有其它自由的发布版本。 1、Debian系主要有Debian&#xff0c;Ubuntu&#xff0c;Mint等及其衍生版本&#xff1b; 2、RedHat系主要有RedHat&#xff0c;Fedora&#xf…