繁簡切換您正在訪問的是FX168財經網,本網站所提供的內容及信息均遵守中華人民共和國香港特別行政區當地法律法規。

FX168财经网>人物频道>帖子

均值方差模型在投资组合中的简单应用

作者/我就是英雄 2019-05-10 05:04 0 来源: FX168财经网人物频道

第一部分 一个示例

  • 市场有资产A和资产B,收益率分别为RA和RB,收益率的期望值E(RA)、E(RB)分别为8%和15%,标准差RA、RB分别为12%和25%。当两资产的相关系数分别为-1、-0.5、0、 0.5、 1时,不同的投资比例下投资组合的期望收益率及风险分别是如何变化的?(示例来自于《量化投资以Python为工具》)
#模拟生成两个的权重
def weight(n):
    w = np.random.random(n)
    return w/sum(w)
#定义计算收益、风险、夏普率的函数
def portfolio_test(w):
    r1,r2 = 0.08,0.12
    sigma1,sigma2 = 0.12,0.25
    rho1,rho2,rho3,rho4,rho5 = -1,-0.5,0,0.5,1
    p_mean = r1*w[0] r2*w[1]
    p_var1 = (w[0]**2)*(sigma1**2) (w[1]**2)*(sigma2**2) 2*w[0]*w[1]*rho1*sigma1*sigma2
    p_var2 = (w[0]**2)*(sigma1**2) (w[1]**2)*(sigma2**2) 2*w[0]*w[1]*rho2*sigma1*sigma2
    p_var3 = (w[0]**2)*(sigma1**2) (w[1]**2)*(sigma2**2) 2*w[0]*w[1]*rho3*sigma1*sigma2
    p_var4 = (w[0]**2)*(sigma1**2) (w[1]**2)*(sigma2**2) 2*w[0]*w[1]*rho4*sigma1*sigma2
    p_var5 = (w[0]**2)*(sigma1**2) (w[1]**2)*(sigma2**2) 2*w[0]*w[1]*rho5*sigma1*sigma2
    p_sigma1 = np.sqrt(p_var1)
    p_sigma2= np.sqrt(p_var2)
    p_sigma3 = np.sqrt(p_var3)
    p_sigma4 = np.sqrt(p_var4)
    p_sigma5 = np.sqrt(p_var5)
    return w[0],w[1],p_mean,p_sigma1,p_sigma2,p_sigma3,p_sigma4,p_sigma5
df_value =np.column_stack([portfolio_test(weight(2)) for i in range(10)]) #产生随机组合
df = pd.DataFrame(df_value.T,columns = ['A资产比例','B资产比例','r_期望收益','p_rho1','p_rho2','p_rho3','p_rho4','p_rho5'])
  • 随机取了十组权重,计算组合收益和风险,其中A、B资产的权重之和为1,
    wA wB=1wA wB=1
    组合收益为 R=wARA wBRBR=wARA wBRB
    组合风险为2.png
    计算之后结果如下图所示
    1.png

  • 给出的10组测试中,每组组合权重相同的情况下,预期收益是一样的,组合风险从1到5逐渐增加,即两资产的相关系数越高,风险越大,下图是十组收益在不同相关系数下的标准差值,可以清楚的看到-1最小而1最大
    3.png

  • 其实如果存在两个标的收益相关系数为-1,则组合收益理论上相互抵消了,所以在实际当中,能够寻找到低相关且都有正收益的标的就是极好的,分散化投资降低风险,其实就是在寻找相关度低的资产作为投资标的,在保证期望收益损失较小的情况下最大化的降低组合风险。

  • 在这个例子中,我们取更多组的权重进行模拟,来观察下组合的期望收益和组合风险的变化情况

    df_value1 =np.column_stack([portfolio_test(weight(2)) for i in range(200)]) #产生随机组合
    df1= pd.DataFrame(df_value1.T,columns = ['A资产比例','B资产比例','p_mean','p_rho1','p_rho2','p_rho3','p_rho4','p_rho5'])
    plt.scatter(df1['p_rho1'],df1['p_mean'],marker = 'o')
    plt.scatter(df1['p_rho2'],df1['p_mean'],marker = 'o')
    plt.scatter(df1['p_rho3'],df1['p_mean'],marker = 'o')
    plt.scatter(df1['p_rho4'],df1['p_mean'],marker = 'o')
    plt.scatter(df1['p_rho5'],df1['p_mean'],marker = 'o')
    

    4.png

  • 在不同的相关系数下,投资组合标准差随投资比例变动的情况呈现如上关系,横轴为组合标准差值,纵轴为组合期望收益值,除去最外面和最里边极端 -1的相关系数下的线性关系外,组合的预期收益和风险呈现的样子就是著名的Markowitz均值-方差模型里面的子弹图雏形了。

