700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 【Python量化】 Scipy库求解最优资产投资组合

【Python量化】 Scipy库求解最优资产投资组合

时间:2021-06-08 23:31:14

相关推荐

【Python量化】 Scipy库求解最优资产投资组合

问题导入

已知无风险利率为3%,下表包括六家公司的年度回报(文件),使用Python编制程序,求解最优投资组合。

首先我们导入相关库。

import pandas as pdimport numpy as npimport scipy.optimize as sco

一、读取excel文件,获取收益率数据

data = pd.read_excel(r'C:\Users\mi\Desktop\收益率.xlsx',index_col=0)>>>dataBMW ORACLE YOIGO SACYR BALAY APPLEYear 1.4866 0.0562 0.9641 -1.2367 0.0512 0.5075 0.2902 0.4356 0.2111 4.0332 0.2491 0.4014 0.1911 0.8831 0.3746 0.3813 0.1815 -1.6639 0.1288 0.3643 -0.2525 0.0666 0.2566 0.1564 -0.0850 0.1460 0.4236 0.4114 0.4718 0.2199 0.1068 0.0836 0.1333 -0.9241 0.3121 -0.0216 -0.0040 -0.6284 -0.3053 3.4962 -0.0368 -0.0636 0.0726 0.4273 -0.2470 0.4870 0.1204 -0.2773 -0.2030 -0.2196 0.1404 0.0862 -0.3052 -0.2985 -0.0437 0.0681 -0.0756 -1.1594 -0.1501 3.0549

二、给定权重,求组合收益率、标准差、夏普比率

# 定义无风险收益率rf = 0.03# 获取股票平均收益率returns = data.mean() # 获取股票收益率的方差协方差矩阵cov = data.cov(bias=True) # 定义资产数量number_assets = 6# 给定权重,求组合收益率、标准差、夏普比率def statistics(weights): weights = np.array(weights)pret = np.dot(weights, returns) #获取组合收益率pvol = np.sqrt(np.dot(weights.T, np.dot(cov, weights))) #获取组合标准差psharpe = (pret - rf) / pvol #获取组合夏普比率return np.array([pret, pvol, psharpe])

三、规划求解

规划求解需要用到scipy.optimize的minimize函数。函数用法如下所示。

scipy.optimize.minimize(fun, x0, args=(), method=None, jac=None, hess=None, hessp=None, bounds=None, constraints=(), tol=None, callback=None, options=None)

主要参数如下表所示:

(一)求解夏普比率最高的投资组合,并且单个资产权重均不超过20%

目标函数fun:夏普比率最大化

约束条件constraints:权重之和=1

变量边界bounds:单个权重不超过0.2

代码如下:

# 设置目标:夏普比率最大def minus_sharpe(x):return -statistics(x)[2]# 约束条件分为eq和ineq# eq表示函数结果等于0 ;ineq 表示 表达式大于等于0 # 约束条件:权重之和=1def constraint1(x):return np.sum(x) -1con1 = {'type': 'eq', 'fun': constraint1} # 定义边界约束(优化变量的上下限)bnds = tuple((None, 0.2) for x in range(number_assets)) #每个资产权重取值范围为0-0.2# 设置初始权重x0 = number_assets * [1 / number_assets]# 规划求解solution = sco.minimize(minus_sharpe,x0,method='SLSQP', bounds=bnds, constraints=con1)# 求解出权重、组合收益率、标准差、夏普比率final_weights = solution.x #权重finanl_ratio = statistics(final_weights) #组合收益率、标准差、夏普比率print(f'{final_weights[0]:.1%}投资于{data.columns[0]},{final_weights[1]:.1%}投资于{data.columns[1]},'f'{final_weights[2]:.1%}投资于{data.columns[2]},{final_weights[3]:.1%}投资于{data.columns[3]},'f'{final_weights[4]:.1%}投资于{data.columns[4]},{final_weights[5]:.1%}投资于{data.columns[5]},'f'组合收益率:{finanl_ratio[0]:.1%},组合标准差:{finanl_ratio[1]:.1%},组合夏普比率:{finanl_ratio[2]:.1%}')

结果如下:

18.5%投资于BMW,20.0%投资于ORACLE,20.0%投资于YOIGO,9.7%投资于SACYR,20.0%投资于BALAY,11.7%投资于APPLE,组合收益率:19.7%,组合标准差:22.3%,组合夏普比率:75.0%

(二)求解方差最小的投资组合

目标函数fun:方差最小化,即标准差最小化

约束条件constraints:权重之和=1

变量边界bounds:无

代码如下:

# 设置目标:方差最小def min_std(x):return statistics(x)[1]# 约束条件:权重之和=1def constraint1(x):return np.sum(x) -1con1 = {'type': 'eq', 'fun': constraint1} # 设置初始权重x0 = number_assets * [1 / number_assets]# 规划求解solution = sco.minimize(min_std,x0,method='SLSQP',constraints=con1)# 求解出权重、组合收益率、标准差、夏普比率final_weights = solution.x #权重finanl_ratio = statistics(final_weights) #组合收益率、标准差、夏普比率print(f'{final_weights[0]:.1%}投资于{data.columns[0]},{final_weights[1]:.1%}投资于{data.columns[1]},'f'{final_weights[2]:.1%}投资于{data.columns[2]},{final_weights[3]:.1%}投资于{data.columns[3]},'f'{final_weights[4]:.1%}投资于{data.columns[4]},{final_weights[5]:.1%}投资于{data.columns[5]},'f'组合收益率:{finanl_ratio[0]:.1%},组合标准差:{finanl_ratio[1]:.1%},组合夏普比率:{finanl_ratio[2]:.1%}')

结果如下:

3.6%投资于BMW,10.1%投资于ORACLE,18.5%投资于YOIGO,3.4%投资于SACYR,56.0%投资于BALAY,8.4%投资于APPLE,组合收益率:14.9%,组合标准差:18.1%,组合夏普比率:65.9%

(三)求解方差最小的投资组合,组合收益率为30%

目标函数fun:方差最小化,即标准差最小化

约束条件constraints:1、权重之和=1;2、组合收益率=0.3

代码如下:

#设置目标:方差最小def min_std(x):return statistics(x)[1]# 约束条件1:权重之和=1def constraint1(x):return np.sum(x) -1# 约束条件2:组合收益=0.3def constraint2(x):return statistics(x)[0]-0.3con1 = {'type': 'eq', 'fun': constraint1} con2 = {'type': 'eq', 'fun': constraint2} cons = (con1,con2)# 设置初始权重x0 = number_assets * [1 / number_assets]# 规划求解solution = sco.minimize(min_std,x0,method='SLSQP',constraints=cons)# 求解出权重、组合收益率、标准差、夏普比率final_weights = solution.x #权重finanl_ratio = statistics(final_weights) #组合收益率、标准差、夏普比率print(f'{final_weights[0]:.1%}投资于{data.columns[0]},{final_weights[1]:.1%}投资于{data.columns[1]},'f'{final_weights[2]:.1%}投资于{data.columns[2]},{final_weights[3]:.1%}投资于{data.columns[3]},'f'{final_weights[4]:.1%}投资于{data.columns[4]},{final_weights[5]:.1%}投资于{data.columns[5]},'f'组合收益率:{finanl_ratio[0]:.1%},组合标准差:{finanl_ratio[1]:.1%},组合夏普比率:{finanl_ratio[2]:.1%}')

结果如下:

47.1%投资于BMW,66.5%投资于ORACLE,2.8%投资于YOIGO,22.3%投资于SACYR,-57.0%投资于BALAY,18.3%投资于APPLE,组合收益率:30.0%,组合标准差:42.9%,组合夏普比率:63.0%

(四)求解收益率最高的投资组合,组合标准差为40%。

目标函数fun:组合收益率最大化

约束条件constraints:1、权重之和=1;2、组合标准差=0.4

代码如下:

# 设置目标:收益率最大化def minus_return(x):return -statistics(x)[0]# 约束条件1:权重之和=1def constraint1(x):return np.sum(x) -1# 约束条件2:组合标准差=0.4def constraint2(x):return statistics(x)[1]-0.4con1 = {'type': 'eq', 'fun': constraint1} con2 = {'type': 'eq', 'fun': constraint2} cons = (con1,con2)# 设置初始权重x0 = number_assets * [1 / number_assets]# 规划求解solution = sco.minimize(minus_return,x0,method='SLSQP',constraints=cons)# 求解出权重、组合收益率、标准差、夏普比率final_weights = solution.x #权重finanl_ratio = statistics(final_weights) #组合收益率、标准差、夏普比率print(f'{final_weights[0]:.1%}投资于{data.columns[0]},{final_weights[1]:.1%}投资于{data.columns[1]},'f'{final_weights[2]:.1%}投资于{data.columns[2]},{final_weights[3]:.1%}投资于{data.columns[3]},'f'{final_weights[4]:.1%}投资于{data.columns[4]},{final_weights[5]:.1%}投资于{data.columns[5]},'f'组合收益率:{finanl_ratio[0]:.1%},组合标准差:{finanl_ratio[1]:.1%},组合夏普比率:{finanl_ratio[2]:.1%}')

结果如下:

43.5%投资于BMW,61.8%投资于ORACLE,4.1%投资于YOIGO,20.8%投资于SACYR,-47.7%投资于BALAY,17.5%投资于APPLE,组合收益率:28.8%,组合标准差:40.0%,组合夏普比率:64.4%

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。