多股票策略回测时常常遇到问题。
仓位如何分配?
你以为基金经理都是一拍脑袋就等分仓位了吗?
或者玩点玄乎的斐波拉契数列?
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库等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)