第二部分 均值方差模型

  • 接下来,在HS300中取5只近一年收益为正的股票,来看下组合的预期收益和组合风险之间的关系
  • 获取HS300中近一年收益超过基银行存款的前5只股票
  • 获取股票近一年收益数据
  • 构建5只股票的组合,计算收益、方差、夏普率
  • 蒙特卡洛模拟(其实就是随机生成大量的组合记录计算结果)
  • 找出风险最小的组合权重、找出夏普率最大的组合权重
  • 找出有效前沿
可以参考之前的一篇文章 https://www.joinquant.com/post/702
  • step1 获取HS300中近一年收益超过基银行存款的前5只股票
#选出几个标的数据,进行演示计算
#这里选取HS300里面近一年涨幅大于4%的5只股票
stock_list = get_index_stocks('000300.XSHG')
pool = []
for i in stock_list:
    price_df = get_price(i,start_date='2017-9-1',end_date='2018-9-1',fields=['close'])
    pct = price_df['close'].values[-1]/price_df['close'].values[0]
    if pct>1.04:
        pool.append(i)
    if len(pool)==5:
        break
pool
注意:这里为了展示效果,后面的数据都是选取的一年前的数据进行的模拟
  • step2 获取HS300中近一年收益超过基银行存款的前5只股票
    #数据准备
    #计算股票池的涨跌幅、回报率
    def get_return(pool):
      prices = get_price(list(pool), end_date='2017-9-1', frequency='1d', fields=['close'],count=252).close
      returns = (prices/prices.shift(1)).iloc[1:]
      rets = returns.dropna(axis=1)
      return rets
    
  • step3 构建5只股票的组合,计算收益、方差、夏普率
    #随机权重设置
    def weight(n):
      w = np.random.random(n)
      return w/sum(w)
    #获取回报值
    returns = get_return(pool) 
    #输入收益returns,权重
    #返回年化收益、标准差、夏普率
    def portfolio(returns,w):
      #无风险收益年化设置为0.04
      r_b = 0.04
      returns = np.log(returns)
      r_mean = returns.mean()*252
      p_mean = np.sum(r_mean*w)
      r_cov = returns.cov()*252
      p_var = np.dot(w.T,np.dot(r_cov,w))
      p_std = np.sqrt(p_var)
      p_sharpe = (p_mean-r_b)/p_std
      return p_mean,p_std,p_sharpe
    
  • step4 蒙特卡洛模拟

    p_mean,p_std,p_sharpe = np.column_stack([portfolio(returns,weight(5)) for i in range(2000)]) #产生随机组合
    plt.figure(figsize = (14,8))
    plt.scatter(p_std, p_mean, c=p_sharpe, marker = 'o')
    plt.grid(True)   #显示网格
    plt.xlabel('std')
    plt.ylabel('mean')
    plt.colorbar(label = 'Sharpe')
    plt.title('Mean and Std of Returns')
    

    将随机权重的组合收益风险进行图形化展示
    5.png

  • step5 找出风险最小的组合权重、找出夏普率最大的组合权重

    from scipy.optimize import minimize 
    #最小方差函数
    def min_variance(w):
      return portfolio(returns,w)[1]**2
    #最大夏普函数(转化为求最小值)
    def min_sharpe(w):
      return -portfolio(returns,w)[2]
    #约束条件,权重总和为1
    cons = ({'type':'eq', 'fun':lambda x: np.sum(x)-1})
    #夏普率最大
    opt_sharpe = minimize(min_sharpe,weight(5),bounds=((0,1),(0,1),(0,1),(0,1),(0,1)),constraints = cons)
    #方差最小
    opt_var = minimize(min_variance,weight(5),bounds=((0,1),(0,1),(0,1),(0,1),(0,1)),constraints = cons)
    

    7.png

  • step6 找出有效前沿

  • 找出风险最小的组合权重,取此权重下收益更高的组合,为了避免找不到最优的结果,这里取了1.7倍的最小风险收益,在优化函数中加入收益约束条件进行求解
    #有效前沿
    #最小方差下的收益率
    r_min = portfolio(returns,opt_var['x'])[0]
    r_mean_list = np.linspace(r_min,r_min*1.7,20)
    v_list = []
    for r in r_mean_list:    
      cons1 = ({'type':'eq','fun':lambda w:portfolio(returns,w)[0]-r},{'type':'eq','fun':lambda w:np.sum(w)-1})
      opt_var_1 = minimize(min_variance,weight(5),bounds=((0,1),(0,1),(0,1),(0,1),(0,1)),constraints = cons1)
      #最小方差下的收益率
      v_min = portfolio(returns,opt_var_1['x'])[1]
      print v_min
      v_list.append(v_min)
    
    8.png

