pandas_样本(资产)组合找最优资产组合(CML)

目录

概念

代码


概念

投资者一般会把一部分资产购买无风险资产,其余用于购买风险资产。无风险资产在收益与风险的图中表现在Var为0的竖线上

所以,可以看出,寻找最优投资组合也是寻找最大夏普比率投资组合

代码

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

df_004 = pd.read_csv('600004.csv',encoding='utf-8')
df_015 = pd.read_csv('600015.csv',encoding='utf-8')
df_023 = pd.read_csv('600023.csv',encoding='utf-8')
df_033 = pd.read_csv('600033.csv',encoding='utf-8')
df_343 = pd.read_csv('600343.csv',encoding='utf-8')
df_346 = pd.read_csv('600346.csv',encoding='utf-8')
df_183 = pd.read_csv('600183.csv',encoding='utf-8')
df_1398 = pd.read_csv('601398.csv',encoding='utf-8')
df_050 = pd.read_csv('600050.csv',encoding='utf-8')
df_000 = pd.read_csv('600000.csv',encoding='utf-8')

df_004['ret_004'] = df_004['closePrice'].pct_change()
df_004 = df_004.loc[:,['tradeDate','ret_004']]
df_015['ret_015'] = df_015['closePrice'].pct_change()
df_015 = df_015.loc[:,['tradeDate','ret_015']]
df_023['ret_023'] = df_023['closePrice'].pct_change()
df_023 = df_023.loc[:,['tradeDate','ret_023']]
df_033['ret_033'] = df_033['closePrice'].pct_change()
df_033 = df_033.loc[:,['tradeDate','ret_033']]
df_343['ret_343'] = df_343['closePrice'].pct_change()
df_343 = df_343.loc[:,['tradeDate','ret_343']]
df_346['ret_346'] = df_346['closePrice'].pct_change()
df_346 = df_346.loc[:,['tradeDate','ret_346']]
df_183['ret_183'] = df_183['closePrice'].pct_change()
df_183 = df_183.loc[:,['tradeDate','ret_183']]
df_1398['ret_1398'] = df_1398['closePrice'].pct_change()
df_1398 = df_1398.loc[:,['tradeDate','ret_1398']]
df_050['ret_050'] = df_050['closePrice'].pct_change()
df_050 = df_050.loc[:,['tradeDate','ret_050']]
df_000['ret_000'] = df_000['closePrice'].pct_change()
df_000 = df_000.loc[:,['tradeDate','ret_000']]

ten_df = pd.merge(df_004,df_015,on='tradeDate')
ten_df = pd.merge(ten_df,df_023,on='tradeDate')
ten_df = pd.merge(ten_df,df_033,on='tradeDate')
ten_df = pd.merge(ten_df,df_343,on='tradeDate')
ten_df = pd.merge(ten_df,df_346,on='tradeDate')
ten_df = pd.merge(ten_df,df_183,on='tradeDate')
ten_df = pd.merge(ten_df,df_1398,on='tradeDate')
ten_df = pd.merge(ten_df,df_050,on='tradeDate')
ten_df = pd.merge(ten_df,df_000,on='tradeDate')
ten_df.dropna(inplace=True)
ten_df['tradeDate'] = pd.to_datetime(ten_df['tradeDate'])
ten_df.set_index('tradeDate',inplace=True)
ten_df.head()

def annualize_rets(returns,n_periods):
    '''
    给定一系列的收益率和期数,算出年化收益率
    '''
    # 每一期的平均收益
    r_periodic_mean = ((1+returns).prod())**(1/returns.shape[0])-1
    return (1+r_periodic_mean)**n_periods-1

def annualize_std(returns,n_periods):
    '''
    给定一系列的收益率,算出年化的标准差
    '''
    return returns.std()*np.sqrt(n_periods)

def portfolio_return(weights,returns):
    '''
    计算投资组合收益率,weights和returns需要矩阵形式
    weights是组合资产的权重
    returns是组合中的资产年化收益率
    '''
    return weights.T @ returns

def portfolio_vol(weights,covmat):
    '''
    计算投资组合风险(波动率),weights和covmat需要矩阵形式
    covmat代表的是协方差矩阵
    '''
    return np.sqrt(weights.T @ covmat @ weights)

