选择了四支股票进行投资组合优化练习
[‘智飞生物’,‘伊利股份’,‘贵州茅台’,‘顺丰控股’]

结果展示

股票:[‘智飞生物’,‘伊利股份’,‘贵州茅台’,‘顺丰控股’]

情形 报酬率 标准差 夏普指数 权重
夏普指数最大 0.300 0.288 1.044 [0.179, 0.0165, 0.703, 0.102]
标准差最小 0.272 0.274 0.994 [0.112, 0.260, 0.488, 0.140]
市场组合 0.303 0.290 0.906 [0.187, 0. , 0.722, 0.091]

好奇操作(前菜)

获取股票数据

import akshare as ak
import numpy as np
import pandas as pd
import math
import scipy.optimize as sco
import scipy.interpolate as spi
from matplotlib import pyplot as plt
plt.rcParams['font.family']=['DengXian']
# plt.style.use('seaborn')
name = ['智飞生物','伊利股份','贵州茅台','顺丰控股']
sym_list = ['sz300122','sh600887' , 'sh600519','sz002352']
stock_close_price_df = pd.DataFrame(ak.stock_zh_a_daily(symbol='sz300122', start_date="20100101", end_date="20210315", adjust="qfq")['close'])
for i in range(1 , len(sym_list)):cols = name[i]stock_close_price_df[f'{cols}'] = ak.stock_zh_a_daily(symbol=sym_list[i], start_date="20100101", end_date="20210315", adjust="qfq")['close']
stock_close_price_df.columns = name
stock_close_price_df = stock_close_price_df.dropna()
stock_close_price_df.head(10)
智飞生物 伊利股份 贵州茅台 顺丰控股
date
2010-09-28 9.15 5.76 107.15 8.53
2010-09-29 9.20 5.63 104.88 8.11
2010-09-30 9.58 5.72 105.86 8.20
2010-10-08 9.61 5.95 108.88 8.41
2010-10-11 9.39 5.58 105.28 8.33
2010-10-12 9.18 5.35 104.53 8.52
2010-10-13 9.31 5.41 101.01 8.52
2010-10-14 9.06 5.23 99.41 8.20
2010-10-15 8.80 5.05 100.37 8.00
2010-10-18 8.70 5.12 101.91 7.97

绘制相对股价变动趋势

stock_base_10_df = stock_close_price_df / stock_close_price_df.iloc[0] * 1
stock_base_10_df.plot(figsize = (10,6),cmap='coolwarm')
plt.legend()
<matplotlib.legend.Legend at 0x1c8e943fc10>

计算每一支股票的累计收益率

df = stock_close_price_df.copy()
rets = np.log( df / df.shift(1) ).dropna()
rets
智飞生物 伊利股份 贵州茅台 顺丰控股
date
2010-09-29 0.005450 -0.022828 -0.021413 -0.050491
2010-09-30 0.040474 0.015859 0.009301 0.011036
2010-10-08 0.003127 0.039422 0.028129 0.025287
2010-10-11 -0.023159 -0.064202 -0.033623 -0.009558
2010-10-12 -0.022618 -0.042092 -0.007149 0.022553
... ... ... ... ...
2021-03-09 -0.116564 -0.047597 -0.011809 -0.011709
2021-03-10 0.046926 0.012309 0.016903 0.021000
2021-03-11 0.026254 0.022646 0.038825 0.006074
2021-03-12 0.064774 0.004570 -0.010800 -0.007054
2021-03-15 -0.048183 -0.030867 -0.025267 -0.026039

2376 rows × 4 columns

rets.cumsum().plot(figsize = (10,6), cmap='coolwarm')
<AxesSubplot:xlabel='date'>

绘制平均年化收益率直方图

看基本形态是否复合常态分布。

rets.hist(bins=40, figsize=(10, 10))
array([[<AxesSubplot:title={'center':'智飞生物'}>,<AxesSubplot:title={'center':'伊利股份'}>],[<AxesSubplot:title={'center':'贵州茅台'}>,<AxesSubplot:title={'center':'顺丰控股'}>]], dtype=object)

计算平均年化收益率

rets.mean() * 252
智飞生物    0.304579
伊利股份    0.200878
贵州茅台    0.309095
顺丰控股    0.249264
dtype: float64

计算年化收益率方差

rets.var() * 252
智飞生物    0.248457
伊利股份    0.134778
贵州茅台    0.103541
顺丰控股    0.215159
dtype: float64

计算年化收益率协方差

