楼主: tkfy920
5731 8

[源码分享] 【手把手教你】Python量化策略风险指标 [推广有奖]

  • 8关注
  • 38粉丝

Python金融量化

已卖:1641份资源

讲师

62%

还不是VIP/贵宾

-

威望
0
论坛币
474 个
通用积分
22.3086
学术水平
27 点
热心指数
25 点
信用等级
19 点
经验
65416 点
帖子
544
精华
0
在线时间
516 小时
注册时间
2008-3-28
最后登录
2025-1-14

楼主
tkfy920 在职认证  学生认证  发表于 2019-1-22 14:32:56 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币

引言

尽管过去不能代表未来,通过历史回测来评估量化策略仍然是量化投资非常重要的一环。量化回测过程中常用到的指标有年化收益率、最大回撤、beta、alpha、夏普比率、信息比率等(见下图)。目前很多量化网站都能提供Python的量化回测框架,如聚宽 、优矿、万矿、Zipline 、vnpy 和pyalgotrade等,为我们评估量化策略提供了很好的交互平台。毕竟平台的使用有其局限性,如果不借助平台, 如何使用python写一个简单的量化回测框架呢?本文将一步一步为你展示如何使用python计算量化策略风险指标。文中提及股票仅供学习示例,不构成投资建议。

02Python计算量化指标
使用tushare获取交易数据,考虑最简单的策略:买入持有!分别计算期间总收益率,年化收益率,最大回撤,beta、alpha系数,夏普比率和信息比率。

#先引入后面可能用到的包(package)
import pandas as pd  
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline   

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

### 获取数据:tushare开源库(确认已安装好:pip install tushare)
import tushare as ts
#起始和结束日期可以自行输入,否则使用默认
def get_data(code,start_date="2009-01-01", end_date="2019-01-18"):
    df = ts.get_k_data(code, start=start_date, end=end_date)
    df.index=pd.to_datetime(df.date)
    return df.close
#返回收盘价

#以上证综指、贵州茅台、工商银行、中国平安为例
stocks={'sh':'上证综指','600519':'贵州茅台',
        '601398':'工商银行','601318':'中国平安'}
#获取上述股票(指数)的每日前复权收盘价
df=pd.DataFrame()
for code,name in stocks.items():
    df[name]=get_data(code)

df.head()


#以第一交易日2009年1月5日收盘价为基点,计算净值

df_new=df/df.iloc[0]
#将上述股票在回测期间内的净值可视化
df_new.plot(figsize=(16,7))
#图标题
plt.title('股价净值走势',fontsize=15)
#设置x轴坐标
my_ticks = pd.date_range('2008-01-01','2019-01-18',freq='Y')
plt.xticks(my_ticks,fontsize=12)
#去掉上、右图的线
ax=plt.gca()
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
plt.show()




1累计收益率和年化收益率

收益率可以根据上面公式计算,或使用对数收益率,下面直接根据上面的累计净值来推出累计收益率(累计净值-1)。

### 区间累计收益率(绝对收益率)
total_ret=df_new.iloc[-1]-1
TR=pd.DataFrame(total_ret.values,columns=['累计收益率'],index=total_ret.index)
TR


2最大回撤

实际上,numpy和pandas借助库函数均可以实现一行代码计算最大回撤。

#numpy:np.maximum.accumulate计算序列累计最大值
code='上证综指'
n_d=((np.maximum.accumulate(df[code])-df[code])/np.maximum.accumulate(df[code])).max()
#pandas使用cummax()计算序列累计最大值
p_d=((df[code].cummax()-df[code])/df[code].cummax()).max()
#打印结果
print(f'numpy方法计算结果:{round(n_d*100,2)}%')
print(f'pandas方法计算结果:{round(p_d*100,2)}%') numpy方法计算结果:52.3%
pandas方法计算结果:52.3%   


###年化收益率,假设一年以250交易日计算annual_ret=pow(1+total_ret,250/len(df_new))-1
AR=pd.DataFrame(annual_ret.values,columns=['年化收益率'],index=annual_ret.index)
AR


#定义成函数,减少重复工作

def max_drawdown(df):
    md=((df.cummax()-df)/df.cummax()).max()
    return round(md,4)
md={}
for code,name in stocks.items():
    md[name]=max_drawdown(df[name])
#最大回撤率结果:
MD=pd.DataFrame(md,index=['最大回撤']).T
MD


3alpha和beta


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

