0


使用python绘制有效性前沿

有效性前沿
在无数风险资产投资组合中,只要给出既定风险水平,我们总是可以找到收益最高的一个组合。当投资者可承受的风险水平变化时,与该风险水平相对应的最优投资组合A点也一直存在,并且随着风险水平变化不断的移动。这条由不同风险水平下最优投资组合A点构成的曲线,我们称之为有效曲线,又叫有效前沿。

有效性前沿python计算
输入项:
1、资产收益率irr
2、资产相关性矩阵(协方差):cov
3、随机种子:seed。随机生成的配置比例数量,随机种子越大计算越精确
4、目标收益:r_return。投资者期望获得的收益率。
5、无风险利率:rf。指的是10年期国债收益率或者同业拆借利率。

计算步骤:
1、首先随机生成配置比例,个数为随机种子(seed)。
对应的代码为def random_weight
2、依据随机生成的配置比例,计算目标收益(r_return)下的最优配置比例
对应的代码为def cal_random_weight
3、依据随机生成的配置比例,求有效性前沿最左侧的点,即为有效性前沿的起点。
对应的代码为 self.cal_left_point
4、依据所有的最优点,绘制有效性前沿
对应的代码为 self.cal_ff
5、计算市场组合的预期收益率,预期波动率
对应的代码为 self.cal_market_weight
6、依据无风险利率,及市场组合两点连线,求出资本市场线

python代码:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import scipy.optimize as sco

