为了降低风险,投资者在购买股票时往往会构建一个投资组合,以对冲风险和最大获益。在投资组合中,描述该投资组合效果的两个重要变量是预期收益率及其波动率。
1.投资组合的预期收益率
预期收益率的计算公式为:
E(R)=E(
∑
k
=
1
n
w
i
R
i
\displaystyle \sum_{k=1}^n w_i R_i
k=1∑nwiRi )=
[
w
1
,
w
2
,
w
3
.
.
.
w
n
[ \displaystyle \ w_1,w_2,w_3...w_n
[ w1,w2,w3...wn ][
E
(
R
1
)
,
E
(
R
2
)
,
.
.
.
E
(
R
n
)
]
T
\displaystyle \ E(R_1),E(R_2),...E(R_n)]^T
E(R1),E(R2),...E(Rn)]T
其中,
w
i
w_i
wi表示投资组合中第i支股票的权重,通常为股票市值占投资总值的比例,满足
∑
k
=
1
n
w
i
=
1
\displaystyle \sum_{k=1}^n w_i =1
k=1∑nwi=1。而E(
R
i
R_i
Ri)表示第i支股票的预期收益率,通常用该股票过去的收益率均值表示。
假设我们任选5支股票(就拿Tushare里获取的前几支股票为例),计算其预期收益率。
首先获取所有股票的信息:
import tushare as ts
pro=ts.pro_api('b497571a3ddd7dde8ebe28b372879594b2f8356c918ad80dae01605b') #此token已过期,只有基础积分,随便用
df = pro.stock_basic(exchange='', list_status='L', fields='ts_code,symbol,name,area,industry,list_date')
df.head()
为了简化操作,我们就选前5支数据较好的股票,先获取其行情数据,这里是收盘价close,日期为2018年7月1日至2021年8月31日:
dt=pd.DataFrame() #构建一个空数据框,装载所有股票行情信息
for i in df.loc[:5][['ts_code','name']].values:
name=i[1]
dt[name]=pro.daily(ts_code=i[0], start_date='20180701', end_date='20210831')['close']
dt
发现国华网安的数据后面有很多空数据,所以把它删掉,剩余5支作为待计算数据。
dt.drop('国华网安',axis=1,inplace=True)
dt
首先先做一个股票走势绘图:
from pylab import mpl
mpl.rcParams['font.sans-serif']=['SimHei']
mpl.rcParams['axes.unicode_minus']=False
(dt/dt.iloc[0]).plot(figsize=(10,8)) #所有数据都对首日数据进行归一处理
可以看到ST全新有点疯狂啊,而平安银行则有点萎靡不振。
接着对所有股票计算收益率,并绘制直方图。
r=np.log(dt/dt.shift(1)) #求收益率公式
r=r.dropna() #去除其他有空数据的行
r.hist(bins=40,figsize=(10,8))
可以看到,除了ST全新,基本上收益率都还是比较符合正态分布的。
接着随机生成一个股票投资比例,计算一下,该投资组合的预期收益率:
#先求每支股票的年化平均收益率
r_mean=r.mean()*252
r_mean
结果是:
平安银行 -0.235112
万科A 0.054881
ST星源 0.063218
深振业A 0.072212
*ST全新 0.382847
dtype: float64
#然后随机生成投资比例,计算投资组合的预期收益率
import numpy as np
x=np.random.random(5)
weights=x/x.sum()
weights
得到各支股票的权重为:
array([0.13628201, 0.25905629, 0.12644307, 0.26794179, 0.21027683])
再计算组合投资收益率:
reward=np.sum(weights*r_mean)
reward
可以看到,这个组合的收益是0.056951510250772996,貌似刚刚跑赢CPI啊,基本上还是盈利的。
2.投资组合的波动率
波动率就是我们俗称的风险,用于反映收益率的波动程度。
考虑两支股票组合的收益率波动率,设
σ
1
\sigma_1
σ1,
σ
2
\sigma_2
σ2分别是两支股票的波动率,则有组合波动率
σ
2
\sigma^2
σ2=
w
1
2
σ
1
2
w_1 ^2 \sigma_1^2
w12σ12+
w
2
2
σ
2
2
w_2 ^2 \sigma_2^2
w22σ22+2
w
1
w
2
δ
σ
i
σ
2
w_1 w_2 \delta \sigma_i\sigma_2
w1w2δσiσ2
这里的
δ
\delta
δ表示两支股票收益率的相关系数,并且与两支股票收益率的协方差有如下关系:
δ
\delta
δ=cov(R1,R2)/
σ
i
σ
2
\sigma_i\sigma_2
σiσ2
可见,若
δ
\delta
δ=1,即完全线性正相关,则组合波动率为
w
1
σ
1
+
w
2
σ
2
w_1 \sigma_1 +w_2 \sigma_2
w1σ1+w2σ2,也就是加权平均值,若完全负相关,则为二者之差绝对值。
扩展到N支股票的组合中时(这公式实在太多了,懒得敲)
σ
\sigma
σ=
w
∑
σ
s
w
T
\sqrt{w \displaystyle \sum \sigma_s w^T}
w∑σswT
这里的
σ
s
\sigma_s
σs表示投资组合的收益率协方差矩阵
接着我们继续计算投资组合的收益率波动率,首先对收益率计算协方差矩阵并年化处理:
r_cov=r.cov()*252
r_cov
再得到收益率相关系数矩阵,从相关系数看,相互之间,关联性较低
r_corr=r.corr()
r_corr
以及每支股票的年化波动率:
r_vol=r.std()*np.sqrt(252)
r_vol
可以看到,年化波动率都比较大
平安银行 0.350814
万科A 0.332052
ST星源 0.383830
深振业A 0.373611
*ST全新 0.591139
dtype: float64
最后,再根据前面的比例计算投资组合的波动率:
v_p=np.sqrt(np.dot(weights,np.dot(r_cov,weights.T)))
v_p
结果为0.23965157585238028,组合的波动率不小啊,应该是在ST全新上下注了不少的原因吧。
OK,全文到此结束,利用数据做了简单的预期收益率和波动率的计算,当然,这种方式得到的结果很随机,不一定能碰到最优解,因此后续将讨论如何取得最优解。