pyfolio工具结合backtrader分析量化策略组合,附源码+问题分析

pyfolio可以分析backtrader的策略,并生成一系列好看的图表,但是由于pyfolio直接install的稳定版有缺陷,开发版也存在诸多问题,使用的依赖版本都偏低,试用了一下之后还是更推荐quantstats。

1、安装依赖

pip install pyfolio
# 直接install是稳定版会报各式各样的错误,要用git拉开发版
pip install git+https://github.com/quantopian/pyfolio

但是git拉也可能报各种http代理等问题,可以使用如下方法解决:

  1. 克隆 GitHub 仓库: 打开命令行或终端,然后使用以下命令将 pyfolio 仓库克隆到本地:

    bashCopy code

    如果git clone https://github.com/quantopian/pyfolio.git报错,可以用下面格式
    git clone git@github.com:quantopian/pyfolio.git

    这将在当前目录下创建一个名为 “pyfolio” 的文件夹,并将仓库的所有代码下载到其中。

  2. 切换到仓库目录: 使用以下命令进入 pyfolio 文件夹:

    bashCopy code

    cd pyfolio

  3. 安装: 在 pyfolio 文件夹中执行以下命令,安装开发版本的代码:

    bashCopy code

    pip install -e .

    -e 选项表示以 “editable” 模式安装,这意味着你对代码的修改会立即反映在安装的库中。这对于开发和测试非常有用。

pyfolio策略源码

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
'''
@Author:Airyv
@Project:test 
@File:quantstats_demo.py
@Date:2024/1/1 21:45 
@desc:
'''from datetime import datetimeimport backtrader as bt  # 升级到最新版
import matplotlib.pyplot as plt  # 由于 Backtrader 的问题,此处要求 pip install matplotlib==3.2.2
import akshare as ak  # 升级到最新版
import pandas as pd
import quantstats as qs
import pyfolio as pfplt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False# 利用 AKShare 获取股票的后复权数据,这里只获取前 6 列
stock_hfq_df = ak.stock_zh_a_hist(symbol="600028", adjust="hfq").iloc[:, :6]
# 处理字段命名,以符合 Backtrader 的要求
stock_hfq_df.columns = ['date','open','close','high','low','volume',
]
# 把 date 作为日期索引,以符合 Backtrader 的要求
stock_hfq_df.index = pd.to_datetime(stock_hfq_df['date'])class MyStrategy(bt.Strategy):"""主策略程序"""params = (("maperiod", 5),)  # 全局设定交易策略的参数def __init__(self):"""初始化函数"""self.data_close = self.datas[0].close  # 指定价格序列# 初始化交易指令、买卖价格和手续费self.order = Noneself.buy_price = Noneself.buy_comm = None# 添加移动均线指标self.sma = bt.indicators.SimpleMovingAverage(self.datas[0], period=self.params.maperiod)def next(self):"""执行逻辑"""if self.order:  # 检查是否有指令等待执行,return# 检查是否持仓if not self.position:  # 没有持仓if self.data_close[0] > self.sma[0]:  # 执行买入条件判断:收盘价格上涨突破20日均线self.order = self.buy(size=100)  # 执行买入else:if self.data_close[0] < self.sma[0]:  # 执行卖出条件判断:收盘价格跌破20日均线self.order = self.sell(size=100)  # 执行卖出# 更新指令状态if self.order:self.buy_price = self.data_close[0]self.buy_comm = self.broker.getcommissioninfo(self.data).getcommission(self.buy_price, 100)self.order = None  # 在这里将订单设置为None,表示没有正在执行的订单else:self.buy_price = Noneself.buy_comm = Nonecerebro = bt.Cerebro()  # 初始化回测系统
start_date = datetime(2010, 1, 3)  # 回测开始时间
end_date = datetime(2023, 6, 16)  # 回测结束时间
data = bt.feeds.PandasData(dataname=stock_hfq_df, fromdate=start_date, todate=end_date)  # 加载数据
# data=bt.feeds.PandasData(dataname=df,fromdate=start_date,todate=end_date)#加银数据
cerebro.adddata(data)  # 将数据传入回测系统
cerebro.addstrategy(MyStrategy)  # 将交易策略加载到回测系统中
# 加入pyfolio分析者
cerebro.addanalyzer(bt.analyzers.PyFolio, _name='pyfolio')
start_cash = 1000000
cerebro.broker.setcash(start_cash)  # 设置初始资本为 100000
cerebro.broker.setcommission(commission=0.002)  # 设置交易手续费为 0.2%
result = cerebro.run()  # 运行回测系统port_value = cerebro.broker.getvalue()  # 获取回测结束后的总资金
pnl = port_value - start_cash  # 盈亏统计print(f"初始资金: {start_cash}\n回测期间:{start_date.strftime('%Y%m%d')}:{end_date.strftime('%Y%m%d')}")
print(f"总资金: {round(port_value, 2)}")
print(f"净收益: {round(pnl, 2)}")# cerebro.plot(style='candlestick')  # 画图cerebro.broker.getvalue()strat = result[0]
pyfoliozer = strat.analyzers.getbyname('pyfolio')returns, positions, transactions, gross_lev = pyfoliozer.get_pf_items()
%matplotlib inline
pf.create_full_tear_sheet(returns,positions=positions,transactions=transactions,live_start_date='2023-01-03')# returns, positions, transactions, gross_lev = pyfoliozer.get_pf_items()
# returns
# positions
# transactions
# gross_lev# pf.create_full_tear_sheet(returns)
# pf.create_full_tear_sheet(
#     returns,
#     positions=positions,
#     transactions=transactions,
#     live_start_date='2010-01-03',
#     round_trips=True)
# pf.create_full_tear_sheet(returns,live_start_date='2010-01-03')
# cerebro.plot()

