如何用python实现Markowitz投资组合优化

如何用python实现Markowitz投资组合优化,第1张

多股票策略回测时常常遇到问题。

仓位如何分配?

你以为基金经理都是一拍脑袋就等分仓位了吗?

或者玩点玄乎的斐波拉契数列?

OMG,谁说的黄金比例,让我看到你的脑袋(不削才怪)!!

其实,这个问题,好多好多年前马科维茨(Markowitz)我喜爱的小马哥就给出答案——投资组合理论。

根据这个理论,我们可以对多资产的组合配置进行三方面的优化。

1找到有效前沿。在既定的收益率下使组合的方差最小。

2找到sharpe最优的组合(收益-风险均衡点)

3找到风险最小的组合

跟着我,一步两步,轻松实现。

该理论基于用均值和方差来表述组合的优劣的前提。将选取几只股票,用蒙特卡洛模拟初步探究组合的有效前沿。

通过最大Sharpe和最小方差两种优化来找到最优的资产组合配置权重参数。

最后,刻画出可能的分布,两种最优以及组合的有效前沿。

注:

文中的数据API来自量化平台聚宽,在此表示感谢。

原文见组合管理——投资组合理论(有效前沿)(包含正态检验部分)

0导入需要的包

import pandas as pd

import numpy as np

import statsmodelsapi as sm #统计运算

import scipystats as scs #科学计算

import matplotlibpyplot as plt #绘图

1选取几只感兴趣的股票

000413 东旭光电,000063 中兴通讯,002007 华兰生物,000001 平安银行,000002 万科A

并比较一下数据(2015-01-01至2015-12-31)

In[1]:

stock_set = ['000413XSHE','000063XSHE','002007XSHE','000001XSHE','000002XSHE']

noa = len(stock_set)

df = get_price(stock_set, start_date = '2015-01-01', end_date ='2015-12-31', 'daily', ['close'])

data = df['close']

#规范化后时序数据

(data/dataix[0]100)plot(figsize = (8,5))

Out[1]:

2计算不同证券的均值、协方差

每年252个交易日,用每日收益得到年化收益。计算投资资产的协方差是构建资产组合过程的核心部分。运用pandas内置方法生产协方差矩阵。

In [2]:

returns = nplog(data / datashift(1))

returnsmean()252

Out[2]:

000413XSHE 0184516

000063XSHE 0176790

002007XSHE 0309077

000001XSHE -0102059

000002XSHE 0547441

In [3]:

returnscov()252

Out[3]:

3给不同资产随机分配初始权重

由于A股不允许建立空头头寸,所有的权重系数均在0-1之间

In [4]:

weights = nprandomrandom(noa)

weights /= npsum(weights)

weights

Out[4]:

array([ 037505798, 021652754, 031590981, 006087709, 003162758])

4计算预期组合年化收益、组合方差和组合标准差

In [5]:

npsum(returnsmean()weights)252

Out[5]:

021622558669017816

In [6]:

npdot(weightsT, npdot(returnscov()252,weights))

Out[6]:

023595133640121463

In [7]:

npsqrt(npdot(weightsT, npdot(returnscov() 252,weights)))

Out[7]:

04857482232609962

5用蒙特卡洛模拟产生大量随机组合

进行到此,我们最想知道的是给定的一个股票池(证券组合)如何找到风险和收益平衡的位置。

下面通过一次蒙特卡洛模拟,产生大量随机的权重向量,并记录随机组合的预期收益和方差。

In [8]:

port_returns = []

port_variance = []

for p in range(4000):

weights = nprandomrandom(noa)

weights /=npsum(weights)

port_returnsappend(npsum(returnsmean()252weights))

port_varianceappend(npsqrt(npdot(weightsT, npdot(returnscov()252, weights))))

port_returns = nparray(port_returns)

port_variance = nparray(port_variance)

#无风险利率设定为4%

risk_free = 004

pltfigure(figsize = (8,4))

pltscatter(port_variance, port_returns, c=(port_returns-risk_free)/port_variance, marker = 'o')

pltgrid(True)

pltxlabel('excepted volatility')

pltylabel('expected return')

pltcolorbar(label = 'Sharpe ratio')

Out[8]:

6投资组合优化1——sharpe最大

建立statistics函数来记录重要的投资组合统计数据(收益,方差和夏普比)

通过对约束最优问题的求解,得到最优解。其中约束是权重总和为1。

In [9]:

def statistics(weights):

weights = nparray(weights)

port_returns = npsum(returnsmean()weights)252

port_variance = npsqrt(npdot(weightsT, npdot(returnscov()252,weights)))

return nparray([port_returns, port_variance, port_returns/port_variance])

#最优化投资组合的推导是一个约束最优化问题

import scipyoptimize as sco

#最小化夏普指数的负值

def min_sharpe(weights):

return -statistics(weights)[2]

#约束是所有参数(权重)的总和为1。这可以用minimize函数的约定表达如下

cons = ({'type':'eq', 'fun':lambda x: npsum(x)-1})

#我们还将参数值(权重)限制在0和1之间。这些值以多个元组组成的一个元组形式提供给最小化函数

bnds = tuple((0,1) for x in range(noa))

#优化函数调用中忽略的唯一输入是起始参数列表(对权重的初始猜测)。我们简单的使用平均分布。

opts = scominimize(min_sharpe, noa[1/noa,], method = 'SLSQP', bounds = bnds, constraints = cons)

opts

Out[9]:

status: 0

success: True

njev: 4

