whale-quant 学习 part7:量化回测

news2024/12/23 8:15:33

量化回测

  • 计算策略评估指标
  • 聚宽平台量化回测实践
    • 策略实现
  • 参考

计算策略评估指标

使用数据为:贵州茅台(600519.SH)、工商银行(601398.SH)、中国平安(601318.SH),策略基准是沪深300指数(000300.XSHG),策略采用最简单的方式:买入持有。持有周期为20180101 - 20221231,共1826个自然日。
数据获取

import pandas as pd  
import numpy as np
import matplotlib.pyplot as plt
import tushare as ts
%matplotlib inline   

# 无视warning
import warnings
warnings.filterwarnings("ignore")

# 正常显示画图时出现的中文和负号
from pylab import mpl
mpl.rcParams['font.sans-serif']=['SimHei']
mpl.rcParams['axes.unicode_minus']=False

#起始和结束日期可以自行输入,否则使用默认
def get_data(code, start_date, end_date):
    # 配置 tushare token
    my_token = 'XXXXX'  
    pro = ts.pro_api(my_token)

    df = pro.daily(ts_code=code, start_date=start_date, end_date=end_date)
    df.index = pd.to_datetime(df.trade_date)

    return df.close

#以上证综指、贵州茅台、工商银行、中国平安为例
stocks={
    '600519.SH':'贵州茅台',
    '601398.SH':'工商银行',
    '601318.SH':'中国平安'
}

df = pd.DataFrame()
for code,name in stocks.items():
    df[name] = get_data(code, '20180101', '20221231')

# 按照日期正序
df = df.sort_index()

# 本地读入沪深300合并
df_base = pd.read_csv('000300.XSHG_2018_2022.csv')
df_base.index = pd.to_datetime(df_base.trade_date)
df['沪深300'] = df_base['close']
  • 净值曲线 一组时间序列的曲线,其含义表示为股票或基金在不同时间的价值相对于期初的价值的倍数。
# 以第一交易日2018年1月1日收盘价为基点,计算净值并绘制净值曲线
df_worth = df / df.iloc[0]
df_worth.plot(figsize=(15,6))
plt.title('股价净值走势', fontsize=10)
plt.xticks(pd.date_range('20180101','20221231',freq='Y'),fontsize=10)
plt.show()
  • 年化收益率
    累计收益率
    R t = P r − P t P t P T 表示在期末资产的价格 P t 表示期初资产价格 R_t = \frac{P_r-P_t}{P_t} \\ P_T 表示在期末资产的价格 \\ P_t 表示期初资产价格 Rt=PtPrPtPT表示在期末资产的价格Pt表示期初资产价格
    年化收益率
    R p = ( 1 + R ) m n − 1 R_p = (1+R)^{\frac{m}{n}}-1 Rp=(1+R)nm1
    R表示期间总收益率,m是与n(可以是天数、周数、月数)相对应的计算周期,根据计算惯例,m=252、52、12分别指代日、周、月向年化的转换;n为期间自然日天数。(年化收益的一个直观的理解是,假设按照某种盈利能力,换算成一年的收益大概能有多少。这个概念常常会存在误导性,比如,这个月股票赚了5%,在随机波动的市场中,这是很正常的现象。如果据此号称年化收益为5%×12个月=60%,这就显得不太可信了,实际上每个月的收益不可能都这么稳定。所以在听到有人说年化收益的时候,需要特别留意一下具体的情况,否则很容易被误导。)
# 区间累计收益率(绝对收益率)
total_return = df_worth.iloc[-1]-1
total_return = pd.DataFrame(total_return.values,columns=['累计收益率'],index=total_return.index)
total_return