def minimize_vol(target_return,annual_rets,covmat):
    '''
    最小方差边界函数
    target_return 为客户所要求的收益率水平
    annual_rets 代表组合中的资产的年化收益率
    covmat 代表资产之间的协方差矩阵
    '''
    from scipy.optimize import minimize
    n = annual_rets.shape[0]
    init_guess = np.repeat(1/n,n)
    bounds = ((0.0,1.0),)*n #每个资产的权重在0~1之间
    weights_sum_to_1 = {'type':'eq','fun': lambda weights:np.sum(weights)-1}
    return_is_target = {'type':'eq','args':(annual_rets,),'fun': lambda weights,annual_rets: portfolio_return(weights,annual_rets)-target_return}
    weights = minimize(portfolio_vol,init_guess,args=(covmat,),method='SLSQP',bounds=bounds,constraints=(weights_sum_to_1,return_is_target))
    return weights.x

def plot_ef(n_points,rets,cov):
    '''
    画出有效边界的函数
    n_points 需要画的点的数量
    rets 组合资产的年化收益率
    cov 代表资产之间的协方差矩阵
    '''
    prets = []
    pvols = []
    target_rs = np.linspace(rets.min(),rets.max(),n_points)
    weights = [minimize_vol(target_returns,rets,cov) for target_returns in target_rs]
    for w in weights:
        prets.append(portfolio_return(w,rets))
        pvols.append(portfolio_vol(w,cov))
    ef = pd.DataFrame({'R':prets,'Var':pvols})
    return ef.plot.line(x='Var',y='R',style='.-')

def get_gmvp(covmat):
    '''
    寻找全局最小方差点
    covmat 代表资产之间的协方差矩阵
    '''
    from scipy.optimize import minimize
    n = covmat.shape[0]
    init_guess = np.repeat(1/n,n)
    bounds = ((0.0,1.0),)*n #每个资产的权重在0~1之间
    weights_sum_to_1 = {'type':'eq','fun': lambda weights:np.sum(weights)-1}
    weights = minimize(portfolio_vol,init_guess,args=(covmat,),method='SLSQP',bounds=bounds,constraints=(weights_sum_to_1))
    return weights.x

annual_rets = annualize_rets(ten_df,252)
annual_vols = annualize_std(ten_df,252)
annual_cov = np.cov(ten_df,rowvar=False)*252

gmvp_10samples = get_gmvp(annual_cov)
ret_gmvp_10samples = portfolio_return(gmvp_10samples,annual_rets)
vol_gmvp_10samples = portfolio_vol(gmvp_10samples,annual_cov)

ax = plot_ef(30,annual_rets,annual_cov)
ax.plot(vol_gmvp_10samples,ret_gmvp_10samples,color='red',marker="*",markersize=20)

 

 求最大夏普比率函数

def maximum_sharp(riskfree_rate,rets,covmat):
    '''
    该函数返回最优投资组合,该组合为切线组合,夏普比率达到当前最大值
    riskfree_rate 为无风险利率
    rets 代表组合中的资产的年化收益率
    covmat 代表资产之间的年化协方差矩阵
    '''
    from scipy.optimize import minimize
    n = rets.shape[0]
    init_guess = np.repeat(1/n,n)
    bounds = ((0.0,1.0),)*n #每个资产的权重在0~1之间
    weights_sum_to_1 = {'type':'eq','fun': lambda weights:np.sum(weights)-1}
    def neg_sharpe(weights,riskfree_rate,rets,covmat):
        '''
        为了寻找最大夏普比率,该函数定义负夏普比率,以最终返回其最小值
        '''
        r = portfolio_return(weights,rets)
        v = portfolio_vol(weights,covmat)
        return -(r-riskfree_rate)/v
    weights = minimize(neg_sharpe,init_guess,args=(riskfree_rate,rets,covmat),method='SLSQP',bounds=bounds,constraints=(weights_sum_to_1))
    return weights.x

# 寻找最优切线投资组合
rf=0.0135
# 寻找最优切线投资组合的权重
weights_maxsharp = maximum_sharp(rf,annual_rets,annual_cov)
weights_maxsharp

# 计算最优投资组合的收益与风险
r_maxsharp = portfolio_return(weights_maxsharp,annual_rets)
v_maxsharp = portfolio_vol(weights_maxsharp,annual_cov)

# 将最小方差边界,GMVP组合和最大夏普比率投资组合一起画图
ax = plot_ef(30,annual_rets,annual_cov)
ax.plot(vol_gmvp_10samples,ret_gmvp_10samples,color='red',marker="*",markersize=20)
# 绘制资本市场线 CML
cml_x = [0,v_maxsharp]
cml_y = [rf,r_maxsharp]
ax.plot(cml_x,cml_y,color='green',marker='o')
ax.set_xlim(left=0.0)

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值