plt.rcParams['font.sans-serif']=['SimHei']# 中文显示问题
plt.rcParams['axes.unicode_minus']=False# 负数显示问题classEffectiveForefront(object):"""
    有效性前沿类
    """def__init__(self, irr, cov, seed, r_return, rf):"""
        有效性前沿初始化
        :param irr: 收益率
        :param cov: 协方差
        :param seed: 随机种子数
        :param r_return: 目标收益率
        :param rf: 无风险利率
        """
        self.irr = irr
        self.rf = rf
        self.cov = cov
        self.seed = seed
        self.r_return = r_return
        self.plt =None
        self.cons =({'type':'eq','fun':lambda x: np.sum(x)-1},{'type':'eq','fun':lambda x: self.opt_return_vol(x)[0]- r_return})# 输入最优解条件
        self.bnds =tuple((0,1)for x inrange(len(irr)))# 输入边界条件
        self.frist_weight =len(irr)*[1/len(irr)]# 生成初始权重defeff_handler(self):"""
        有效性前沿计算流程
        :return: self.plt   有效性前沿及资本市场线
        :return: opt_w      目标收益率下资产配置比例
        """
        self.plt = self.random_weight()
        opt_w = self.cal_random_weight()
        left_point_return, left_point_vol = self.cal_left_point()
        self.plt.plot(left_point_vol, left_point_return,'y*', markersize=14)
        self.cal_ff(left_point_return)
        rm, vm, slope = self.cal_market_weight()
        rp_cml, vp_cml = self.cal_cml(slope)
        self.plt.plot(vp_cml, rp_cml,'b--')
        self.plt.plot(vm, rm,'g*', markersize=14)
        self.plt.show()return self.plt, opt_w

    defcal_cml(self, slope):"""
        计算资本市场线
        :param slope: 计算资本市场线斜率
        :return:
        """
        rp_cml = np.linspace(0.02,0.25)
        vp_cml =(rp_cml - self.rf)/ slope
        return rp_cml, vp_cml

    defcal_market_weight(self):"""
        市场组合的预期收益率,预期波动率
        :return:
        """# 仅设定权重之和为1的约束条件
        cons_sr =({'type':'eq','fun':lambda x: np.sum(x)-1})# 求解最优权重
        result_sr = sco.minimize(self.srmin_f, self.frist_weight, method='SLSQP', bounds=self.bnds, constraints=cons_sr)
        slope =-result_sr['fun']# 即资本市场线斜率# 市场组合的预期收益率
        rm = np.sum(irr * result_sr['x'])# 市场组合的收益率# 市场组合的波动率
        vm =(rm - self.rf)/ slope  # 市场组合的波动率return rm, vm, slope

    defcal_ff(self, left_point_return):"""
        求解有效前沿
        :param left_point_return: 最左侧点收益率
        :param left_point_vol: 最左侧点波动率
        :return:
        """
        rp_target = np.linspace(left_point_return,0.25,100)# 设定波动率列表
        vp_target =[]for r in rp_target:
            cons_new =({'type':'eq','fun':lambda x: np.sum(x)-1},{'type':'eq','fun':lambda x: self.opt_return_vol(x)[0]- r})
            result_new = sco.minimize(self.vmin_f, self.frist_weight, method='SLSQP',
                                      bounds=self.bnds, constraints=cons_new)
            vp_target.append(result_new['fun'])

        self.plt.plot(vp_target, rp_target,'r-')defcal_random_weight(self):"""
        计算最有结果权重
        :return:
        """# 求最值
        result = sco.minimize(self.vmin_f, self.frist_weight, method='SLSQP', bounds=self.bnds, constraints=self.cons)# 获取最优化结果的权重
        result['x'].round(4)
        w_df = pd.DataFrame()
        w_df['asset']=list(self.cov)
        w_df['weight']= result['x']return w_df

    defrandom_weight(self):"""
        随机生成配置比例
        :return:
        """
        rp_list =[]
        vp_list =[]# 设定投资组合各产品的均值for i in np.arange(self.seed):
            x = np.random.random(5)
            weights = x /sum(x)
            rp_list.append(np.sum(weights * self.irr))
            vp_list.append(np.sqrt(np.dot(weights, np.dot(self.cov, weights.T))))

        plt.figure(figsize=(8,6))
        plt.scatter(vp_list, rp_list)
        plt.xlim(0.12,0.28)
        plt.ylim(-0.1,0.2)
        plt.xlabel('波动率')
        plt.ylabel('预期收益率')
        plt.grid('True')return plt

    defopt_return_vol(self, w):"""
        计算最优组合的预期收益率、收益波动率
        :param w: 资产配置权重
        :return:
        """
        w = np.array(w)
        rp_opt = np.sum(w * self.irr)# 计算最优投资组合的预期收益率
        vp_opt = np.sqrt(np.dot(w, np.dot(self.cov, w.T)))# 计算最优投资组合的收益波动率return np.array([rp_opt, vp_opt])defvmin_f(self, w):return self.opt_return_vol(w)[1]defcal_left_point(self):"""
        求解有效前沿最左侧的点
        :return:
        """
        cons_vmin =({'type':'eq','fun':lambda x: np.sum(x)-1})
        result_vmin = sco.minimize(self.vmin_f, self.frist_weight, method='SLSQP',
                                   bounds=self.bnds, constraints=cons_vmin)# 求解投资组合的最左侧点的收益率
        rp_vmin = np.sum(irr * result_vmin['x'])# 求解投资组合的最左侧点的波动率
        vp_vmin = result_vmin['fun']return rp_vmin, vp_vmin

    defsrmin_f(self, w):"""
        最优投资组合夏普比率
        :param w:
        :return:
        """
        w = np.array(w)
        rp_opt = np.sum(w * irr)
        vp_opt = np.sqrt(np.dot(w, np.dot(cov, w.T)))
        SR =(rp_opt - self.rf)/ vp_opt
        return-np.array([rp_opt, vp_opt, SR])[2]# 求解最大的夏普比率就是求解负的最小值if __name__ =='__main__':
    irr = np.array([0.20,0.08,-0.17,0.06,-0.04])
    cov = pd.DataFrame({'A':[0.09,0.02,0.02,0.01,0.02],'B':[0.02,0.12,0.04,0.02,0.03],'C':[0.02,0.04,0.07,0.02,0.03],'D':[0.01,0.02,0.02,0.04,0.02],'E':[0.02,0.03,0.03,0.02,0.04]})
    seed =10000
    r_return =0.1
    rf =0.02
    ef = EffectiveForefront(irr, cov, seed, r_return, rf)
    plt, opt_w = ef.eff_handler()print('目标收益率下的配置比例为')print(opt_w)
    plt.show()

该算法的优点:
1、无需用到复杂的tensorflow模型,比较好调试参数
2、资产数较少的时候,计算非常准确。

缺点:
1、资产数较大的时候,要满足相同的精度,需要的随机种子数会指数级增加。在本案例中,五个资产用了一万随机种子。如果资产数增加为六,随机种子数要达到十万个。如果50个资产,随机种子数要达到10^50。不适合资产配置较多的投资组合。
2、大量随机生成的配置点离最优点非常远,浪费掉了。

附上python结果:

目标收益率下的配置比例为:
asset weight
0 A 0.310922
1 B 0.085937
2 C 0.000000
3 D 0.550663
4 E 0.052478

在这里插入图片描述


本文转载自: https://blog.csdn.net/tingyuanyuan/article/details/125428127
版权归原作者 GOGOTYY 所有, 如有侵权,请联系我们删除。

“使用python绘制有效性前沿”的评论:

还没有评论