第三部分 组合应用

有这么一个策略,每月换仓HS300前5只涨幅超过4%的股票进行买入持仓,具体操作如下

  1. 取HS300前一年涨幅超过4%的5只股票
  2. 每月调仓,更换股票池
  3. 在同一个股票池下,A组合平均分仓,B组合取最大夏普权重
  4. 比较股票收益的波动情况和年化收益
  5. 代码较长可以在研究里面参考,组合模拟结果如下
    9.png

    #计算总收益率
    total_return1,total_return2 = df_returns.cumprod().values[-1]-1,df_a.cumprod().values[-1]-1
    #计算年化收益
    total_a_r1,total_a_r2 = (1 total_return1)**(250.0/len(df_returns))-1,(1 total_return2)**(250.0/len(df_a))-1
    #计算夏普率
    sharpe1,sharpe2 = (total_a_r1-0.04)/np.std(df_returns.cumprod()),(total_a_r2-0.04)/np.std(df_a.cumprod())
    df_summary = pd.DataFrame([],index=['均值方差优化组合','平均分仓组合'])
    df_summary['总收益'] = [total_return1,total_return2]
    df_summary['年化收益'] = [total_a_r1,total_a_r2]
    df_summary['sharpe'] = [sharpe1,sharpe2]
    df_summary
    

    10.png

  6. 可以看到优化后的组合获得了更好的表现


第一部分 投资组合的收益率和风险¶

示例问题:¶

  • 市场有资产A和资产B,收益率分别为RA和RB,收益率的期望值E(RA)、E(RB)分别为8%和15%,标准差RA、RB分别为12%和25%。当两资产的相关系数分别为-1、-0.5、0、+0.5、+1时,不同的投资比例下投资组合的期望收益率及风险分别是如何变化的?
import numpy as np
import pandas as pd
import math
import matplotlib.pyplot as plt
#模拟生成两个的权重
def weight(n):
    w = np.random.random(n)
    return w/sum(w)
#定义计算收益、风险、夏普率的函数
def portfolio_test(w):
    r1,r2 = 0.08,0.12
    sigma1,sigma2 = 0.12,0.25
    rho1,rho2,rho3,rho4,rho5 = -1,-0.5,0,0.5,1
    p_mean = r1*w[0]+r2*w[1]
    p_var1 = (w[0]**2)*(sigma1**2)+(w[1]**2)*(sigma2**2)+2*w[0]*w[1]*rho1*sigma1*sigma2
    p_var2 = (w[0]**2)*(sigma1**2)+(w[1]**2)*(sigma2**2)+2*w[0]*w[1]*rho2*sigma1*sigma2
    p_var3 = (w[0]**2)*(sigma1**2)+(w[1]**2)*(sigma2**2)+2*w[0]*w[1]*rho3*sigma1*sigma2
    p_var4 = (w[0]**2)*(sigma1**2)+(w[1]**2)*(sigma2**2)+2*w[0]*w[1]*rho4*sigma1*sigma2
    p_var5 = (w[0]**2)*(sigma1**2)+(w[1]**2)*(sigma2**2)+2*w[0]*w[1]*rho5*sigma1*sigma2
    p_sigma1 = np.sqrt(p_var1)
    p_sigma2= np.sqrt(p_var2)
    p_sigma3 = np.sqrt(p_var3)
    p_sigma4 = np.sqrt(p_var4)
    p_sigma5 = np.sqrt(p_var5)
    return w[0],w[1],p_mean,p_sigma1,p_sigma2,p_sigma3,p_sigma4,p_sigma5
