【答读者问47】一场由夏普率引发的乱斗(backtrader和joinquant计算夏普率的方式哪一种更稳定?)
作者:yunjinqi   类别:    日期:2022-03-20 12:40:15    阅读:1107 次   消耗积分:0 分    

接着上一篇文章【答读者问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)

散点图

在这里插入图片描述#### 箱体图
在这里插入图片描述#### 结论

从散点图和箱体图来看,两家计算的夏普率都有很高的一致性,夏普率的核心作用主要用于衡量承担了一单位的风险可以带来多少超额收益,在不同资产之间对比的时候,使用任意一个算法去计算夏普率都是可以的。


版权所有,转载本站文章请注明出处:云子量化, http://www.woniunote.com/article/97
上一篇:【答读者问46】一场由夏普率引发的乱斗(backtrader,pyfolio和聚宽都是怎么计算夏普率的?)
下一篇:【CTA思考1】CTA基金使用纯趋势跟踪策略还是使用多策略好?