错误解决

解决后可能报错:

  1. AttributeError: 'Series' object has no attribute 'iteritems'
    solution:

    For anyone else who has the same error pls edit the plotting.py file in ur site packages folder from iteritems() to items()

    意思是进入plotting.py文件(可以用everything搜索)中全局搜索iteritems(),替换为items()即可

  2. AttributeError: module 'pandas' has no attribute 'Float64Index'

    原因是pandas版本太高了(2.0.1),安装低版本:

pip uninstall pandas
pip install pandas==1.5.3 -i https://pypi.tuna.tsinghua.edu.cn/simple
  1. File "...\pyfolio\timeseries.py", line 896, in get_max_drawdown_underwater

    将timeseries.py893行改为:

# valley = np.argmin(underwater)  # end of the period
valley = underwater.idxmin()
  1. File "\pyfolio\round_trips.py", line 133, in _groupby_consecutive grouped_price = (t.groupby(('block_dir',KeyError: ('block_dir', 'block_time')

    修改round_trips.py第133行

        # grouped_price = (t.groupby(('block_dir',#                            'block_time'))#                   .apply(vwap))grouped_price = (t.groupby(['block_dir','block_time']).apply(vwap))grouped_price.name = 'price'grouped_rest = t.groupby(['block_dir', 'block_time']).agg({'amount': 'sum','symbol': 'first','dt': 'first'})
  1. File "...\pyfolio\round_trips.py", line 77, in agg_all_long_short stats_all = (round_trips pandas.errors.SpecificationError: nested renamer is not supported

    改round_trips.py第77行

    stats_all = (round_trips.assign(ones=1).groupby('ones')[col].agg(list(stats_dict.items())).T.rename(columns={1.0: 'All trades'}))stats_long_short = (round_trips.groupby('long')[col].agg(list(stats_dict.items())).T.rename(columns={False: 'Short trades',True: 'Long trades'}))
  1. File "...\pyfolio\round_trips.py", line 393, in gen_round_trip_stats round_trips.groupby('symbol')['returns'].agg(RETURN_STATS).T pandas.errors.SpecificationError: nested renamer is not supported

    393行修改:

    stats['symbols'] = \round_trips.groupby('symbol')['returns'].agg(list(RETURN_STATS.items())).T
  1. ValueError: The number of FixedLocator locations (16), usually from a call to set_ticks, does not match the number of labels (3).

    注释掉tears.py文件的871行

画图运行

在Jupter notebook中运行,不建议直接console中运行,结果如图:


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

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

相关文章

数据采集有哪些方法?HTTP代理起到什么作用?

在这个数字化的时代&#xff0c;数据就如同生活中不可或缺的元素&#xff0c;我们的行为、喜好、甚至是想法都被转化成了数字化的信息。那么&#xff0c;现代社会是如何进行数据的采集的呢&#xff1f;让我们一同来看看&#xff01; 1. 网络浏览行为的追踪 在我们浏览互联网的…

【AI视野·今日NLP 自然语言处理论文速览 第六十六期】Tue, 31 Oct 2023

AI视野今日CS.NLP 自然语言处理论文速览 Tue, 31 Oct 2023 (showing first 100 of 141 entries) Totally 100 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers The Eval4NLP 2023 Shared Task on Prompting Large Language Models a…

解读 $mash 通证 “Fair Launch” 规则,将公平发挥极致?(Staking 玩法)

Solmash是Solana生态中由社区主导的铭文资产LaunchPad平台&#xff0c;该平台旨在为Solana原生铭文项目&#xff0c;以及通过其合作伙伴SoBit跨链桥桥接到Solana的Bitcoin生态铭文项目提供更广泛的启动机会。有了Solmash&#xff0c;将会有更多的Solana生态的铭文项目、资产通过…

24年初级会计资格考试报名信息采集流程共10大步骤,千万不要搞错

2024年初级会计资格考试报名信息采集流程共10大步骤&#xff0c;不要搞错哦&#xff1b; 第一步&#xff1a;输入证件号、点击登录 第二步&#xff1a;阅读采集须知 第三步&#xff1a;填写个人信息&#xff08;支付宝搜索"亿鸣证件照"或者微信搜索"随时照&q…

计算机网络-以太网交换基础

一、网络设备的演变 最初的网络在两台设备间使用传输介质如网线等进行连接就可以进行通信。但是随着数据的传输需求&#xff0c;多个设备需要进行数据通信时就需要另外的设备进行网络互联&#xff0c;并且随着网络传输的需求不断更新升级。从一开始的两台设备互联到企业部门内部…

数据结构第六弹---带头双向循环链表

双向循环链表 1、带头双向循环链表概念2、带头双向循环链表的优势3、带头双向循环链表的实现3.1、头文件包含和结构定义3.2、创建新结点3.3、打印3.4、初始化3.5、销毁3.6、尾插3.7、头插3.8、头删3.9、尾删3.10、查找3.11、在pos之前插入3.12、删除pos位置3.13、判断是否为空3…

EBU7140 Security and Authentication(三)密钥管理;IP 层安全

B3 密钥管理 密钥分类&#xff1a; 按时长&#xff1a; short term&#xff1a;短期密钥&#xff0c;用于一次加密。long term&#xff1a;长期密钥&#xff0c;用于加密或者授权。 按服务类型&#xff1a; Authentication keys&#xff1a;公钥长期&#xff0c;私钥短期…

虾皮、Lazada店铺流量怎么提升?自养号优势及测评系统如何搭建?

虾皮、Lazada是东南亚地区最大的购物平台之一&#xff0c;吸引了大量的买家和卖家。在竞争激烈的虾皮市场上&#xff0c;如何提升店铺的流量成为许多卖家关注的问题。以下是关于如何提升虾皮、Lazada店铺流量的一些建议。 一、店铺流量怎么提升? 首先&#xff0c;进行优质的…

50N65-ASEMI高压N沟道MOS管50N65

编辑&#xff1a;ll 50N65-ASEMI高压N沟道MOS管50N65 型号&#xff1a;50N65 品牌&#xff1a;ASEMI 封装&#xff1a;TO-247 连续漏极电流(Id)&#xff1a;50A 漏源电压(Vdss)&#xff1a;650V 功率(Pd)&#xff1a;388W 芯片个数&#xff1a;2 引脚数量&#xff1a;…

tp5+workman(GatewayWorker) 安装及使用

一、安装thinkphp5 1、宝塔删除php禁用函数putenv、pcntl_signal_dispatch、pcntl_wai、pcntl_signal、pcntl_alarm、pcntl_fork&#xff0c;执行安装命令。 composer create-project topthink/think5.0.* tp5 --prefer-dist 2、配置好站点之后&#xff0c;浏览器打开访问成…

软件验收测试计划、验收测试报告案例模板参考

1. 概述 1.1. 编写目的 1.2. 测试背景 1.3. 测试依据 1.4. 测试对象 1.5. 测试资源 2. 测试方式与环境 2.1. 测试方式 2.2. 测试环境 3. 测试结果 3.1. 功能适合性和准确性 3.1.1. 总体统计 3.1.2. 详细结果 3.2. 安全性 3.3. 可靠性和性能 4. 总体分析 5. 测试…

bat批处理文件_输出内容到文本

文章目录 1、echo str > test.txt&#xff08;覆盖原有内容&#xff09;2、echo str >> test.txt&#xff08;不覆盖原有内容&#xff0c;追加&#xff09; 1、echo str > test.txt&#xff08;覆盖原有内容&#xff09; 2、echo str >> test.txt&#xff0…

Spring Cloud Gateway 缓存区异常

目录 1、问题背景 2、分析源码过程 3、解决办法 最近在测试环境spring cloud gateway突然出现了异常&#xff0c;在这里记录一下&#xff0c;直接上干货 1、问题背景 测试环境spring cloud gateway遇到以下异常 DataBufferLimitException: Exceeded limit on max bytes t…

Docker nginx容器代理播放m3u8视频文件(HLS)

文章目录 Docker Nginx容器代理播放M3U8文件教程获取Nginx Docker镜像设置Nginx配置文件用 ffmpeg 将 MP4 文件转换成 m3u8 文件运行Docker容器测试M3U8流其他问题我用vlc都能播放http://192.168.121.50/forest4kTest.m3u8和http://192.168.121.50/forest4kTest.mp4&#xff0c…

【HBase】——优化

1 RowKey设计 重要&#xff1a;一条数据的唯一标识就是 rowkey&#xff0c;那么这条数据存储于哪个分区&#xff0c;取决于 rowkey 处于 哪个一个预分区的区间内&#xff0c;设计 rowkey的主要目的 &#xff0c;就是让数据均匀的分布于所有的 region 中&#xff0c;在一定程度…

HTML 使用 ruby 给汉字加拼音

使用 ruby 给汉字加拼音 兼容性 使用 ruby 给汉字加拼音 大家有没有遇到过要给汉字头顶上加拼音的需求? 如果有的话, 你是怎么解决的呢? 如果费尽心思, 那么你可能走了很多弯路, 因为 HTML 原生就有这样的标签来帮我们实现类似的需求. <ruby> ruby 本身是「红宝石」…

大学物理-实验篇——测量误差与数据处理(测量分类、误差、有效数字、逐差法)

目录 测量分类 测量次数角度 测量条件角度 误差 误差分类 系统误差 随机误差 异常值 误差描述 精密度&#xff08;Precision&#xff09; 正确度&#xff08;Trueness&#xff09; 准确度/精确度&#xff08;Accuracy&#xff09; 随机误差的处理 直接测量 算术…

一起玩儿物联网人工智能小车(ESP32)——27. 旋转编码器的使用方法

摘要&#xff1a;本文介绍旋转编码器的使用方法 旋转编码器是一种机电设备&#xff0c;可将轴或轴的角位置或运动转换为模拟或数字输出信号&#xff0c;在工业控制中发挥着举足轻重的作用。旋转编码器目前被广泛的应用在数控机床、印刷设备、包装机械、输送带、电梯、机器人、风…

WeNet语音识别+Qwen-72B-Chat Bot+Sambert-Hifigan语音合成

WeNet语音识别Qwen-72B-Chat Bot&#x1f47e;Sambert-Hifigan语音合成 简介 利用 WeNet 进行语音识别&#xff0c;使用户能够通过语音输入与系统进行交互。接着&#xff0c;Qwen-72B-Chat Bot作为聊天机器人接收用户的语音输入或文本输入&#xff0c;提供响应并与用户进行对话…

Docker overlay2文件busy,容器不能删除问题解决

文章目录 在删除docker容器的时候报错,说设备正忙通过 docker ps -a 查看有两个状态的dead的容器解决方法&#xff1a;1.查看所有挂载的设备2.截取设备的进程id3.清理进程(kill掉即可) 在删除docker容器的时候报错,说设备正忙 Error response from daemon: Driver overlay2 fai…