df_value =np.column_stack([portfolio_test(weight(2)) for i in range(10)]) #产生随机组合
df = pd.DataFrame(df_value.T,columns = ['A资产比例','B资产比例','r_期望收益','p_rho1','p_rho2','p_rho3','p_rho4','p_rho5'])
df
A资产比例 B资产比例 p_mean p_rho1 p_rho2 p_rho3 p_rho4 p_rho5
0 0.698865 0.301135 0.092045 0.008580 0.079920 0.112698 0.137893 0.159148
1 0.668762 0.331238 0.093250 0.002558 0.081561 0.115316 0.141221 0.163061
2 0.416181 0.583819 0.103353 0.096013 0.128482 0.154263 0.176313 0.195896
3 0.828637 0.171363 0.086855 0.056596 0.086389 0.108273 0.126423 0.142277
4 0.525211 0.474789 0.098992 0.055672 0.102861 0.134392 0.159819 0.181723
5 0.220925 0.779075 0.111163 0.168258 0.182960 0.196565 0.209287 0.221280
6 0.559924 0.440076 0.097603 0.042828 0.096055 0.128914 0.154955 0.177210
7 0.654125 0.345875 0.093835 0.007974 0.082770 0.116783 0.142918 0.164964
8 0.235294 0.764706 0.110588 0.162941 0.178739 0.193250 0.206745 0.219412
9 0.584404 0.415596 0.096624 0.033770 0.091797 0.125351 0.151655 0.174027
df[['p_rho1','p_rho2','p_rho3','p_rho4','p_rho5']].plot()
<matplotlib.axes._subplots.AxesSubplot at 0x7f7a452da610>

给出的10组测试中,每组组合的预期收益是一样的,组合风险从1到4逐渐增加,两资产的相关系数越高,风险越大。

df_value1 =np.column_stack([portfolio_test(weight(2)) for i in range(200)]) #产生随机组合
df1= pd.DataFrame(df_value1.T,columns = ['A资产比例','B资产比例','p_mean','p_rho1','p_rho2','p_rho3','p_rho4','p_rho5'])
plt.scatter(df1['p_rho1'],df1['p_mean'],marker = 'o')
plt.scatter(df1['p_rho2'],df1['p_mean'],marker = 'o')
plt.scatter(df1['p_rho3'],df1['p_mean'],marker = 'o')
plt.scatter(df1['p_rho4'],df1['p_mean'],marker = 'o')
plt.scatter(df1['p_rho5'],df1['p_mean'],marker = 'o')
<matplotlib.collections.PathCollection at 0x7f7a98957990>

以上是不同的相关系数下,投资组合标准差随投资比例变动的情况

接下来是马科维兹均值方差模型

从上面部分我们看到,几种资产的相关度越低,他们的组合收益?

第二部分 均值方差模型¶

  • 接下来,我们在HS300中取5只近一年收益为正的股票,来看下组合的预期收益和组合风险之间的关系
#选出几个标的数据,进行演示计算
#这里选取HS300里面近一年涨幅大于4%的5只股票
stock_list = get_index_stocks('000300.XSHG')
pool = []
for i in stock_list:
    price_df = get_price(i,start_date='2017-9-1',end_date='2018-9-1',fields=['close'])
    pct = price_df['close'].values[-1]/price_df['close'].values[0]
    if pct>1.04:
        pool.append(i)
    if len(pool)==5:
        break
pool
[u'000002.XSHE',
 u'000333.XSHE',
 u'000338.XSHE',
 u'000425.XSHE',
 u'000786.XSHE']
#数据准备
#计算股票池的涨跌幅、回报率
def get_return(pool):
    prices = get_price(list(pool), end_date='2017-9-1', frequency='1d', fields=['close'],count=252).close
    returns = (prices/prices.shift(1)).iloc[1:]
    rets = returns.dropna(axis=1)
    return rets
#随机权重设置
def weight(n):
    w = np.random.random(n)
    return w/sum(w)
#获取回报值
returns = get_return(pool)     

1.计算取的是对数收益率,研究中收益率都是用对数收益率,理论上对数收益率才是正态分布 2.求组合的方差、组合的标准差。 求方差时是收益率序列的协方差矩阵加权出来,并年化(*252)的。