# 年化收益率
annual_return = pd.DataFrame((1 + total_return.values) ** (252 / 1826) - 1,columns=['年化收益率'],index=total_return.index)
annual_return
  • 波动率
    波动率是对收益变动的一种衡量,本质也是风险,波动率和风险,都是用来衡量收益率的不确定性的。我们用方差来表示,年波动率等于策略收益和无风险收益的标准差除以其均值,再除以交易日倒数的平方根,通常交易日取252天。
    V o l a t i l i t y = 252 n − 1 ∑ r i = 1 n ( r p − r p ^ ) 2 r p 表示策略每日收益率 r p ^ 表示策略每日收益率的平均值 n 表示策略执行天数 Volatility = \sqrt{\frac{252}{n-1}\sum^{n}_{ri=1}(r_p-\hat{r_p})^2} \\ r_p 表示策略每日收益率 \\ \hat{r_p} 表示策略每日收益率的平均值 \\ n表示策略执行天数 Volatility=n1252ri=1n(rprp^)2 rp表示策略每日收益率rp^表示策略每日收益率的平均值n表示策略执行天数
df_return = df / df.shift(1) - 1
df_return = ((df_return.iloc[1:] - df_return.mean()) ** 2)

volatility = pd.DataFrame(np.sqrt(df_return.sum() * 252 / (1826-1)),columns=['波动率'],index=total_return.index)
volatility

  • 最大撤回
    选定周期内任一历史时点往后推,于最低点时的收益率回撤幅度的最大值。最大回撤用来描述可能出现的最糟糕的情况。最大回撤是一个重要的风险指标,对于量化策略交易,该指标比波动率还重要。 P为某一天的净值,i为某一天,j为i后的某一天,Pi为第i天的产品净值,Pj则是Pi后面某一天的净值
    该资产的最大回撤计算如下:
    M a x D r a w d o w n = m a x ( P i − P j ) P i MaxDrawdown=\frac{max(P_i-P_j)}{P_i} MaxDrawdown=Pimax(PiPj)
def max_drawdown_cal(df):
    md = ((df.cummax() - df)/df.cummax()).max()
    return round(md, 4)

max_drawdown = {}

stocks={
    '600519.SH':'贵州茅台',
    '601398.SH':'工商银行',
    '601318.SH':'中国平安',
    '000300.XSHG': '沪深300'
}

for code,name in stocks.items():
    max_drawdown[name]=max_drawdown_cal(df[name])

max_drawdown = pd.DataFrame(max_drawdown,index=['最大回撤']).T
max_drawdown
  • Alpha和Beta系数
  • Beta系数代表投资中的系统风险,而在投资中除了系统风险外还面临着市场波动无关的非系统性风险。 Alpha系数就代表投资中的非系统性风险,是投资者获得与市场波动无关的回报。
    可以使用资本资产定价模型(CAPM)来估计策略的beta和alpha值,CAPM模型为:
    E ( r i ) = r f + β ( E ( r m ) − r f ) E ( r i ) 表示投资组合的预期收益率 r f 表示无风险利率 r m 表示市场指数收益率 β 表示股市波动风险与投资机会中的结构性与系统性风险 C A P M 的计量模型可以表示为 r i = α + β r m + ϵ α ϵ α 表示随机扰动,即个体风险 E(r_i)=r_f+\beta(E(r_m)-r_f) \\ E(r_i) 表示投资组合的预期收益率 \\ r_f 表示无风险利率 \\ r_m 表示市场指数收益率 \\ \beta 表示股市波动风险与投资机会中的结构性与系统性风险 \\ CAPM的计量模型可以表示为 \\ r_i=\alpha+\beta r_m +\epsilon_{\alpha} \\ \epsilon_\alpha表示随机扰动,即个体风险 E(ri)=rf+β(E(rm)rf)E(ri)表示投资组合的预期收益率rf表示无风险利率rm表示市场指数收益率β表示股市波动风险与投资机会中的结构性与系统性风险CAPM的计量模型可以表示为ri=α+βrm+ϵαϵα表示随机扰动,即个体风险
from scipy import stats