rets.cov() * 252 #年化收益率协成对方差
智飞生物 伊利股份 贵州茅台 顺丰控股
智飞生物 0.248457 0.053033 0.041325 0.093816
伊利股份 0.053033 0.134778 0.054290 0.054185
贵州茅台 0.041325 0.054290 0.103541 0.041356
顺丰控股 0.093816 0.054185 0.041356 0.215159

投资组合机会集

设置权重


nums = len(name)
weights = np.random.random(nums)
weights /= np.sum(weights)
weights.sum()
1.0
#投资组合的年化收益率
prets = np.sum((weights * rets.mean()) * 252)
prets
0.2898256347004005
#投资组合的年化标准差
pstd = math.sqrt(np.dot(weights.T, np.dot(rets.cov() * 252, weights)))
pstd
0.2944639083515521

定义生成年化收益率&年化标准差函数


def gen_prets(weights):return np.sum((weights * rets.mean()) * 252)
def gen_pstd(weights):return math.sqrt(np.dot(weights.T, np.dot(rets.cov() * 252, weights)))

利用蒙特卡洛法生成20000个投资组合

r = 0.04
prets = []
pstd = []
for i in range(20000):weights = np.random.random(nums)weights /= np.sum(weights)prets.append(gen_prets(weights))pstd.append(gen_pstd(weights))
prets = np.array(prets)
pstd = np.array(pstd)

绘制投资组合机会集图

plt.figure(figsize = (10 , 6))
plt.scatter(pstd , prets , c = (prets) / pstd,marker = 'o', cmap = 'coolwarm')
plt.xlabel('expected volatility')
plt.ylabel('expected return')
plt.colorbar(label = 'Sharpe ratio')
<matplotlib.colorbar.Colorbar at 0x1c8e9308520>

求投资组合最优解

夏普指数最大

#定义夏普指数函数
def mini_sharpe(weights):return - gen_prets(weights) / gen_pstd(weights)
cons = ({'type': 'eq','fun': lambda x: np.sum(x) - 1})  #权重之和 =0
bnds = tuple((0, 1) for x in range(nums)) #0 <= wi <= 1
eweights = np.array(nums * [1. / nums,])  #给目标函数一个起始值
opts = sco.minimize(mini_sharpe, eweights, method='SLSQP', bounds=bnds, constraints=cons)  #最大化夏普指数
opts
     fun: -1.0437425848628836jac: array([ 2.88799405e-04, -8.74847174e-05, -1.06215477e-04,  2.37122178e-04])message: 'Optimization terminated successfully'nfev: 30nit: 6njev: 6status: 0success: Truex: array([0.17919435, 0.01648604, 0.70201677, 0.10230284])
#全局最优解weight下的报酬率
gen_prets(opts['x'])
0.3003805392456562
#全局最优解weight下的标准差
gen_pstd(opts['x'])
0.2877917827652085
gen_prets(opts['x']) / gen_pstd(opts['x'])
1.0437425848628836

投资组合标准差最小

#最小化投资组合标准差(波动度)
optv = sco.minimize(gen_pstd, eweights, method='SLSQP', bounds=bnds, constraints=cons)
optv
     fun: 0.2739024864937134jac: array([0.27394041, 0.27389679, 0.27398745, 0.27358665])message: 'Optimization terminated successfully'nfev: 35nit: 7njev: 7status: 0success: Truex: array([0.11257167, 0.25950405, 0.48784983, 0.14007445])
#最小std情况下weight的报酬率
gen_prets(optv['x'])
0.27212282631267554
gen_pstd(optv['x'])
0.2739024864937134
gen_prets(optv['x']) / gen_pstd(optv['x'])
0.9935025774909176

市场组合

求解绘制投资组合有效集