np.log(returns).mean()*252
000002.XSHE    0.106476
000333.XSHE    0.042645
000338.XSHE    0.208467
000425.XSHE    0.081795
000786.XSHE    0.103304
dtype: float64
#输入收益returns,权重
#返回年化收益、标准差、夏普率
def portfolio(returns,w):
    #无风险收益年化设置为0.04
    r_b = 0.04
    returns = np.log(returns)
    r_mean = returns.mean()*252
    p_mean = np.sum(r_mean*w)
    r_cov = returns.cov()*252
    p_var = np.dot(w.T,np.dot(r_cov,w))
    p_std = np.sqrt(p_var)
    p_sharpe = (p_mean-r_b)/p_std
    return p_mean,p_std,p_sharpe
p_mean,p_std,p_sharpe = np.column_stack([portfolio(returns,weight(5)) for i in range(2000)]) #产生随机组合
plt.figure(figsize = (14,8))
plt.scatter(p_std, p_mean, c=p_sharpe, marker = 'o')
plt.grid(True)   #显示网格
plt.xlabel('std')
plt.ylabel('mean')
plt.colorbar(label = 'Sharpe')
plt.title('Mean and Std of Returns')
<matplotlib.text.Text at 0x7f7a940f2850>

找到方差最小的点

optimize.minimize(target_fun,init_val,method,jac,hess) target_fun:函数的表达式计算; init_val:初始值; method:最小化的算法; jac:雅各比矩阵 hess:黑塞矩阵。

from scipy.optimize import minimize 

#最小方差函数
def min_variance(w):
    return portfolio(returns,w)[1]**2
#最大夏普函数(转化为求最小值)
def min_sharpe(w):
    return -portfolio(returns,w)[2]
#约束条件,权重总和为1
cons = ({'type':'eq', 'fun':lambda x: np.sum(x)-1})
#夏普率最大
opt_sharpe = minimize(min_sharpe,weight(5),bounds=((0,1),(0,1),(0,1),(0,1),(0,1)),constraints = cons)
#方差最小
opt_var = minimize(min_variance,weight(5),bounds=((0,1),(0,1),(0,1),(0,1),(0,1)),constraints = cons)
print("Sharpe最大时的组合最优解是:")
print "组合仓位比例:",'%s' % (opt_sharpe['x'].round(3))
print('组合收益:%s' % (portfolio(returns,opt_sharpe['x'].round(3))[0]))
print('组合标准差(波动率):%s' % (portfolio(returns,opt_sharpe['x'].round(3))[1]) )
print('组合sharpe:%s' % (portfolio(returns,opt_sharpe['x'].round(3))[2]) )
Sharpe最大时的组合最优解是:
组合仓位比例: [ 0.     0.383  0.471  0.     0.147]
组合收益:0.489976378043
组合标准差(波动率):0.204062548869
组合sharpe:2.20509045161
plt.figure(figsize = (14,8))
plt.scatter(p_std, p_mean, c=p_sharpe, marker = 'o')

#红星:标记最高sharpe组合
plt.plot(portfolio(returns,opt_sharpe['x'])[1],portfolio(returns,opt_sharpe['x'])[0], 'r*', markersize = 15.0)

#黄星:标记最小方差组合
plt.plot(portfolio(returns,opt_var['x'])[1], portfolio(returns,opt_var['x'])[0], 'y*', markersize = 15.0)

plt.grid(True)   #显示网格
plt.xlabel('std')
plt.ylabel('mean')
plt.colorbar(label = 'Sharpe')
plt.title('Mean and Std of Returns')
<matplotlib.text.Text at 0x7f7a467ec210>
#有效前沿
#最小方差下的收益率
r_min = portfolio(returns,opt_var['x'])[0]
r_mean_list = np.linspace(r_min,r_min*1.7,20)
v_list = []
for r in r_mean_list:    
    cons1 = ({'type':'eq','fun':lambda w:portfolio(returns,w)[0]-r},{'type':'eq','fun':lambda w:np.sum(w)-1})
    opt_var_1 = minimize(min_variance,weight(5),bounds=((0,1),(0,1),(0,1),(0,1),(0,1)),constraints = cons1)
    #最小方差下的收益率
    v_min = portfolio(returns,opt_var_1['x'])[1]
    print v_min
    v_list.append(v_min)
0.175019898941
0.175114714577
0.175411195452
0.175913650611
0.176615582056
0.177519122871
0.178616014397
0.179908116449
0.181387427862
0.183051479008
0.184894460286
0.186910174387
0.18909558519
0.191441857239
0.193945694052
0.196649131372
0.199629477745
0.202879148981
0.209608338398
0.222411666394
plt.figure(figsize = (14,8))
plt.scatter(p_std, p_mean, c=p_sharpe, marker = 'o')

