接着上一篇文章【答读者问46】一场由夏普率引发的乱斗(backtrader,pyfolio和聚宽都是怎么计算夏普率的?),本文尝试用蒙特卡洛模拟的思想,模拟1000次,随机生成1000个交易日的收益率序列,然后按照backtrader和聚宽计算夏普率的方式计算出结果,并分别画出一一对应的散点图,箱体图。
测试代码
import numpy as np from functools import reduce from operator import mul import pyecharts.options as opts from pyecharts.charts import Scatter,Boxplot def cal_sharpe(days): n = days # 生成n个收益率序列 rate_arr=np.random.randn(n)/1000 value_arr = rate_arr+1 end_value = reduce(mul,value_arr) total_return = end_value - 1 total_annual_return = (1+total_return)**(250/n)-1 avg_ret = np.mean(rate_arr) ret_std = (sum([(i-avg_ret)**2 for i in rate_arr])*250/(n-1))**0.5 jq_sharpe = (total_annual_return - 0.04)/ret_std day_risk_free_rate = (1+0.04)**(1/250)-1 day_excess_rate_arr = rate_arr-day_risk_free_rate avg_day_excess_rate = np.mean(day_excess_rate_arr) std_day_excess_rate = np.std(day_excess_rate_arr) day_sharpe = avg_day_excess_rate/std_day_excess_rate bt_year_sharpe = day_sharpe*250**0.5 return [jq_sharpe,bt_year_sharpe]def plot_results(days=1000,times=1000): # times是模拟的次数 # days是生成的日收益率的序列 results= [] for i in range(times): results.append(cal_sharpe(days)) # 对于计算的夏普率,按照聚宽的结果从小到大进行排列 sorted_results = sorted(results,key=lambda x:x[0]) # 使用pyecharts进行画图 x_data = [d[0] for d in sorted_results] y_data = [d[1] for d in sorted_results] ( Scatter(init_opts=opts.InitOpts(width="1600px", height="1000px")) .add_xaxis(xaxis_data=x_data) .add_yaxis( series_name="", y_axis=y_data, symbol_size=20, label_opts=opts.LabelOpts(is_show=False), ) .set_series_opts() .set_global_opts( xaxis_opts=opts.AxisOpts( type_="value", splitline_opts=opts.SplitLineOpts(is_show=True) ), yaxis_opts=opts.AxisOpts( type_="value", axistick_opts=opts.AxisTickOpts(is_show=True), splitline_opts=opts.SplitLineOpts(is_show=True), ), tooltip_opts=opts.TooltipOpts(is_show=False), ) .render(f"模拟{times}次随机生成{days}天的收益率序列时backtrader和聚宽夏普率的散点图对比.html") ) print(x_data[-10:]) print(y_data[-10:]) c = Boxplot() c.add_xaxis(["聚宽", "backtrader"]) c.add_yaxis("",c.prepare_data([x_data,y_data])) c.set_global_opts(title_opts=opts.TitleOpts(title="backtrader和聚宽夏普率的对比")) c.render(f"模拟{times}次随机生成{days}天的收益率序列时backtrader和聚宽夏普率的箱体图对比.html") plot_results(days=1000,times=1000)
#### 结论
从散点图和箱体图来看,两家计算的夏普率都有很高的一致性,夏普率的核心作用主要用于衡量承担了一单位的风险可以带来多少超额收益,在不同资产之间对比的时候,使用任意一个算法去计算夏普率都是可以的。
系统当前共有 469 篇文章