量化策略——准备3 数据、Backtrader回测框架与quantstats评价指标

我们一般使用AKShare这个库来获取股票数据或策略中用得到的数据:
AKShare github主页:https://github.com/akfamily/akshare

使用Backtrader框架作为回测的框架:
Backtrader github主页:https://github.com/mementum/backtrader

使用quantstats库作为回测结果评价的库:
quantstats github主页:https://github.com/ranaroussi/quantstats

这一部分准备好之后,后续我们将关注点主要放在【策略】上,对于数据、评价指标这些如无特殊处理,将不再赘述。整个量化的框架构造起来不太容易,如果以前有所了解,可以用自己习惯的方式;如果觉得困难较大,也可以先跳过,等后面能力够了之后,再上手构建。

ps:大家要慎重的使用网上的量化平台,因为偷策略这种事太正常了,大家还是最好自己本地搭一个测试的平台~

文章目录

  • 1. 数据准备
  • 2. Backtrader回测框架准备
  • 3. 评价指标

下面的数据准备与Backtrader回测准备,只是博主提供的一个参考,在开始正式介绍量化策略的时候是不会涉及到每个数据的采集,手把手的代码,这些都是不会提及的,只会提供一个backtrader的策略类,作为对策略的编程实现。

1. 数据准备

比如股票数据:

  1. 首先创建一个data文件夹,然后在文件夹里创建一个stock_data的文件夹

  2. 创建一个code文件夹用来存放程序文件

  3. 然后新建一个python文件,使用如下代码:

    import time
    import akshare as ak
    from tqdm import tqdm
    from loguru import loggerdef extract_data():start_date = "20150101"end_date = "20221101"stock_list = ak.stock_zh_a_spot_em()  # 东方财富网-沪深京 A 股-实时行情数据for stock_code in tqdm(stock_list['代码']):time.sleep(1)stock_df = ak.stock_zh_a_hist(symbol=stock_code, period="daily", start_date=start_date, end_date=end_date, adjust="hfq")  # 后复权stock_df.to_pickle("../data/stock_data/{}.pkl".format(stock_code))logger.debug("ADD DATA {}", stock_code)if __name__ == '__main__':extract_data()
    

这里博主把股票数据保存到data/stock_data/文件夹下,以股票代码.pkl的格式保存:

在这里插入图片描述

2. Backtrader回测框架准备

Backtrader足够简单,同时也非常接近实盘(国外可以一键切换实盘,国内没有接口)

Backtrader的使用请参考:Backtrader量化&回测1——基本的交易策略与挂单买卖

从策略到最终影响金额,都会经历四个步骤:

  1. 策略信号
  2. 委托
  3. 订单
  4. 金额与标的的置换

因此盯紧订单的变化就可以了解策略对金额变动的影响,为了将更多精力用于策略本身的编写上,我们写一个策略模版,然后以后的策略都可以通过继承这个模版,把与策略无关的变量、操作都写在模版里:

from loguru import logger
import backtrader as btclass TemplateStrategy(bt.Strategy):def __init__(self):# 记录用self.buy_bond_record = {}  # 记录购买的订单self.sell_bond_record = {} # 记录卖出的订单def next(self):"""最核心的触发策略"""raisedef notify_order(self, order):"""通知订单状态,当订单状态变化时触发"""today_time_string = self.datetime.datetime().strftime('%Y-%m-%d')if order.status in [order.Submitted, order.Accepted]:  # 接受订单交易,正常情况returnif order.status in [order.Completed]:if order.isbuy():self.buy_bond_record.setdefault(today_time_string, {})self.buy_bond_record[today_time_string].setdefault(order.data._name.replace(".", "_"), [])self.buy_bond_record[today_time_string][order.data._name.replace(".", "_")].append({"order_ref": order.ref,"bond_name": order.data._name,"size": order.size,"price": order.executed.price,"value": order.executed.value,"trade_date": self.datetime.datetime(0),})logger.debug('{} 订单{} 已购入 {} , 购入单价 {:.2f}, 数量 {}, 费用 {:.2f}, 手续费 {:.2f}'.format(self.datetime.date(), order.ref, order.data._name, order.executed.price, order.size,order.executed.value, order.executed.comm))elif order.issell():self.sell_bond_record.setdefault(today_time_string, {})self.sell_bond_record[today_time_string].setdefault(order.data._name.replace(".", "_"), [])self.sell_bond_record[today_time_string][order.data._name.replace(".", "_")].append({"order_ref": order.ref,"bond_name": order.data._name,"size": order.size,"price": order.executed.price,"value": - order.executed.price * order.size,"sell_type": order.info.sell_type,"trade_date": self.datetime.datetime(0),})logger.debug('{} 订单{} 已卖出 {}, 卖出金额 {:.2f}, 数量 {}, 费用 {:.2f}, 手续费 {:.2f}'.format(self.datetime.date(), order.ref, order.data._name, order.executed.price, order.size,-order.executed.price * order.size, order.executed.comm))elif order.status in [order.Margin, order.Rejected]:logger.warning('{} 订单{} 现金不足、金额不足拒绝交易', self.datetime.date(), order.ref)elif order.status in [order.Canceled]:logger.debug("{} 订单{} 已取消", self.datetime.date(), order.ref)elif order.status in [order.Expired]:logger.warning('{} 订单{} 超过有效期已取消, 订单开价 {}, 当天最高价{}, 最低价{}', self.datetime.date(), order.ref, order.price,order.data.high[0], order.data.low[0])

之后的策略均继承此TemplateStrategy策略类,并覆写def next(self)函数即可,这一部分会将所有的订单在日志中打印下来

在程序中,购买的订单可以使用如下代码:

self.buy(data=self.getdatabyname(stock_name), # 针对哪一个股票代码size=100, # 数量price=self.getdatabyname(stock_name).close[0], # 以当天的收盘价购买exectype=bt.Order.Limit, # 限价单valid=self.getdatabyname(stock_name).datetime.date(1),  # 有效期1天)

3. 评价指标

我们使用quantstats这个库来对回测结果进行评价,这个库里的计算方法简单粗暴,通过对已有的计算方法的封装,我们得到可以方便的进行评价的方法:

import pandas as pd
import quantstats as qsdef cal_daily_return(fund_values: pd.Series):"""根据资金变动,计算日资产的变化率:param fund_values: 每日的总资产"""fund_values = fund_values.sort_index()daily_re: pd.Series = (fund_values / fund_values.shift(1)) - 1daily_re.iloc[0] = 0return daily_redef cal_rolling_feature(daily_return_series: pd.Series, rf=0.02, record_dict: dict = None):"""计算各种指标:param daily_return_series: 日收益的变化率:param rf: 无风险收益,这里定为0.02:param record_dict: 指标的结果会追加到这个字典中"""if record_dict is None:record_dict = {}daily_return_series.index = pd.to_datetime(daily_return_series.index.values)feature_df = pd.DataFrame(index=daily_return_series.index)feature_df['累积收益率'] = qs.stats.compsum(daily_return_series).valuesfeature_df['回撤'] = qs.stats.to_drawdown_series(daily_return_series)record_dict.update({"累积收益率": feature_df['累积收益率'].iloc[-1]})feature_dict = {"复合年增长": qs.stats.cagr(daily_return_series, rf=rf),"夏普比率": qs.stats.sharpe(daily_return_series, rf=rf),"索蒂诺": qs.stats.sortino(daily_return_series, rf=rf),"omega": qs.stats.omega(pd.DataFrame(daily_return_series), rf=rf),"最大回撤": qs.stats.max_drawdown(daily_return_series),"最大回撤期(天)": int(qs.stats.drawdown_details(feature_df['回撤'])['days'].max()),"年波动率": qs.stats.volatility(daily_return_series),}record_dict.update(feature_dict)# 决定保留的小数for key, value in record_dict.items():if isinstance(value, float):record_dict[key] = value.round(3)return feature_df, record_dict

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

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

相关文章

红橙Darren视频笔记 换肤框架4 换肤的功能完善 内存泄漏分析

上一篇完成了换肤框架的基本搭建,这一次 我们继续补完上一次遗留的一些可以完善的部分 1.完善换肤 1.1退出后再进入应用 不会丢失上一次保存的皮肤 基本原理:将上一次切换的皮肤path保存在SharedPreference中,下一次进入应用读取该数值 同时…

红橙Darren视频笔记 热更新 bsdiff bspatch 在Android设备上的应用 架构篇1完结篇

概述 当时红橙的视频讲解就差不多90分钟,但是真正自己做出来热更新的demo还是花了八九个晚上,期间遇到各种各样的问题,什么叫台上一分钟 台下十年功是深有体会了。 本节会涉及一部分NDK的知识 推荐阅读Android官方的NDK简介 https://develope…

飞机大战学习心得(Dev-C++)

在c语言中,我们要用代码来做游戏就必须得去实现代码与图形界面接口的互联,也就是要通过按键的输入与输出来控制游戏的进行,所以以下几个头文件是必不可少的 stdio函数就不用我多说了。 windows.h函数可以获得程序的权柄,涉及到了Windows内核…

网易传媒签约法国队、阿根廷队 世界杯独家内容盛宴即将开启

NEW 关注Tech逆向思维视频号 最新视频→【耗资一百亿美元的韦伯望远镜到底观测什么?】 2022年卡塔尔世界杯进入开幕倒计时。7月14日、15日,网易传媒相继宣布与顶级夺冠热门球队法国队、阿根廷队签约,成为两支队伍的中国独家网络媒体合作伙伴&…

连续两届世界杯与冠军同行 网易传媒创造内容赛道卫冕传奇

2022年12月19日凌晨,阿根廷队战胜法国队,夺得了卡塔尔世界杯冠军,如愿捧回了队史上第三座大力神杯,梅西也以最完美的方式完成了他的世界杯谢幕战,成就球王传奇。 对内容公司来说,世界杯是专业内容、创意灵感…

java 上传Excel文件 使用easyExcel读取文件内容

记录Java接口上传Excel文件,及使用阿里的easyExcel读取excel文件内容,进行内容校验的过程。文中贴出代码是精简后代码,仅供参考。 引入依赖 在pom.xml中引入easyExcel需要的依赖,具体参考官网:EasyExcel文档 上传文…

使用TDM-GCC(mingw)搭建EasyX图形库开发环境

首先去EasyX官网:EasyX Graphics Library for C 然后看这个文章只把 EasyX 拷贝进项目里,方便发给没有安装 EasyX 的人编译(以 MinGW 为例) - CodeBus 请使用TDM-GCC进行编译,其他mingw(GNU)编译器可能有问题。 在 …

SpringBoot项目使用EasyExcel读取上传Excel

SpringBoot项目使用EasyExcel读取上传Excel 1、EasyExcel简介 EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。 EasyExcel读取Excel的解析原理: 2、导入相应的依赖文件 <dependency><groupId>com.a…

EasyV数据可视化|精选2022多行业可视化作品合集,看这篇就够了

​​时光荏苒 2022进度条■■■■■■■■□□ 80% 又是一年金秋时节&#xff0c;又是一年硕果累累&#xff0c;在这丰收的时节里&#xff0c;工作也陆续到了冲刺的阶段&#xff0c;准备开干的你&#xff0c;是否有这些疑惑 想要的效果构思不出来&#xff0c;需要点小灵感&am…

英文Essay各部分的写作攻略

以下是英文Essay各部分的写作攻略&#xff1a; 引言部分&#xff1a;在引言中&#xff0c;应该清晰明了地陈述你的主题和目的&#xff0c;以及你将要探讨的问题和论点。你可以使用一个有趣的事实、例子、名言、问题或者比喻来引起读者的兴趣。同时&#xff0c;你也可以在引言中…

从头到尾写SQL(二)

二 数据表的创建和管理 数据库是我们用的别人的。。数据表就该我们自己创建了吧。。 1.数据基本类型 建表的时候&#xff0c;需要我们确定好这个表有多少字段&#xff0c;这些字段又都是什么类型的(其实创建完以后这些东西也能改)。那么数据库接纳的数据类型有哪些呢&#…

暑假用chatgpt肝了一篇顶会...

小时候特别羡慕大雄&#xff0c;因为他有可以帮他写作业的机器猫小叮当。 熬夜读论文&#xff0c;却无法得出一个好的idea&#xff0c;深夜薅头发苦恼的时候&#xff0c;就会想如果有一个机器人&#xff0c;给出一串指令就能马上生成一篇质量上佳的论文就好了。 现在&#xff0…

Unity Open Day 北京站-技术专场:生成式AI技术助力Unity创作

【获取 2023 Unity Open Day 北京站演讲 PPT】 伴随Unity中国版引擎的布局以及AI技术的爆发式发展&#xff0c;ChatGPT、StableDiffusion等生成式AI技术受到广大Unity创作者的关注。Unity已经在AI领域探索多年&#xff0c;一直致力于利用人工智能技术以及工具&#xff0c;帮助创…

3D引擎龙头Unity:元宇宙和AI活跃玩家

Unity是用于创建和操作交互式实时3D内容的世界领先平台。凭借灵活的编辑器、友好的开发环境、丰富的工具套件&#xff0c;Unity吸引了大量开发者&#xff0c;全球排名前1000的移动游戏70%以上使用了Unity的创作和运营解决方案&#xff0c;如今&#xff0c;Unity引擎在工业场景、…

城市的 “数字生命” 是怎么被赋予的?|场景创新公司是这样开会的

ChatGPT 为我们带来了巨大便利的同时&#xff0c;也让更多人茫然、焦虑甚至恐惧。对于这一重塑我们生活的技术&#xff0c;每个渺小的个体或许都在心里有过类似的疑问&#xff1a;我&#xff0c;还能做什么&#xff1f; 当体力劳动、内容生产都能够以技术的方式进行翻天覆地的变…

关于ChatGPT应用于软件测试中的思考

前言 关于最近大火的ChatGPT相信各位也听过不同渠道听说过他的厉害&#xff0c;目前发展趋势比较火热&#xff0c;科技公司都有在考虑怎么使用ChatGPT进行提高研发效率以及办公效率&#xff0c;最近我所在的公司也有在要求大家使用ChatGPT进行改善工作效率&#xff0c;所以引发…

借助 AI 我为 Raycast 制作了一个可以 OCR 中文的插件

本文速通&#xff1a;最近用了 Raycast&#xff0c;真的很棒&#xff01;但是没有好用的中文 OCR 插件&#xff0c;不怎么会写 Typescript 的我&#xff0c;在 ChatGPT 的指导下&#xff0c;整了一个小插件。开发过程非常不严肃&#xff0c;充满了野路子&#xff0c;不敢妄称指…

ChatGPT令人触目惊心的地方

前两天&#xff0c;马斯克联合数千名AI科技人员&#xff0c;要求暂停巨型AI实验的新闻&#xff0c;想必大家都知道了。 这个消息挺爆炸&#xff0c;一度加剧了人们的恐慌情绪。 鸣哥当时灵光一闪&#xff0c;这件事ChatGPT是如何看待的&#xff1f; 于是我输入这一新闻事件&a…

卷积神经网络与循环神经网络实战 --- 手写数字识别及诗词创作

卷积神经网络与循环神经网络实战 — 手写数字识别及诗词创作 文章目录 卷积神经网络与循环神经网络实战 --- 手写数字识别及诗词创作一、神经网络相关知识1. 深度学习2. 人工神经网络回顾3. 卷积神经网络&#xff08;CNN&#xff09;3.1 卷积层3.2 汇集&#xff08;池化&#x…

chatgpt赋能python:如何在Python中中断程序并退出程序

如何在Python中中断程序并退出程序 在Python编程的过程中&#xff0c;有时候我们需要中断程序的执行&#xff0c;并让程序退出。这在调试程序时尤为重要。本文将介绍Python中如何中断程序并退出程序。 使用sys.exit()函数 在Python中&#xff0c;我们可以使用sys.exit()函数…