#红星:标记最高sharpe组合
plt.plot(portfolio(returns,opt_sharpe['x'])[1],portfolio(returns,opt_sharpe['x'])[0], 'r*', markersize = 15.0)

#黄星:标记最小方差组合
plt.plot(portfolio(returns,opt_var['x'])[1], portfolio(returns,opt_var['x'])[0], 'y*', markersize = 15.0)

#标记有效前沿
plt.plot(v_list,r_mean_list, 'b*', markersize = 5.0)

plt.grid(True)   #显示网格
plt.xlabel('std')
plt.ylabel('mean')
plt.colorbar(label = 'Sharpe')
plt.title('Mean and Std of Returns')
<matplotlib.text.Text at 0x7f7a464d38d0>
#最小方差下的收益率
r_min = portfolio(returns,opt_var['x'])[0]
r_min
0.300883836813862

一个示例 1.取HS300前一年涨幅超过4%的5只股票 2.每月调仓,更换股票池 3.在同一个股票池下,A组合平均分仓,B组合取最大夏普权重 4.比较股票收益的波动情况和年化收益

#输入日期
#返回HS300中股票收益超过4%的前5只股票
def get_pool(date):
    stock_list = get_index_stocks('000300.XSHG',date=date)
    pool = []
    for i in stock_list:
        price_df = get_price(i,end_date=date,fields=['close'],count=252)
        pct = price_df['close'].values[-1]/price_df['close'].values[0]
        if pct>1.04:
            pool.append(i)
        if len(pool)==5:
            break
    return pool

#输入股票列表
#返回一个组合的权重配比
def opt_func(pool,date):
    prices = get_price(list(pool), end_date=date, frequency='1d', fields=['close'],count=252).close
    returns = (prices/prices.shift(1)).iloc[1:]
    returns = returns.dropna(axis=1)

    def portfolio(returns,w):
        #无风险收益年化设置为0.04
        r_b = 0.04
        returns = np.log(returns)
        r_mean = returns.mean()*252
        p_mean = np.sum(r_mean*w)
        r_cov = returns.cov()*252
        p_var = np.dot(w.T,np.dot(r_cov,w))
        p_std = np.sqrt(p_var)
        p_sharpe = (p_mean-r_b)/p_std
        return p_mean,p_std,p_sharpe
    
    def weight(n):
        w = np.random.random(n)
        return w/sum(w)
    
    #最大夏普函数(转化为求最小值)
    def min_sharpe(w):
        return -portfolio(returns,w)[2]
    #约束条件,权重总和为1
    cons = ({'type':'eq', 'fun':lambda x: np.sum(x)-1})
    #夏普率最大
    opt_sharpe = minimize(min_sharpe,weight(5),bounds=((0,1),(0,1),(0,1),(0,1),(0,1)),constraints = cons)
    return opt_sharpe['x'].round(3)
date = '2018-1-1'
pool = get_pool(date)
res = opt_func(pool,date).round(3)
res
array([ 0.314,  0.204,  0.482,  0.   ,  0.   ])
#工具函数
#获取日期列表
def get_tradeday_list(s='2017-1-1',e='2018-7-25',label='month',count=None):
    if count != None:
        df = get_price('000001.XSHG',end_date=e,count=count)
    else:
        df = get_price('000001.XSHG',start_date=s,end_date=e)
    if label==None:
        return df.index
    else:
        df['year-month'] = [str(i)[0:7] for i in df.index]
        if label == 'month':
            return df.drop_duplicates('year-month').index
        elif label == 'quarter':
            df['month'] = [str(i)[5:7] for i in df.index]
            df = df[(df['month']=='01') | (df['month']=='04') | (df['month']=='07') | (df['month']=='10') ]
            return df.drop_duplicates('year-month').index
        elif label =='halfyear':
            df['month'] = [str(i)[5:7] for i in df.index]
            df = df[(df['month']=='01') | (df['month']=='06')]
            return df.drop_duplicates('year-month').index