#市场指数为x,个股收益率为y
from scipy import stats
x=rets.iloc[:,0].values
y=rets.iloc[:,1:].values
AB=pd.DataFrame()
alpha=[]
beta=[]
for i in range(3):
#使用scipy库中的stats.linregress线性回归
#python回归有多种实现方式,
#如statsmodels.api的OLS,sklearn库等等
    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))
AB['alpha']=alpha
AB['beta']=beta
AB.index=rets.columns[1:]
#输出结果:
AB

#使用公式法直接计算beta值(见前文公式):
beta1=rets[['上证综指','贵州茅台']].cov().iat[0,1]/rets['上证综指'].var()
beta2=rets[['上证综指','工商银行']].cov().iat[0,1]/rets['上证综指'].var()
beta3=rets[['上证综指','中国平安']].cov().iat[0,1]/rets['上证综指'].var()
print(f'贵州茅台beta:{round(beta1,3)}')
print(f'工商银行beta:{round(beta2,3)}')
print(f'中国平安beta:{round(beta3,3)}')

#输出结果:贵州茅台beta:0.637
工商银行beta:0.614
中国平安beta:1.071

#使用公式法直接计算beta值(见前文公式):
#annual_ret是前文计算出来的年化收益率
alpha1=(annual_ret[1]-annual_ret[0]*beta1)
alpha2=(annual_ret[2]-annual_ret[0]*beta2)
alpha3=(annual_ret[3]-annual_ret[0]*beta3)
print(f'贵州茅台alpha:{round(alpha1,3)}')
print(f'工商银行alpha:{round(alpha2,3)}')
print(f'中国平安alpha:{round(alpha3,3)}')

#输出结果:贵州茅台alpha:0.244
工商银行alpha:0.077
中国平安alpha:0.138

4夏普比率和信息比率


#超额收益率以无风险收益率为基准
#假设无风险收益率为年化3%
exReturn=rets-0.03/250
#计算夏普比率
sharperatio=np.sqrt(len(exReturn))*exReturn.mean()/exReturn.std()
#夏普比率的输出结果
SHR=pd.DataFrame(sharperatio,columns=['夏普比率'])
SHR

###信息比率
#超额收益率以指数收益率或其他为基准
#这里以上证综指为基准
ex_return=pd.DataFrame()
ex_return['贵州茅台']=rets.iloc[:,1]-rets.iloc[:,0]
ex_return['工商银行']=rets.iloc[:,2]-rets.iloc[:,0]
ex_return['中国平安']=rets.iloc[:,3]-rets.iloc[:,0]a

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



indicators=pd.concat([TR,AR,MD,AB,SHR,INR],axis=1,
    join='outer',sort='False')
#结果保留三位小数
indicators.round(3)


二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝


已有 1 人评分经验 学术水平 热心指数 信用等级 收起 理由
accumulation + 100 + 1 + 1 + 1 精彩帖子

总评分: 经验 + 100  学术水平 + 1  热心指数 + 1  信用等级 + 1   查看全部评分

本帖被以下文库推荐

当一个人把爱倾注于心灵的深处,有什么样的高度不能踩在脚下。

沙发
bluepoet1025 发表于 2019-1-26 22:58:47
写的很好啊,我要好好学习一下。

藤椅
tkfy920 在职认证  学生认证  发表于 2019-2-1 16:28:44
bluepoet1025 发表于 2019-1-26 22:58
写的很好啊,我要好好学习一下。
谢谢,欢迎转发与交流,微信公众号是Python金融量化,获取更多干货

板凳
tkfy920 在职认证  学生认证  发表于 2019-3-8 16:20:04
加入知识金融量化星球,免费获取金融量化视频资料和python源码

IMG_3708.JPG (109.9 KB)

IMG_3708.JPG

报纸
白雾 发表于 2019-5-25 16:03:33
写的太好了,有助于实习

地板
tkfy920 在职认证  学生认证  发表于 2019-6-25 08:05:11 来自手机
白雾 发表于 2019-5-25 16:03
写的太好了,有助于实习
谢谢,欢迎关注Python金融量化,持续干货

7
tkfy920 在职认证  学生认证  发表于 2020-2-22 11:29:33
欢迎转发,感谢评论。

8
tkfy920 在职认证  学生认证  发表于 2020-6-2 09:11:34
量化评价指标。

9
tkfy920 在职认证  学生认证  发表于 2020-11-19 16:51:49
量化策略评价指标衡量

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注jr
拉您进交流群
GMT+8, 2026-1-28 01:59