在股票投资中,投资者面临的除了收益外,还有相应的风险。根据风险是否可以规避,理论上讲风险划分为系统风险和非系统风险。系统风险是由于企业外部的宏观环境中各种不可抗因素的作用下而产生的风险,这些因素包括全球性或区域性恐慌、贸易争端、经济衰退、政府出台经济调控政策等等。对于系统风险,投资者无法提前感知和采取措施规避,也无法通过分散投资进行消除。而非系统风险则是由于企业自身的因素而引发的风险,这些因素包括财务风险、经营风险、信用风险、偶然事件风险等。非系统风险往往可以通过充分分散化投资的方式来进行消除。
本讲主要想通过绘制图形来描述系统风险的存在性,具体思想为:选择N支股票,令N从1至n进行变化,每当投资组合加入一支新股票时,假定每支股票所占权重相等并重新计算该组合的收益率波动率,观察整个投资组合的收益率波动率的变化情况。
最初的想法是获取有代表性的构建指数(如上证180,上证50,中证500等)的股票数据,可惜我的tushare权限太低,已经没有足够分数直接获取对应数据了,因此,本文采用的方法是:随机在全部股票中,选择出一定数量的股票,就不管是否有代表性了,反正根据理论,当分散越充分后,非系统风险也就越小,那就能体现出系统风险的问题了。
首先获取股票基本信息,目的是为了拿到所有股票的股票代码,展示前2条数据看看:
import tushare as ts
pro=ts.pro_api('b497571a3ddd7dde8ebe28b372879594b2f8356c918ad80dae01605b')
df=pro.stock_basic(exchange='', list_status='L', fields='ts_code,symbol,name,area,industry,list_date')
print(df.shape)
df.head(2)
接着定义一个空数组,随机添加一些股票的索引数字进去,根据这些数字,在后面找到表中对应的行,并取出其股票代码:
import datetime
s=[]
import random
for i in range(500):#值可以更改,为了获得较大数量的股票
k=random.randint(0,4462)
s.append(k)
s=list(set(s))
for i in s:
if df.loc[i].list_date>'20170101':
s.remove(i)
为了避免某些股票在数据计算的区间(2017-2018两年)缺失数据,这里对所有2017年之后上市的公司索引进行了删除。
然后建立一个空数据框,将列表中所有的行索引对应的股票信息进行获取并存储,这里只要收盘价close:
import pandas as pd
dt=pd.DataFrame()
k=0
for i in s:
dt[df.loc[i]['name']]=pro.daily(ts_code=df.loc[i].ts_code, start_date='20170101', end_date='20181231')['close']
然后再删除数据框中,列内有空数据的列:
dt=dt.T.dropna().T
查看一下数据:
dt.shape
发现结果为(487, 149),有149支股票,487天的交易数据,凑合用了。
对数据框进行按首行归一处理,并计算出每支股票的收益率:
dt=dt/dt.loc[0]
import numpy as np
r=np.log(dt.astype('float')/dt.astype('float').shift(1))
r=r.dropna()
再根据前两讲所讲到的方法,计算投资组合的收益率波动率,投资组合每增加一支股票就重新计算一次:
n=len(r.columns)
vp=np.zeros(n) #用于存储每增加一支股票后的波动率
for i in range(1,n+1):
weight=np.ones(i)/i
cov=252*r.iloc[:,:i].cov()
vp[i-1]=np.sqrt(np.dot(weight,np.dot(cov,weight.T)))
拿到所有的投资组合波动率变化值后,进行绘图:
k=np.arange(n)+1
import matplotlib.pyplot as plt
from pylab import mpl
mpl.rcParams['font.sans-serif']=['SimHei']
mpl.rcParams['axes.unicode_minus']=False
plt.figure(figsize=(10,8))
plt.plot(k,vp,'b-',lw=2,label='波动率')
plt.xlabel(u'',fontsize=12)
plt.ylabel(u'',fontsize=12,rotation=90)
plt.title(u'系统风险存在图',fontsize=14)
plt.grid(True)
plt.legend()
plt.show()
第一次的数据做的有点少,所以表现还不是特别好,不过大概趋势是很明显的,当股票数量增加时,波动率前期急剧下降,后续逐步下降(但可能数据不好,居然还有反弹?):
为了更好的展示,我把数据量增大了,将随机值个数设为1000后,得到的是426支股票,而图形表现则为:
可以发现,当组合的股票数量超过一定数量时,不管如何增加股票的数量,这个投资组合的收益率波动率就在20%的附近平稳滑动,因此,这个波动率是无法消除的,也就是我们所提到的系统风险,20%也可以视为是系统风险的水平。另外,这个股票数量一般是在40以上,在本文中,趋近于75,也就是说股票数量足够大时,就可以充分分散掉非系统风险。