#计算每日收益率 收盘价缺失值(停牌),使用前值代替
rets=(df.iloc[:,:4].fillna(method='pad')).apply(lambda x:x/x.shift(1)-1)[1:]

#市场指数为x,个股收益率为y
x = rets.iloc[:,3].values
y = rets.iloc[:,:3].values
capm = pd.DataFrame()
alpha = []
beta = []
for i in range(3):
    b, a, r_value, p_value, std_err=stats.linregress(x,y[:,i])
    #alpha转化为年化
    alpha.append(round(a*250,3))
    beta.append(round(b,3))
    
capm['alpha']=alpha
capm['beta']=beta
capm.index=rets.columns[:3]
#输出结果:
capm

  • 夏普比率
    夏普比率(sharpe ratio)表示每承受一单位总风险,会产生多少的超额报酬,该比率越高。夏普比率是在资本资产定价模型进一步发展得来的。
    S h a r p e R a t i o = R p − R f σ p R p 表示策略年化收益率 R F 表示无风险收益差 σ p 表示年化标准差 SharpeRatio=\frac{R_p-R_f}{\sigma_p} \\R_p 表示策略年化收益率 \\R_F 表示无风险收益差 \\ \sigma_p表示年化标准差 SharpeRatio=σpRpRfRp表示策略年化收益率RF表示无风险收益差σp表示年化标准差
# 超额收益率以无风险收益率为基准 假设无风险收益率为年化3%
ex_return=rets - 0.03/250

# 计算夏普比率
sharpe_ratio=np.sqrt(len(ex_return))*ex_return.mean()/ex_return.std()
sharpe_ratio=pd.DataFrame(sharpe_ratio,columns=['夏普比率'])
sharpe_ratio

  • 信息比率
    信息比率含义与夏普比率类似,只不过其参照基准不是无风险收益率,而是策略的市场基准收益率。
    I n f o r m a t i o n R a t i o = R p − R f σ t R p 表示策略年化收益率 R F 表示无风险收益率 σ t 表示策略与基准每日收益率差值的年化标准差 InformationRatio=\frac{R_p-R_f}{\sigma_t} \\ R_p 表示策略年化收益率 \\ R_F表示无风险收益率 \\ \sigma_t 表示策略与基准每日收益率差值的年化标准差 InformationRatio=σtRpRfRp表示策略年化收益率RF表示无风险收益率σt表示策略与基准每日收益率差值的年化标准差
###信息比率
ex_return = pd.DataFrame() 
ex_return['贵州茅台']=rets.iloc[:,0]-rets.iloc[:,3]
ex_return['工商银行']=rets.iloc[:,1]-rets.iloc[:,3]
ex_return['中国平安']=rets.iloc[:,2]-rets.iloc[:,3]

#计算信息比率
information_ratio = np.sqrt(len(ex_return))*ex_return.mean()/ex_return.std()
#信息比率的输出结果
information_ratio = pd.DataFrame(information_ratio,columns=['信息比率'])
information_ratio

聚宽平台量化回测实践