nfev: 28

fun: -11623048291871221

x: array([ -360840218e-16, 224626781e-16, 163619563e-01, -227085639e-16, 836380437e-01])

message: 'Optimization terminated successfully'

jac: array([ 181575805e-01, 540387481e-01, 818073750e-05, 103137662e+00, -160038471e-05, 000000000e+00])

nit: 4

得到的最优组合权重向量为:

In [10]:

opts['x']round(3)

Out[10]:

array([-0 , 0 , 0164, -0 , 0836])

sharpe最大的组合3个统计数据分别为:

In [11]:

#预期收益率、预期波动率、最优夏普指数

statistics(opts['x'])round(3)

Out[11]:

array([ 0508, 0437, 1162])

7投资组合优化2——方差最小

接下来,我们通过方差最小来选出最优投资组合。

In [12]:

#但是我们定义一个函数对 方差进行最小化

def min_variance(weights):

return statistics(weights)[1]

optv = scominimize(min_variance, noa[1/noa,],method = 'SLSQP', bounds = bnds, constraints = cons)

optv

Out[12]:

status: 0

success: True

njev: 7

nfev: 50

fun: 038542969450547221

x: array([ 114787640e-01, 328089742e-17, 209584008e-01, 353487044e-01, 322141307e-01])

message: 'Optimization terminated successfully'

jac: array([ 03851725 , 043591119, 03861807 , 03849672 , 038553924, 0 ])

nit: 7

方差最小的最优组合权重向量及组合的统计数据分别为:

In [13]:

optv['x']round(3)

Out[13]:

array([ 0115, 0 , 021 , 0353, 0322])

In [14]:

#得到的预期收益率、波动率和夏普指数

statistics(optv['x'])round(3)

Out[14]:

array([ 0226, 0385, 0587])

8组合的有效前沿

有效前沿有既定的目标收益率下方差最小的投资组合构成。

在最优化时采用两个约束,1给定目标收益率,2投资组合权重和为1。

In [15]:

def min_variance(weights):

return statistics(weights)[1]

#在不同目标收益率水平(target_returns)循环时,最小化的一个约束条件会变化。

target_returns = nplinspace(00,05,50)

target_variance = []

for tar in target_returns:

cons = ({'type':'eq','fun':lambda x:statistics(x)[0]-tar},{'type':'eq','fun':lambda x:npsum(x)-1})

res = scominimize(min_variance, noa[1/noa,],method = 'SLSQP', bounds = bnds, constraints = cons)

target_varianceappend(res['fun'])

target_variance = nparray(target_variance)

下面是最优化结果的展示。

叉号:构成的曲线是有效前沿(目标收益率下最优的投资组合)

红星:sharpe最大的投资组合

黄星:方差最小的投资组合

In [16]:

pltfigure(figsize = (8,4))

#圆圈:蒙特卡洛随机产生的组合分布

pltscatter(port_variance, port_returns, c = port_returns/port_variance,marker = 'o')

#叉号:有效前沿

pltscatter(target_variance,target_returns, c = target_returns/target_variance, marker = 'x')

#红星:标记最高sharpe组合

pltplot(statistics(opts['x'])[1], statistics(opts['x'])[0], 'r', markersize = 150)

#黄星:标记最小方差组合

pltplot(statistics(optv['x'])[1], statistics(optv['x'])[0], 'y', markersize = 150)

pltgrid(True)

pltxlabel('expected volatility')

pltylabel('expected return')

pltcolorbar(label = 'Sharpe ratio')

Out[16]:

你可以添加一个判断语句,如果某个点数量比较多,就给这个点设置为深色,这里设置颜色你可以参考colorbar。

另外一种策略,你需要设置中点的透明度,然后设置颜色为浅色调。如果不设置透明度,plt画图默认是没有透明度的,多个点颜色并不会叠加而只会覆盖,所以你需要设置恰当的透明度,让多个点颜色可以叠加。具体的参数你可以去“CSDN”论坛搜索。

无意中从今日头条中看到的一篇文章,可以生成简单的图表。据说一些大数据开发们也是经常用类似的图表库,毕竟有现成的,改造下就行,谁会去自己造轮子呢。

pyecharts是什么?

pyecharts 是一个用于生成 Echarts 图表的类库。Echarts 是百度开源的一个数据可视化 JS 库。用 Echarts 生成的图可视化效果非常棒, pyecharts 是为了与 Python 进行对接,方便在 Python 中直接使用数据生成图 。使用pyecharts可以生成独立的网页,也可以在flask、django中集成使用。

安装很简单:pip install pyecharts

如需使用 Jupyter Notebook 来展示图表,只需要调用自身实例即可,同时兼容 Python2 和 Python3 的 Jupyter Notebook 环境。所有图表均可正常显示,与浏览器一致的交互体验,简直不要太强大。

参考自pyecharts官方文档: >

主要就两个文件 一个是sample的名字 labelstxt

还有个放矩阵 predicttxt 两列,一列pre 二列true

放矩阵那里他会调confusion_matrix自己算,如果你自己算好了不需要算,那代码就要改

confusion_matrix介绍见

>

以上就是关于如何用python实现Markowitz投资组合优化全部的内容,包括:如何用python实现Markowitz投资组合优化、python plt可视化时,怎么实现散点图或者其他图画图时,数据中相同点越多该点画在图上的颜色越深、python可视化神器——pyecharts库等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/9284755.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-26
下一篇 2023-04-26

发表评论

登录后才能评论

评论列表(0条)

保存