#限制条件下的效率前缘
cons = ({'type': 'eq','fun': lambda x: gen_prets(x) - fret}, # wi要使 指定的fret = 该wi下的pret{'type': 'eq','fun': lambda x: np.sum(x) - 1})
bnds = tuple((0, 1) for x in eweights ) frets = np.linspace(0.26, 0.31, 50)
fstd = []
for fret in frets:optf = sco.minimize(gen_pstd, eweights, method='SLSQP', bounds=bnds, constraints=cons) fstd.append(optf['fun'])
fstd = np.array(fstd)
fstd
array([0.27649069, 0.276074  , 0.27569353, 0.27534867, 0.27504108,0.27476995, 0.2745355 , 0.27433727, 0.27417642, 0.27405254,0.27396599, 0.27391567, 0.27390281, 0.27392701, 0.27398825,0.2740865 , 0.27422174, 0.2743939 , 0.27460292, 0.2748487 ,0.27513115, 0.27545017, 0.27580561, 0.27619735, 0.27662522,0.27708906, 0.2775887 , 0.27812393, 0.27869456, 0.27930036,0.27994112, 0.28061658, 0.28132651, 0.28207063, 0.28284812,0.28365976, 0.28450475, 0.28538281, 0.28629362, 0.28723688,0.28821226, 0.28921996, 0.29028203, 0.29152197, 0.29295427,0.29457613, 0.29638442, 0.29837576, 0.3170859 , 0.32177772])
plt.figure(figsize = (10 , 6))
plt.scatter(pstd , prets , c = (prets) / pstd,marker = '.', cmap = 'coolwarm')
plt.plot(fstd , frets , 'b')
plt.plot(gen_pstd(opts['x']), gen_prets(opts['x']),'y*', markersize=15.0)
plt.plot(gen_pstd(optv['x']), gen_prets(optv['x']),'r*', markersize=15.0)
plt.xlabel('expected volatility')
plt.ylabel('expected return')
plt.colorbar(label = 'Sharpe ratio')

绘制资本市场线

使用样条插值法拟合有效集曲线


ind = np.argmin(fstd)
fstd = fstd[ind:]
frets = frets[ind:]
tck =  spi.splrep(fstd, frets, k=3)
def f(x):return spi.splev(x, tck , der = 0)
def df(x):return spi.splev(x, tck , der = 1)

联立求解资本市场线方程参数

def equations(p):equa1 = r - p[0]  #a = requa2 = r + p[1] * p[2] - f(p[2]) # a + bx = f(x)equa3 = df(p[2]) - p[1]  # b = f'(x)return equa1,equa2,equa3
opt = sco.fsolve(equations, [0.04, 1.04, 0.28])  #给初始值
opt
array([0.04      , 0.90552348, 0.29025658])
equations(opt)
(0.0, 9.405831669084819e-11, 9.609891771233947e-10)
opt[0] + opt[1] * opt[2]
0.30283414400786657

绘制资本市场线

plt.figure(figsize = (10 , 6))
plt.scatter(pstd , prets , c = (prets - r) / pstd,marker = '.', cmap = 'coolwarm')
plt.plot(fstd , frets , 'b')
x = np.linspace(0.24 , 0.38)
plt.plot(x , opt[0] + opt[1] * x, 'r', lw=1.5)
plt.plot(opt[2], f(opt[2]),'y*', markersize=15.0)
plt.axhline(0.20, color='k', ls='--', lw=2.0)
plt.axvline(0.25, color='k', ls='--', lw=2.0)
plt.xlabel('expected volatility')
plt.ylabel('expected return')
plt.colorbar(label = 'Sharpe ratio')

求解最佳组合的权重

cons = ({'type': 'eq', 'fun': lambda x:  gen_prets(x) - f(opt[2])},{'type': 'eq', 'fun': lambda x:  np.sum(x) - 1})
res = sco.minimize(gen_pstd, eweights, method='SLSQP',bounds=bnds, constraints=cons)
res['x'].round(3)
array([0.187, 0.   , 0.722, 0.091])
gen_prets(res['x'])
0.30283414391081653
gen_pstd(res['x'])
0.2902563195400728
(gen_prets(res['x']) - r ) / gen_pstd(res['x'])
0.9055242770503388

【python for finance】 Portfolio Optimization 投资组合优化相关推荐

  1. 量子退火Python实战(3):投资组合优化(Portfolio) MathorCup2023特供PyQUBO教程

    文章目录 前言 一.什么是投资组合优化? 二.投资组合优化建模 1. 目标函数:回报 2.约束函数:风险 3.最终优化目标函数 三.基于PyQUBO实现 1. 获取数据 2. 数据处理 3. 目标函数 ...

  2. python n个list如何组成矩阵_如何用马科维茨投资组合优化法和现代资产组合理论生成交易策略?...

    全文共6852字,预计学习时长14分钟 图源:pixabay 本文旨在展示如何用马科维茨(Markowitz)的投资组合优化法和现代资产组合理论(MPT)来生成交易策略. 本文首先对均值-方差优化法进 ...

  3. 资产组合优化原理与实例 Portfolio Optimization

    在前一片文章(SkLearn 对上证50成分股聚类 )中简单介绍了投资组合优化理论,在此进一步介绍下该理论,以及如何进行Portfolio Optimization. 1. Markowitz投资组合 ...

  4. python有效边界_Markowitz有效边界和投资组合优化基于Python(附代码)

    原标题:Markowitz有效边界和投资组合优化基于Python(附代码) 本期作者:Bernard Brenyah 本期翻译:Barry 未经授权,严禁转载 哈里马科维茨对金融和经济学的世界的贡献是 ...

  5. Python--【研究】如何用python实现Markowitz投资组合优化

    来源:https://zhuanlan.zhihu.com/p/20604930?refer=quantstory 多股票策略回测时常常遇到问题. 仓位如何分配? 你以为基金经理都是一拍脑袋就等分仓位 ...

  6. 利用Python进行「基金投资组合优化」(一)

    文章目录 引言 主要思路 投资组合 现代投资组合理论(MPT) 波动率 协方差 权重分配 投资组合期望回报 投资组合方差 代码实践 获取基金净值的变化情况 计算基金的波动率 比较基金之间的相关性 计算 ...

  7. 利用python构建马科维茨_使用CVXOPT包实现马科维茨投资组合优化

    在真实股票市场的回测 上面的例子特别有趣但不是很适用. 接下来,我们将演示如何在BigQuant中创建一个策略. 本实验的目的是验证在一个买入固定5只股票的多头组合,利用马科维茨组合优化确定的投资组合 ...

  8. python粒子群喷发_Python基于粒子群优化的投资组合优化研究

    原文链接:http://tecdat.cn/?p=6811 我今年的研究课题是使用粒子群优化(PSO)的货币进位交易组合优化.在本文中,我将介绍投资组合优化并解释其重要性.其次,我将演示粒子群优化如何 ...

  9. python 组合优化_python基于粒子群优化的投资组合优化研究

    我今年的研究课题是使用粒子群优化(PSO)的货币进位交易组合优化.在本文中,我将介绍投资组合优化并解释其重要性.其次,我将演示粒子群优化如何应用于投资组合优化.第三,我将解释套利交易组合,然后总结我的 ...

  10. python基于粒子群优化的投资组合优化

    我今年的研究课题是使用粒子群优化(PSO)的货币进位交易组合优化.在本文中,我将介绍投资组合优化并解释其重要性.其次,我将演示粒子群优化如何应用于投资组合优化.第三,我将解释套利交易组合,然后总结我的 ...

最新文章

  1. [svc]磁盘接口与RAID
  2. 零基础自学python的app-零基础转行Python,为什么有些人自学几天就放弃了?
  3. 面试必备之:MFC socket编程(浅出+深度:服务端和客户端端口问题)
  4. PowerSploit-CodeExecution(代码执行)脚本渗透实战
  5. C#中break,continue,return,,goto,throw的区别(转)
  6. 补码(为什么按位取反再加一):告诉你一个其实很简单的问题(转自醍醐灌顶)...
  7. WBOLT热门关键词推荐插件v1.3.0 Pro 绿色版
  8. java对焦_【Camera】手机相机自动对焦的3种方式及原理
  9. 吴恩达机器学习7——支持向量机SVM
  10. Android服务函数远程调用源码分析
  11. Java软件低级错误:短路运算和非短路运算的区别
  12. oracle中trim,ltrim,rtrim函数用法
  13. 微pe添加网络组件_(已解决)干掉peset后如何启动PE的网络组件?
  14. Bandicam软件及安装教程(详细)
  15. Windows系统封装(四)正式封装和测试。
  16. 開關(switch)規格中,SPDT, DPDT, 3PDT, 4PDT是什麼意思?
  17. 爱心~~~红色的~~~小爱心组成的大爱心~~~
  18. 隔壁老王的女朋友都能学会的ELK实战之elasticsearch
  19. 解决笔记本连接wifi提示无法连接这个网络问题
  20. Rest风格请求方式

热门文章

  1. windbg调试命令9(dt、d)
  2. 微信视频号视频如何下载保存?教你批量下载保存视频号视频到手机相册
  3. python---之struck.pack()和struct.unpack
  4. C语言四分位数Quartile算法(附完整源码)
  5. spec文件知识整理
  6. adb 无线wifi调试
  7. Android Banner Indicator 轮播图指示器
  8. [Spark调优]--TaskSetManager的有效Locality Levels
  9. SCAR:Scalable Consensus Algorithm一种可伸缩共识算法
  10. 普林斯顿大学计算机科学排名,普林斯顿大学研究生计算机系统专业排名