#获取股票池的组合收益(不进行市值加权)
def ret_se(sl,start_date='2018-6-1',end_date='2018-7-1',w=[1.0/len(sl)]*len(sl)):
    if len(sl) != 0:
        #得到股票的历史价格数据
        df = get_price(list(sl),start_date=start_date,end_date=end_date,fields=['close']).close
        df = df.dropna(axis=1)
        #获取列表中的股票流通市值对数值
        df_mkt = get_fundamentals(query(valuation.code,valuation.circulating_market_cap).filter(valuation.code.in_(df.columns)))
        df_mkt.index = df_mkt['code'].values
        fact_se =pd.Series(df_mkt['circulating_market_cap'].values,index = df_mkt['code'].values)
        fact_se = np.log(fact_se)
    else:
        df = get_price('000001.XSHG',start_date=start_date,end_date=end_date,fields=['close'])
        df['v'] = [1]*len(df)
        del df['close']
    #相当于昨天的百分比变化
    pct = df.pct_change()+1
    pct.iloc[0,:] = 1
    #df1 = pct.cumprod()
    #等权重平均收益结果
    #按权重的方式计算
    se1 = (pct*w).cumsum(axis=1).iloc[:,-1]
    se2 = pct.cumsum(axis=1).iloc[:,-1]/pct.shape[1]
    return se1,se2
def f_sum(x):
    return sum(x)
#设置回测时间
start,end = '2016-9-1','2018-9-1'
#获取交易日列表
trade_list = get_tradeday_list(start,end,'month')
num = 1

for s,e in zip(trade_list[:-1],trade_list[1:]): 
    #获取满足条件的股票列表
    pool = get_pool(s)   
    #获取优化权重
    w = opt_func(pool,s)
    if num == 0:
        df_returns1 = ret_se(pool,s,e,w)[0] 
        df_a1 = ret_se(pool,s,e,w)[1] 
        df_returns = pd.concat([df_returns,df_returns1])
        df_a = pd.concat([df_a,df_a1])
    else:
        df_returns = ret_se(pool,s,e,w)[0]
        df_a = ret_se(pool,s,e,w)[1]
        num = 0
#进行图表展示
df_returns.cumprod().plot(figsize=(12,7),legend=True,label='组合优化收益',title='图2 组合收益走势')
df_a.cumprod().plot(figsize=(12,7),legend=True,label='平均分仓收益')
<matplotlib.axes._subplots.AxesSubplot at 0x7f7a45724f90>
#计算总收益率
total_return1,total_return2 = df_returns.cumprod().values[-1]-1,df_a.cumprod().values[-1]-1
#计算年化收益
total_a_r1,total_a_r2 = (1+total_return1)**(250.0/len(df_returns))-1,(1+total_return2)**(250.0/len(df_a))-1
#计算夏普率
sharpe1,sharpe2 = (total_a_r1-0.04)/np.std(df_returns.cumprod()),(total_a_r2-0.04)/np.std(df_a.cumprod())
df_summary = pd.DataFrame([],index=['均值方差优化组合','平均分仓组合'])
df_summary['总收益'] = [total_return1,total_return2]
df_summary['年化收益'] = [total_a_r1,total_a_r2]
df_summary['sharpe'] = [sharpe1,sharpe2]
df_summary
总收益 年化收益 sharpe
均值方差优化组合 0.106654 0.053288 0.056197
平均分仓组合 -0.175383 -0.094066 -0.969469
分享到:
举报财经168客户端下载

全部回复

0/140

投稿 您想发表你的观点和看法?

更多人气分析师

  • 张亦巧

    人气2192文章4145粉丝45

    暂无个人简介信息

  • 王启蒙现货黄金

    人气296文章3215粉丝8

    本人做分析师以来,并专注于贵金属投资市场,尤其是在现货黄金...

  • 指导老师

    人气1864文章4423粉丝52

    暂无个人简介信息

  • 李冉晴

    人气2320文章3821粉丝34

    李冉晴,专业现贷实盘分析师。

  • 梁孟梵

    人气2176文章3177粉丝39

    qq:2294906466 了解群指导添加微信mfmacd

  • 张迎妤

    人气1896文章3305粉丝34

    个人专注于行情技术分析,消息面解读剖析,给予您第一时间方向...

  • 金泰铬J

    人气2328文章3925粉丝51

    投资问答解咨询金泰铬V/信tgtg67即可获取每日的实时资讯、行情...

  • 金算盘

    人气2696文章7761粉丝125

    高级分析师,混过名校,厮杀于股市和期货、证券市场多年,专注...

  • 金帝财神

    人气4760文章8329粉丝119

    本文由资深分析师金帝财神微信:934295330,指导黄金,白银,...

FX168财经

FX168财经学院

FX168财经

FX168北美