投资组合分析基础1

多股票策略回测时常常遇到问题。
仓位如何分配?
其实,这个问题,好多好多年前马科维茨(Markowitz)我喜爱的小马哥就给出答案——投资组合理论。
根据这个理论,我们可以对多资产的组合配置进行三方面的优化。

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

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

3.找到风险最小的组合

该理论基于用均值和方差来表述组合的优劣的前提。将选取几只股票,用蒙特卡洛模拟初步探究组合的有效前沿。
通过最大Sharpe和最小方差两种优化来找到最优的资产组合配置权重参数。
最后,刻画出可能的分布,两种最优以及组合的有效前沿。

1)选取A股所有股票2018年的EOD数据(数据事先已经下载好)

import pandas as pd
import numpy as np
data=pd.read_csv(r'C:\Users\yi\Desktop\Study\量化交易\stock2018.csv',sep=',',engine ='python')

查看DataFrame信息:
在这里插入图片描述
画一只股票的图形看看:

#切出需要的字段
EOD=data.iloc[:,[0,1,6]].sort_values('trade_date')
#按股票代码分组
stock=EOD.groupby(['ts_code'])
#取出'000063.SH'组的数据
zte=stock.get_group(['000063.SH'])
zte.plot('trade_date','close',figsize=(25,15))

在这里插入图片描述

stock_means=pd.DataFrame(columns=['ts_code', 'returnmean'])
j=0
for i in stock.nunique().index:
    if j>10:
        break
    #取代码为i的股票的close数据
    sclose=stock.get_group(i)['close']
    #计算对数收益
    returns = np.log(sclose / sclose.shift(1))  
     #计算年化对数收益
    returnmean=returns.mean()*252
    #将所有股票的年化对数收益写入列表
    transit=pd.DataFrame({'ts_code':[0], 'returnmean':[0]})
    transit['ts_code']=i
    transit['returnmean']=returnmean
    stock_means=stock_means.append(transit,ignore_index=True)
    print('code=%s returnmean=%s'%(i,returnmean))
    #returns.hist(bins=50, figsize=(12, 9))
    j+=1

在这里插入图片描述
画出这12只股票的收益直方图,可以看出大体是正态分布.
去掉计数器j,对所有股票跑一边,得到stock_means数据:

stock_means.describe()
Out[69]: 
        returnmean
count  3556.000000
mean     -0.373557
std       1.111227
min     -26.589527
25%      -0.573231
50%      -0.381268
75%      -0.195562
max      24.007412

我去,简直坑死人,2018年所有股票的平均指数收益率是-0.373557,-0.195562的成绩就已经跑赢了75%的股票~就问你坑不坑?
我们看看最坑的和最牛的5个都是谁:

 stock_means.sort_values('returnmean').head(5)
Out[74]: 
        ts_code  returnmean
536   002075.SZ  -26.589527
244   000693.SZ  -12.881314
2184  600086.SH   -8.144002
1195  002739.SZ   -7.548460
608   002147.SZ   -7.318664

stock_means.sort_values('returnmean').tail(5)
Out[75]: 
        ts_code  returnmean
2972  601162.SH   13.214315
2115  300751.SZ   15.765417
3001  601319.SH   23.970533
3226  603220.SH   23.990517
2043  300674.SZ   24.007412

年度最坑奖:沙钢股份
年度最牛奖:没有评的意义,基本全是新股,看来市场还是相当不理性的

*注:全部代码

import pandas as pd
import numpy as np
data=pd.read_csv(r'D:\Study\stock2018.csv',sep=',',engine ='python')
EOD=data.set_index(['trade_date'],drop=True).drop(['pre_close','change','pct_change','trade_date.1'],axis=1).sort_index()
p_close=EOD['close']
#EOD.pivot_table(index='ts_code',values=['open','high','low','close'],aggfunc=(np.log(p_close/p_close.shift(1)).mean))
EODG=EOD.groupby(['ts_code'])
j=0
lreturn_list=pd.DataFrame()
for i in EODG.groups.keys():
    pclose=EODG.get_group(i)['close']
    stock_code=i
    log_return=np.log(pclose/pclose.shift(1))
    lr=pd.DataFrame({'log_return':log_return})
    log_return_mean=log_return.mean()*len(log_return)
    transit=pd.DataFrame({'ts_code':[i],'log_return_mean':[log_return_mean]})
    if j==0:
        lreturn_mean=transit
    else:
        lreturn_mean=lreturn_mean.append(transit)
    lreturn_list[i]=log_return
    #print ('stock %s :log return is %s'%(i,log_return))
    print ('%s/%s stock %s :mean log return is %s'%(len(EODG.groups.keys()),j+1, i,log_return_mean))
    j=j+1
    #if j>2000:
    #    break
cov_dual_stock=pd.DataFrame()
a=0
for st1 in lreturn_list.columns:
    for st2 in lreturn_list.columns:
        if st1!=st2:
            cov2=lreturn_list.loc[:,[st1,st2]].cov()*len(log_return)
            print(cov2)
            cov_dual_stock=cov_dual_stock.append(cov2)
            a+=1
            if a>10:
                break

猜你喜欢

转载自blog.csdn.net/weixin_43622668/article/details/84572488