聚宽(https://www.joinquant.com/) 成立于2015年5月,是一家量化交易平台,为投资者提供做量化交易的工具与服务,帮助投资者更好地做量化交易。 整体来看,聚宽具有以下几点优势

  1. 聚宽让做量化交易的成本极大降低
  2. 提供多种优质的便于取用的数据
  3. 提供投资研究功能,便于自由地统计、研究、学习等
  4. 提供多种的策略评价指标与评价维度
  5. 支持多种策略的编写、回测、模拟、实盘
  6. 具备丰富且活跃的量化社区,可以发帖、学习、比赛等。

策略实现

本部分将介绍如何在聚宽平台实现一个双均线策略(具体参照ch05择时策略),并且在聚宽平台上进行回测, 来测试整体收益率。

策略代码如下,核心点有:

  • 选择标的为:002594.XSHE 比亚迪
  • 选择基准为:000300.XSHG 沪深300
  • 策略为:当5日线金叉10日线,全仓买入;当5日线死叉10日线全仓卖出。
# 导入函数库
from jqdata import *

# 初始化函数,设定基准等等
def initialize(context):
    # 设定沪深上证作为基准
    set_benchmark('000300.XSHG')
    # 开启动态复权模式(真实价格)
    set_option('use_real_price', True)
    # 输出内容到日志 log.info()
    log.info('初始函数开始运行且全局只运行一次')
    # 过滤掉order系列API产生的比error级别低的log
    # log.set_level('order', 'error')

    ### 股票相关设定 ###
    # 股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')

    ## 运行函数(reference_security为运行时间的参考标的;传入的标的只做种类区分,因此传入'000300.XSHG'或'510300.XSHG'是一样的)
      # 开盘前运行
    run_daily(before_market_open, time='before_open', reference_security='000300.XSHG')
      # 开盘时运行
    run_daily(market_open, time='open', reference_security='000300.XSHG')
      # 收盘后运行
    run_daily(after_market_close, time='after_close', reference_security='000300.XSHG')

## 开盘前运行函数
def before_market_open(context):
    # 输出运行时间
    log.info('函数运行时间(before_market_open):'+str(context.current_dt.time()))

    # 给微信发送消息(添加模拟交易,并绑定微信生效)
    # send_message('美好的一天~')

    # 要操作的股票:比亚迪(g.为全局变量)
    g.security = '002594.XSHE'

## 开盘时运行函数
def market_open(context):
    log.info('函数运行时间(market_open):'+str(context.current_dt.time()))
    security = g.security
    # 获取股票的收盘价
    close_data5 = get_bars(security, count=5, unit='1d', fields=['close'])
    close_data10 = get_bars(security, count=10, unit='1d', fields=['close'])
    # close_data20 = get_bars(security, count=20, unit='1d', fields=['close'])
    # 取得过去五天,十天的平均价格
    MA5 = close_data5['close'].mean()
    MA10 = close_data10['close'].mean()
    # 取得上一时间点价格
    #current_price = close_data['close'][-1]
    # 取得当前的现金
    cash = context.portfolio.available_cash

    # 五日均线上穿十日均线
    if (MA5 > MA10) and (cash > 0):
        # 记录这次买入
        log.info("5日线金叉10日线,买入 %s" % (security))
        # 用所有 cash 买入股票
        order_value(security, cash)
    # 五日均线跌破十日均线
    elif (MA5 < MA10) and context.portfolio.positions[security].closeable_amount > 0:
        # 记录这次卖出
        log.info("5日线死叉10日线, 卖出 %s" % (security))
        # 卖出所有股票,使这只股票的最终持有量为0
        for security in context.portfolio.positions.keys():
            order_target(security, 0)

## 收盘后运行函数
def after_market_close(context):
    log.info(str('函数运行时间(after_market_close):'+str(context.current_dt.time())))
    #得到当天所有成交记录
    trades = get_trades()
    for _trade in trades.values():
        log.info('成交记录:'+str(_trade))
    log.info('一天结束')
    log.info('##############################################################')

在聚宽上回测策略结果如下,虽然策略整体具备较好的收益,但需要提示的是该策略并不稳定。

  1. 该策略带入了后验知识。因为我们大致知道2018-2020年左右比亚迪处于上涨周期,该周期内基本上五日线在10日线以上。
  2. 该策略会有很强的回撤。例如回测的后半段,该策略已经开始较大幅度回撤,因此需要结合其他策略来进行止盈止损。
  3. 该策略回测周期不够长。本策略仅回测了两年,并且处于较强周期内,因此不具备较强的回测意义。
    在这里插入图片描述

参考

Datawhale 202401 whale-quant 开源学习(更多内容Backtrader、BigQuant等量化实战 微信搜索“Datawhale”)

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

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

相关文章

使用输出事件激活Simulink块

什么是输出事件? 输出事件是发生在Stateflow图表中,但在图表外的Simulink块中可见的事件。这种类型的事件允许图表将图表中发生的事件通知模型中的其他块。 您可以使用输出事件来激活同一模型中的其他块。您可以在图表中定义多个输出事件,其中每个输出事件映射到一个输出端…

Flutter组件 StatefulWidget、StatelessWidget 可继承写法

前言 学过Java的同学&#xff0c;应该都知道面向对象语言的三大特征&#xff0c;封装、继承、多态&#xff1b; Dart也是面向对象的语言&#xff0c;但是在Flutter中的很多组件都被下划线 _ 标记为私有&#xff0c;导致无法继承&#xff0c;本文将介绍一种非私有的创建组件写…

大数据-Spark-关于Json数据格式的数据的处理与练习

上一篇&#xff1a; 大数据-MapReduce-关于Json数据格式的数据的处理与练习-CSDN博客 16.7 Json在Spark中的引用 依旧利用上篇的数据去获取每部电影的平均分 {"mid":1,"rate":6,"uid":"u001","ts":15632433243} {"m…

Qt/C++音视频开发66-音频变速不变调/重采样/提高音量/变速变调/倍速播放/sonic库使用

一、前言 之前在做倍速这个功能的时候&#xff0c;发现快速播放会有滴滴滴的破音出现&#xff0c;正常1倍速没有这个问题&#xff0c;尽管这个破音间隔很短&#xff0c;要放大音量才能听到&#xff0c;但是总归是不完美的&#xff0c;后面发现&#xff0c;通过修改qaudiooutpu…

centOS/Linux系统安全加固方案手册

服务器系统:centos8.1版本 说明:该安全加固手册最适用版本为centos8.1版本,其他服务器系统版本可作为参考。 1.账号和口令 1.1 禁用或删除无用账号 减少系统无用账号,降低安全风险。 操作步骤  使用命令 userdel <用户名> 删除不必要的账号。  使用命令 passwd…

ubuntu 上安装和配置Apache2+Subversion

目录 一、安装Apache2和SVN 二、Apache2设置 三、subversion配置 四、创建仓库和设置权限 五、仓库备份和恢复 系统环境 Ubuntu Linux (20.04) apache2 Subversion(1.13.0) 一、安装Apache2和SVN 通过命令在线安装apache2和subversion apt-get install apache2 libap…

Datax问题记录

1、同步mysql&#xff1a;OS errno 24 - Too many open files 2023-11-20 12:30:04.371 [job-0] ERROR JobContainer - Exception when job run com.alibaba.datax.common.exception.DataXException: Code:[DBUtilErrorCode-07], Description:[读取数据库数据失败. 请检查您的…

颐和园龙纹珍宝展亮相,文物预防保护科技护航

在皇家园林颐和园的深处&#xff0c;一场独特的文化盛宴正静静上演。2月1日&#xff0c;“祥龙贺岁—颐和园藏龙纹题材文物特展”在德和园华丽揭幕。此次特展汇聚了66件珍贵文物&#xff0c;包括玉器、瓷器、书画、珐琅、家具等&#xff0c;每一件都是颐和园园藏的瑰宝。这些文…

LLM应用开发与落地:使用gradio十分钟搭建聊天UI

一、背景 如果你是做LLM应用开发的&#xff0c;特别是做后端开发&#xff0c;你一定会遇到怎么快速写一个聊天UI界面来调试prompt或agent的问题。这时候的你可能在苦恼中&#xff0c;毕竟react.js, next.js, css, html也不是每个人都那么熟练&#xff0c;对吧&#xff1f;即使…

pyqt5-QCheckBox控件使用介绍

一、简介 作用&#xff1a;用于给用户提供若干选项中的多选操作&#xff0c;比如&#xff1a;爱好可以有多个 等等。 继承自 QAbstractButton。 1、基础工程 from PyQt5.Qt import * import sysapp QApplication(sys.argv)window QWidget()window.setWindowTitle("Q…

一文掌握SpringBoot注解之@Configuration知识文集(3)

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

【ADI 知识库】 AN-1354:集成式ZIF、RF至比特、LTE、广域接收机分析和测试结果

官方链接&#xff1a; https://www.analog.com/cn/resources/app-notes/an-1354.html 简介 本应用笔记参考了3GPP TS 36系列文件和ADI公司的多种数据手册、特性标定报告和实验室测试结果。本文重点关注基于集成式零中频(ZIF)、RF至比特、IC (AD9371)的多载波广域LTE接收机的性…

使用css绘制小三角形

要使用CSS绘制小三角形&#xff0c;您可以使用border属性来设置边框样式。下面是一种常见的绘制小三角形的方法&#xff1a; <style>.box {width: 0;height: 0;/* border-top: 10px solid red; */border-bottom: 10px solid blue;border-left: 10px solid transparent;b…

2024PMP考试新考纲-【业务环境领域】典型真题和很详细解析(3)

华研荟继续分享【业务环境Business Environment领域】在新考纲下的真题&#xff0c;帮助大家体会和理解新考纲下PMP的考试特点和如何应用所学的知识和常识&#xff08;经验&#xff09;来解题&#xff0c;并且举一反三&#xff0c;一次性3A通过2024年PMP考试。 2024年PMP考试新…

Interpolator:在Android中方便使用一些常见的CubicBezier贝塞尔曲线动画效果

说明 方便在Android中使用Interpolator一些常见的CubicBezier贝塞尔曲线动画效果。 示意图如下 import android.view.animation.Interpolator import androidx.core.view.animation.PathInterpolatorCompat/*** 参考* android https://yisibl.github.io/cubic-bezier* 实现常…

在flutter中集成Excel导入和导出

flutter中集成Excel导入和导出功能 1、需要的依赖 在pubspec.yaml #excel导出syncfusion_flutter_xlsio: ^24.1.45open_file: ^3.0.1#导入excelflutter_excel: ^1.0.1#选择文件的依赖file_picker: ^6.1.1&#xff08;1&#xff09;依赖说明 在测试时&#xff0c;我们在使用导…

MySQL学习记录——일 MySQL 安装、配置

文章目录 1、卸载内置环境2、安装MySQL3、启动4、登录5、配置my.cnf 当前环境是1核2G云服务器&#xff0c;CentOS7.6 1、卸载内置环境 云服务器中有可能会自带mysql还有mariadb这样的数据库服务&#xff0c;在安装我们mysql前&#xff0c;得先查找一下是否有。 ps ajx |grep m…

20240202在WIN10下使用whisper.cpp

20240202在WIN10下使用whisper.cpp 2024/2/2 14:15 【结论&#xff1a;在Windows10下&#xff0c;确认large模式识别7分钟中文视频&#xff0c;需要83.7284 seconds&#xff0c;需要大概1.5分钟&#xff01;效率太差&#xff01;】 83.7284/4200.1993533333333333333333333333…

Latex学习记录

目录 1.Latex各种箭头符号总结 2.[Latex]公式编辑&#xff0c;编号、对齐 3.Latex公式编号: 多行公式多编号&#xff0c;多行公式单编号 4.LaTex中输入空格以及换行 1.Latex各种箭头符号总结 箭头符号 - ➚ (piliapp.com)https://cn.piliapp.com/symbol/arrow/Latex各种箭头…

【algorithm】一个简单的PID工程 base 用于手生时候快速复习 用于设计模式 cpp语法八股 快速复习校验

写在前面 最近项目一直用matlab&#xff0c;防止手生整一个回忆工具使用的简单的pid demo&#xff0c;走一边流程&#xff0c;包括配工程debug看结果&#xff0c;复用之前记录的配置见我的bloghttps://blog.csdn.net/weixin_46479223/article/details/135082867?csdn_share_t…