理论就不多加叙述了,感兴趣的可以去查找MPT现代/均值-方差资产组合理论。
均值-方差理论的核心思想是同时考察资产组合的预期收益和风险,研究当我们有一系列可选资产的时候,应如何对其配置资金权重,从而可以得到最好的收益风险比,也就是最好的夏普比率。
以下模拟投资组合的预期收益率和波动情况
import pandas as pd
import numpy as np
%matplotlib inline
import matplotlib.pyplot as plt
plt.style.use('ggplot')
dates=pd.date_range(start='2010/1/1',end='2010/12/31')
df_rtn=pd.DataFrame(index=dates)
df_rtn['s1']=np.random.normal(0.1, 0.05, len(dates))
df_rtn['s2']=np.random.normal(0.2, 0.10, len(dates))
df_rtn['s3']=np.random.normal(0.3, 0.15, len(dates))
df_rtn['s4']=np.random.normal(0.4, 0.2, len(dates))
df_rtn['s5']=np.random.normal(-0.2, 0.10, len(dates))
df_rtn
s1 | s2 | s3 | s4 | s5 | |
---|---|---|---|---|---|
2010-01-01 | 0.165496 | 0.054865 | 0.550757 | 0.416184 | -0.241358 |
2010-01-02 | 0.123811 | 0.066198 | 0.236836 | 0.269195 | -0.276284 |
2010-01-03 | 0.059512 | 0.321974 | 0.194933 | 0.144246 | -0.250190 |
2010-01-04 | 0.056678 | 0.003651 | 0.499698 | 0.579080 | -0.235689 |
2010-01-05 | 0.065828 | 0.129830 | 0.291351 | 0.397176 | 0.001602 |
... | ... | ... | ... | ... | ... |
2010-12-27 | 0.104600 | 0.335536 | 0.303462 | 0.346302 | -0.243276 |
2010-12-28 | 0.047231 | 0.199015 | 0.475520 | -0.043252 | -0.236914 |
2010-12-29 | 0.130282 | 0.131229 | 0.386482 | 0.614867 | 0.059841 |
2010-12-30 | 0.093123 | 0.288365 | 0.442705 | 0.326410 | -0.126081 |
2010-12-31 | 0.118626 | 0.213211 | 0.601449 | 0.605520 | -0.116745 |
365 rows × 5 columns
df_rtn.plot(figsize=(10,6))
<AxesSubplot:>
df_rtn.mean()*252
s1 25.781191
s2 49.999966
s3 78.002242
s4 102.503923
s5 -50.197467
dtype: float64
df_rtn.cov()*252
s1 | s2 | s3 | s4 | s5 | |
---|---|---|---|---|---|
s1 | 0.677835 | -0.049152 | -0.003292 | -0.264586 | 0.008482 |
s2 | -0.049152 | 2.617314 | -0.143490 | 0.321991 | 0.113303 |
s3 | -0.003292 | -0.143490 | 5.242705 | 0.443050 | 0.032384 |
s4 | -0.264586 | 0.321991 | 0.443050 | 9.358566 | 0.395169 |
s5 | 0.008482 | 0.113303 | 0.032384 | 0.395169 | 2.581551 |
随机一个投资组合权重
n=len(df_rtn.columns)
w=np.random.random(n)
w=w/np.sum(w)
w
array([0.21695834, 0.14631267, 0.1290212 , 0.20732207, 0.30038572])
# 投资组合收益率,s1~s5是每个资产的收益情况,每个资产的均值乘以不同的权重计算出投资组合的收益率
p_ret= np.sum(df_rtn.mean()*w)*252
p_ret
29.145739519785984
#投资组合波动率
p_vol=np.sqrt(np.dot(w.T,np.dot(df_rtn.cov()*252,w)))
p_vol
# 以上是某书籍中的波动率的衡量,感觉不太对,因为不是之前学过的标准的投资组合的风险计算方式,不知道是不是量化中特有的
0.9401632467991151
模拟多个权重的情况下,收益率和风险的变化情况,并作图,这个图就是经典的投资组合有效边界图
n=len(df_rtn.columns)
# 保存一系列权重对应的投资组合收益率
p_rets=[]
# 保存一系列权重对应的投资组合波动率
p_vols=[]
# 随机生成10000组权重
for i in range(10000):
w=np.random.random(n)
w/=np.sum(w)
# # 投资组合收益率
p_ret= np.sum(df_rtn.mean()*w)*252
#投资组合波动率(需要注意的是,使用np生成的一维数据,实际上是N*1矩阵,而不是1*N矩阵)
p_vol=np.sqrt(np.dot(w.T,np.dot(df_rtn.cov()*252,w)))
p_rets.append(p_ret)
p_vols.append(p_vol)
p_rets=np.array(p_rets)
p_vols=np.array(p_vols)
p_rets
array([37.37827321, 24.83548494, 27.16777023, ..., 51.47163399,
26.03826012, 31.35167142])
p_vols
array([1.05508155, 0.89835554, 0.97479329, ..., 1.09094976, 0.78924616,
0.91253653])
plt.figure(figsize=(10,6))
plt.scatter(p_vols, p_rets, c=p_rets/p_vols,marker='o')
plt.grid(True)
# x轴是风险,y轴是收益
plt.xlabel('volatility')
plt.ylabel('return')
# 夏普比率y/x的值,越黄的部分夏普比率越高,说明收益风险比最优秀
plt.colorbar(label='Sharpe ratio')
<matplotlib.colorbar.Colorbar at 0x1d6bd551588>
接下来求解最优投资组合权重,也就是求解最大的夏普比率下的投资组合权重
def portfolio_stat(weights):
"""获取投资组合的各种统计值
参数:
weights:分配的资金权重
返回值:
p_ret:投资组合的收益率
p_vol:投资组合的波动率
p_sr:投资组合的夏普比率
注意:rets是全局变量,在函数外部定义
"""
w=np.array(weights)
p_ret=np.sum(rets.mean()*w)*252
p_vol=np.sqrt(np.dot(w.T,np.dot(rets.cov()*252,w)))
p_sr=p_ret/p_vol
return np.array([p_ret,p_vol,p_sr])
# 该函数返回了夏普比率的负值,换句话说,我们需要对该函数进行最小化操作。之所以使用这种形式,是因为scipy.optimization只有minimize函数(机器学习中优化目标通常是最小化损失函数),所以这里使用了这种看起来有点奇怪的形式。
def min_func_sharpe(weights):
"""优化的目标函数,最小化夏普比率的负值,即最大化夏普比率
"""
return -portfolio_stat(weights)[2]
import scipy.optimize as sco
# 投资组合
rets=df_rtn
n=len(rets.columns)
# 优化的约束条件:资金的权重和为1,下面表示np.sum(x)-1 eq 0
cons=({'type':'eq','fun':lambda x:np.sum(x)-1})
#参数取值范围
bnds=tuple((0,1) for x in range(n))
# 生成初始权重
w_initial=n*[1./n,]
# 计算最有权重
opts_sharpe=sco.minimize(min_func_sharpe,w_initial,method='SLSQP',bounds=bnds,constraints=cons)
opts_sharpe
fun: -65.88146585394263
jac: array([ 4.17900085e-03, -1.56126022e-02, 7.96985626e-03, 3.96728516e-04,
7.72509413e+01])
message: 'Optimization terminated successfully'
nfev: 82
nit: 12
njev: 12
status: 0
success: True
x: array([4.94327710e-01, 2.19114359e-01, 1.64106232e-01, 1.22451699e-01,
1.55918074e-11])
# fun对应最优夏普比率,注意取负值,x为权重
opts_sharpe['x'].round(2)
array([0.49, 0.22, 0.16, 0.12, 0. ])
接下来我们来实战一下,根据近一年比亚迪,长安汽车,长城汽车近一年的收益率情况,搭建投资组合,计算最有的投资权重。
import tushare as ts
ts.set_token('d56646c5b067c6715534aff6a6487d736a545e525bbb3bd5abf7f9ed')
df_byd = ts.pro_bar(ts_code='002594.SZ', adj='qfq', start_date='20220427', end_date='20220627')
df_byd.sort_values(by="trade_date",inplace=True)
df_byd
ts_code | trade_date | open | high | low | close | pre_close | change | pct_chg | vol | amount | |
---|---|---|---|---|---|---|---|---|---|---|---|
39 | 002594.SZ | 20220427 | 226.61 | 235.81 | 218.81 | 235.01 | 231.81 | 3.20 | 1.3804 | 254341.67 | 5.794106e+06 |
38 | 002594.SZ | 20220428 | 234.60 | 235.50 | 230.00 | 231.98 | 235.01 | -3.03 | -1.2893 | 146372.13 | 3.405250e+06 |
37 | 002594.SZ | 20220429 | 233.80 | 243.83 | 230.75 | 243.00 | 231.98 | 11.02 | 4.7504 | 248163.10 | 5.912448e+06 |
36 | 002594.SZ | 20220505 | 246.20 | 252.39 | 241.77 | 248.80 | 243.00 | 5.80 | 2.3868 | 253258.79 | 6.282898e+06 |
35 | 002594.SZ | 20220506 | 241.02 | 246.00 | 240.10 | 242.08 | 248.80 | -6.72 | -2.7010 | 145488.66 | 3.530097e+06 |
34 | 002594.SZ | 20220509 | 231.00 | 236.89 | 231.00 | 232.73 | 242.08 | -9.35 | -3.8624 | 175116.35 | 4.086614e+06 |
33 | 002594.SZ | 20220510 | 224.10 | 233.66 | 222.28 | 233.33 | 232.73 | 0.60 | 0.2578 | 209696.64 | 4.792959e+06 |
32 | 002594.SZ | 20220511 | 232.00 | 256.66 | 231.50 | 252.70 | 233.33 | 19.37 | 8.3015 | 459525.71 | 1.148248e+07 |
31 | 002594.SZ | 20220512 | 249.99 | 257.70 | 248.71 | 254.09 | 252.70 | 1.39 | 0.5501 | 241156.06 | 6.107995e+06 |
30 | 002594.SZ | 20220513 | 259.80 | 271.50 | 255.91 | 270.08 | 254.09 | 15.99 | 6.2930 | 367120.61 | 9.733352e+06 |
29 | 002594.SZ | 20220516 | 271.11 | 273.00 | 265.30 | 267.12 | 270.08 | -2.96 | -1.0960 | 202368.80 | 5.441552e+06 |
28 | 002594.SZ | 20220517 | 268.98 | 285.00 | 268.50 | 282.50 | 267.12 | 15.38 | 5.7577 | 293489.03 | 8.193619e+06 |
27 | 002594.SZ | 20220518 | 282.50 | 288.00 | 279.00 | 281.42 | 282.50 | -1.08 | -0.3823 | 205302.70 | 5.812001e+06 |
26 | 002594.SZ | 20220519 | 275.31 | 285.35 | 274.30 | 284.51 | 281.42 | 3.09 | 1.0980 | 173636.51 | 4.879757e+06 |
25 | 002594.SZ | 20220520 | 287.01 | 291.61 | 281.20 | 287.70 | 284.51 | 3.19 | 1.1212 | 178683.36 | 5.125700e+06 |
24 | 002594.SZ | 20220523 | 292.70 | 298.00 | 287.81 | 295.20 | 287.70 | 7.50 | 2.6069 | 255588.16 | 7.496178e+06 |
23 | 002594.SZ | 20220524 | 290.00 | 292.96 | 281.00 | 281.00 | 295.20 | -14.20 | -4.8103 | 290496.53 | 8.303004e+06 |
22 | 002594.SZ | 20220525 | 281.26 | 288.65 | 278.03 | 287.20 | 281.00 | 6.20 | 2.2064 | 230857.73 | 6.563212e+06 |
21 | 002594.SZ | 20220526 | 287.37 | 291.22 | 282.50 | 286.64 | 287.20 | -0.56 | -0.1950 | 143094.99 | 4.106312e+06 |
20 | 002594.SZ | 20220527 | 292.95 | 297.61 | 286.65 | 288.88 | 286.64 | 2.24 | 0.7815 | 153186.85 | 4.467796e+06 |
19 | 002594.SZ | 20220530 | 292.00 | 299.70 | 291.08 | 298.12 | 288.88 | 9.24 | 3.1986 | 218523.50 | 6.485732e+06 |
18 | 002594.SZ | 20220531 | 300.00 | 300.96 | 293.51 | 295.91 | 298.12 | -2.21 | -0.7413 | 177011.19 | 5.242211e+06 |
17 | 002594.SZ | 20220601 | 298.00 | 304.80 | 293.12 | 299.98 | 295.91 | 4.07 | 1.3754 | 216911.75 | 6.501902e+06 |
16 | 002594.SZ | 20220602 | 296.00 | 305.00 | 295.22 | 301.02 | 299.98 | 1.04 | 0.3467 | 177727.77 | 5.355774e+06 |
15 | 002594.SZ | 20220606 | 304.00 | 320.47 | 302.55 | 318.23 | 301.02 | 17.21 | 5.7172 | 294757.29 | 9.260503e+06 |
14 | 002594.SZ | 20220607 | 318.00 | 319.87 | 311.11 | 314.89 | 318.23 | -3.34 | -1.0496 | 200220.89 | 6.296538e+06 |
13 | 002594.SZ | 20220608 | 318.60 | 328.06 | 313.01 | 327.41 | 314.89 | 12.52 | 3.9760 | 290513.40 | 9.321933e+06 |
12 | 002594.SZ | 20220609 | 334.03 | 334.80 | 321.00 | 322.41 | 327.41 | -5.00 | -1.5271 | 307541.72 | 1.005064e+07 |
11 | 002594.SZ | 20220610 | 321.50 | 350.00 | 321.06 | 348.80 | 322.41 | 26.39 | 8.1852 | 438249.00 | 1.479062e+07 |
10 | 002594.SZ | 20220613 | 346.00 | 358.86 | 340.60 | 348.80 | 348.80 | 0.00 | 0.0000 | 360681.32 | 1.257353e+07 |
9 | 002594.SZ | 20220614 | 342.00 | 344.79 | 327.23 | 343.59 | 348.80 | -5.21 | -1.4937 | 404789.34 | 1.363462e+07 |
8 | 002594.SZ | 20220615 | 343.97 | 346.23 | 332.52 | 335.00 | 343.59 | -8.59 | -2.5001 | 303947.87 | 1.028586e+07 |
7 | 002594.SZ | 20220616 | 335.50 | 342.70 | 333.41 | 336.00 | 335.00 | 1.00 | 0.2985 | 190172.45 | 6.410739e+06 |
6 | 002594.SZ | 20220617 | 330.10 | 341.20 | 327.07 | 338.00 | 336.00 | 2.00 | 0.5952 | 262147.59 | 8.830739e+06 |
5 | 002594.SZ | 20220620 | 338.08 | 348.66 | 335.02 | 342.18 | 338.00 | 4.18 | 1.2367 | 245415.57 | 8.405362e+06 |
4 | 002594.SZ | 20220621 | 339.76 | 341.80 | 332.20 | 341.00 | 342.18 | -1.18 | -0.3448 | 197827.39 | 6.666970e+06 |
3 | 002594.SZ | 20220622 | 342.42 | 347.63 | 338.00 | 339.88 | 341.00 | -1.12 | -0.3284 | 186787.83 | 6.412052e+06 |
2 | 002594.SZ | 20220623 | 344.70 | 354.05 | 338.00 | 353.50 | 339.88 | 13.62 | 4.0073 | 323142.26 | 1.125178e+07 |
1 | 002594.SZ | 20220624 | 352.99 | 356.28 | 346.01 | 351.05 | 353.50 | -2.45 | -0.6931 | 235983.55 | 8.273168e+06 |
0 | 002594.SZ | 20220627 | 352.07 | 357.00 | 348.33 | 349.69 | 351.05 | -1.36 | -0.3874 | 217155.24 | 7.630685e+06 |
df_ca = ts.pro_bar(ts_code='000625.SZ', adj='qfq', start_date='20220427', end_date='20220627')
df_ca.sort_values(by="trade_date",inplace=True)
df_ca
ts_code | trade_date | open | high | low | close | pre_close | change | pct_chg | vol | amount | |
---|---|---|---|---|---|---|---|---|---|---|---|
39 | 000625.SZ | 20220427 | 6.6975 | 7.0399 | 6.5072 | 6.9715 | 6.8877 | 0.0838 | 1.2167 | 958948.85 | 8.507858e+05 |
38 | 000625.SZ | 20220428 | 7.0171 | 7.3520 | 6.9410 | 7.2454 | 6.9715 | 0.2739 | 3.9289 | 1002657.73 | 9.455602e+05 |
37 | 000625.SZ | 20220429 | 7.9685 | 7.9685 | 7.9685 | 7.9685 | 7.2454 | 0.7231 | 9.9801 | 298727.48 | 3.127677e+05 |
36 | 000625.SZ | 20220505 | 8.6002 | 8.7676 | 8.4251 | 8.7676 | 7.9685 | 0.7991 | 10.0282 | 1115967.05 | 1.268370e+06 |
35 | 000625.SZ | 20220506 | 9.0568 | 9.3917 | 8.8437 | 8.9655 | 8.7676 | 0.1979 | 2.2572 | 3547775.54 | 4.247638e+06 |
34 | 000625.SZ | 20220509 | 8.9655 | 9.1253 | 8.5240 | 8.6610 | 8.9655 | -0.3045 | -3.3964 | 2144091.46 | 2.474558e+06 |
33 | 000625.SZ | 20220510 | 8.4251 | 8.6915 | 8.1207 | 8.5849 | 8.6610 | -0.0761 | -0.8787 | 1858279.40 | 2.059471e+06 |
32 | 000625.SZ | 20220511 | 8.5621 | 9.4449 | 8.5393 | 9.3080 | 8.5849 | 0.7231 | 8.4229 | 3463359.41 | 4.132147e+06 |
31 | 000625.SZ | 20220512 | 9.0416 | 9.2851 | 8.9350 | 9.1025 | 9.3080 | -0.2055 | -2.2078 | 2401654.43 | 2.867413e+06 |
30 | 000625.SZ | 20220513 | 9.1025 | 10.0158 | 9.0111 | 10.0158 | 9.1025 | 0.9133 | 10.0335 | 3869386.93 | 4.886108e+06 |
29 | 000625.SZ | 20220516 | 10.0614 | 10.1451 | 9.7418 | 9.8103 | 10.0158 | -0.2055 | -2.0518 | 3231046.57 | 4.195913e+06 |
28 | 000625.SZ | 20220517 | 9.7189 | 10.6398 | 9.7037 | 10.2821 | 9.8103 | 0.4718 | 4.8092 | 3594912.97 | 4.840887e+06 |
27 | 000625.SZ | 20220518 | 10.2821 | 11.0051 | 9.9777 | 10.1756 | 10.2821 | -0.1065 | -1.0358 | 3949048.20 | 5.460881e+06 |
26 | 000625.SZ | 20220519 | 9.9473 | 10.5713 | 9.8864 | 10.5105 | 10.1756 | 0.3349 | 3.2912 | 3292688.10 | 4.464683e+06 |
25 | 000625.SZ | 20220520 | 10.3887 | 10.4800 | 10.1604 | 10.2669 | 10.5105 | -0.2436 | -2.3177 | 2470887.87 | 3.342778e+06 |
24 | 000625.SZ | 20220523 | 10.2669 | 10.6322 | 10.1375 | 10.4343 | 10.2669 | 0.1674 | 1.6305 | 2488559.94 | 3.394024e+06 |
23 | 000625.SZ | 20220524 | 10.7083 | 11.3400 | 10.6551 | 10.7159 | 10.4343 | 0.2816 | 2.6988 | 4130361.13 | 5.962842e+06 |
22 | 000625.SZ | 20220525 | 10.5409 | 11.2944 | 10.2745 | 11.0660 | 10.7159 | 0.3501 | 3.2671 | 3396696.86 | 4.816627e+06 |
21 | 000625.SZ | 20220526 | 10.8834 | 10.9443 | 10.5789 | 10.7388 | 11.0660 | -0.3272 | -2.9568 | 1916191.31 | 2.708203e+06 |
20 | 000625.SZ | 20220527 | 10.8225 | 11.1117 | 10.5485 | 10.7692 | 10.7388 | 0.0304 | 0.2831 | 1781256.44 | 2.532129e+06 |
19 | 000625.SZ | 20220530 | 10.8910 | 10.9443 | 10.5789 | 10.7616 | 10.7692 | -0.0076 | -0.0706 | 1570927.16 | 2.223216e+06 |
18 | 000625.SZ | 20220531 | 10.7007 | 10.7083 | 10.3582 | 10.6170 | 10.7616 | -0.1446 | -1.3437 | 1892289.81 | 2.621740e+06 |
17 | 000625.SZ | 20220601 | 10.8834 | 11.3020 | 10.8453 | 11.0508 | 10.6170 | 0.4338 | 4.0859 | 2930464.92 | 4.245724e+06 |
16 | 000625.SZ | 20220602 | 10.8377 | 12.0859 | 10.8073 | 11.8043 | 11.0508 | 0.7535 | 6.8185 | 3655846.09 | 5.568282e+06 |
15 | 000625.SZ | 20220606 | 11.7358 | 12.1620 | 11.5683 | 11.9184 | 11.8043 | 0.1141 | 0.9666 | 2941937.33 | 4.578257e+06 |
14 | 000625.SZ | 20220607 | 11.7586 | 11.7814 | 11.4009 | 11.6292 | 11.9184 | -0.2892 | -2.4265 | 1913290.76 | 2.911673e+06 |
13 | 000625.SZ | 20220608 | 11.6216 | 12.0250 | 11.4922 | 11.9413 | 11.6292 | 0.3121 | 2.6838 | 2254946.82 | 3.489635e+06 |
12 | 000625.SZ | 20220609 | 11.8347 | 11.8347 | 11.4466 | 11.4922 | 11.9413 | -0.4491 | -3.7609 | 1467712.92 | 2.230526e+06 |
11 | 000625.SZ | 20220610 | 11.3400 | 12.0250 | 11.2944 | 11.8728 | 11.4922 | 0.3806 | 3.3118 | 1876558.32 | 2.895509e+06 |
10 | 000625.SZ | 20220613 | 11.7967 | 13.0524 | 11.7129 | 12.9307 | 11.8728 | 1.0579 | 8.9103 | 3696010.89 | 6.177846e+06 |
9 | 000625.SZ | 20220614 | 12.6871 | 14.2245 | 12.6415 | 14.2245 | 12.9307 | 1.2938 | 10.0056 | 4249183.95 | 7.488059e+06 |
8 | 000625.SZ | 20220615 | 14.3843 | 15.2215 | 14.1712 | 14.1712 | 14.2245 | -0.0533 | -0.3747 | 4727900.37 | 9.067054e+06 |
7 | 000625.SZ | 20220616 | 14.1712 | 14.6888 | 13.9962 | 14.1408 | 14.1712 | -0.0304 | -0.2145 | 2970896.59 | 5.601199e+06 |
6 | 000625.SZ | 20220617 | 14.0799 | 14.4604 | 13.8211 | 14.3995 | 14.1408 | 0.2587 | 1.8295 | 2463060.39 | 4.609731e+06 |
5 | 000625.SZ | 20220620 | 14.8410 | 15.0312 | 14.3387 | 14.5670 | 14.3995 | 0.1675 | 1.1632 | 2629303.35 | 5.064239e+06 |
4 | 000625.SZ | 20220621 | 14.3082 | 15.4498 | 14.2930 | 15.3737 | 14.5670 | 0.8067 | 5.5379 | 3363875.71 | 6.578857e+06 |
3 | 000625.SZ | 20220622 | 15.3889 | 15.5868 | 14.9932 | 15.0312 | 15.3737 | -0.3425 | -2.2278 | 2619720.99 | 5.236025e+06 |
2 | 000625.SZ | 20220623 | 15.2215 | 16.5382 | 15.0693 | 16.5382 | 15.0312 | 1.5070 | 10.0258 | 3512679.33 | 7.302952e+06 |
1 | 000625.SZ | 20220624 | 16.7056 | 17.4134 | 16.2261 | 17.0100 | 16.5382 | 0.4718 | 2.8528 | 3504568.61 | 7.700924e+06 |
0 | 000625.SZ | 20220627 | 17.5000 | 18.7100 | 16.7100 | 18.5000 | 17.0100 | 1.4900 | 8.7596 | 5753928.73 | 1.027395e+07 |
df_cc = ts.pro_bar(ts_code='601633.SH', adj='qfq', start_date='20220427', end_date='20220627')
df_cc.sort_values(by="trade_date",inplace=True)
df_cc
ts_code | trade_date | open | high | low | close | pre_close | change | pct_chg | vol | amount | |
---|---|---|---|---|---|---|---|---|---|---|---|
39 | 601633.SH | 20220427 | 21.9337 | 22.9316 | 21.3051 | 22.7720 | 22.2630 | 0.5090 | 2.2863 | 341470.02 | 757962.925 |
38 | 601633.SH | 20220428 | 22.5524 | 23.2410 | 22.4526 | 22.9316 | 22.7720 | 0.1596 | 0.7009 | 235284.09 | 538410.271 |
37 | 601633.SH | 20220429 | 23.6102 | 24.9274 | 23.0813 | 24.7677 | 22.9316 | 1.8361 | 8.0069 | 417307.70 | 1005261.810 |
36 | 601633.SH | 20220505 | 24.2488 | 25.1170 | 23.9794 | 24.7079 | 24.7677 | -0.0598 | -0.2414 | 376912.00 | 927626.444 |
35 | 601633.SH | 20220506 | 23.8996 | 24.0093 | 23.6102 | 23.7599 | 24.7079 | -0.9480 | -3.8368 | 227978.49 | 544080.521 |
34 | 601633.SH | 20220509 | 23.4505 | 23.8197 | 23.0214 | 23.2809 | 23.7599 | -0.4790 | -2.0160 | 167211.01 | 390822.373 |
33 | 601633.SH | 20220510 | 22.4526 | 23.1711 | 22.1533 | 23.0015 | 23.2809 | -0.2794 | -1.2001 | 252818.28 | 574889.646 |
32 | 601633.SH | 20220511 | 23.0015 | 25.3066 | 23.0015 | 25.3066 | 23.0015 | 2.3051 | 10.0215 | 312912.35 | 770334.450 |
31 | 601633.SH | 20220512 | 25.7457 | 27.5219 | 25.3964 | 26.8234 | 25.3066 | 1.5168 | 5.9937 | 1049395.34 | 2777063.170 |
30 | 601633.SH | 20220513 | 26.4941 | 29.5077 | 26.2446 | 29.5077 | 26.8234 | 2.6843 | 10.0073 | 1133286.69 | 3169086.473 |
29 | 601633.SH | 20220516 | 30.3160 | 30.3160 | 28.5198 | 28.9389 | 29.5077 | -0.5688 | -1.9276 | 929327.24 | 2710805.031 |
28 | 601633.SH | 20220517 | 28.6995 | 31.8328 | 28.5597 | 31.8328 | 28.9389 | 2.8939 | 10.0000 | 857405.12 | 2633159.103 |
27 | 601633.SH | 20220518 | 31.9326 | 35.0161 | 31.1842 | 33.5991 | 31.8328 | 1.7663 | 5.5487 | 1370972.18 | 4593804.484 |
26 | 601633.SH | 20220519 | 32.8108 | 36.9221 | 32.4615 | 35.6847 | 33.5991 | 2.0856 | 6.2073 | 1127528.77 | 3805122.945 |
25 | 601633.SH | 20220520 | 34.9045 | 35.8443 | 34.4146 | 34.5245 | 35.6844 | -1.1599 | -3.2504 | 866565.33 | 3026872.497 |
24 | 601633.SH | 20220523 | 34.3846 | 35.6144 | 33.1548 | 34.0046 | 34.5245 | -0.5199 | -1.5059 | 1033487.10 | 3530852.856 |
23 | 601633.SH | 20220524 | 35.1944 | 35.9643 | 33.6747 | 34.3646 | 34.0046 | 0.3600 | 1.0587 | 1154648.95 | 4062426.732 |
22 | 601633.SH | 20220525 | 33.5247 | 37.6940 | 32.7948 | 37.0941 | 34.3646 | 2.7295 | 7.9428 | 1149982.27 | 4056564.929 |
21 | 601633.SH | 20220526 | 36.1143 | 36.5942 | 35.0145 | 35.2244 | 37.0941 | -1.8697 | -5.0404 | 843588.02 | 3010855.738 |
20 | 601633.SH | 20220527 | 35.0245 | 36.6542 | 34.0346 | 34.8445 | 35.2244 | -0.3799 | -1.0785 | 778321.46 | 2748631.008 |
19 | 601633.SH | 20220530 | 34.9200 | 35.3000 | 33.5000 | 34.0200 | 34.8500 | -0.8300 | -2.3816 | 685725.84 | 2339470.648 |
18 | 601633.SH | 20220531 | 34.0300 | 34.0400 | 32.1400 | 33.2000 | 34.0200 | -0.8200 | -2.4103 | 763013.82 | 2518375.766 |
17 | 601633.SH | 20220601 | 34.0000 | 34.8000 | 33.6900 | 33.7900 | 33.2000 | 0.5900 | 1.7771 | 766761.94 | 2619704.685 |
16 | 601633.SH | 20220602 | 33.2400 | 36.4900 | 33.2200 | 35.4700 | 33.7900 | 1.6800 | 4.9719 | 907016.54 | 3196874.468 |
15 | 601633.SH | 20220606 | 34.8200 | 37.2400 | 34.8000 | 36.3600 | 35.4700 | 0.8900 | 2.5092 | 891169.06 | 3198770.206 |
14 | 601633.SH | 20220607 | 36.0000 | 36.1600 | 34.5800 | 35.0900 | 36.3600 | -1.2700 | -3.4928 | 579871.20 | 2045914.414 |
13 | 601633.SH | 20220608 | 35.0500 | 37.5000 | 34.8500 | 37.3900 | 35.0900 | 2.3000 | 6.5546 | 873766.34 | 3183634.937 |
12 | 601633.SH | 20220609 | 37.2500 | 37.2500 | 35.5500 | 35.5800 | 37.3900 | -1.8100 | -4.8409 | 638815.97 | 2302870.364 |
11 | 601633.SH | 20220610 | 35.1800 | 37.2000 | 34.9500 | 36.5200 | 35.5800 | 0.9400 | 2.6419 | 720066.72 | 2617492.454 |
10 | 601633.SH | 20220613 | 35.9000 | 38.9700 | 35.5000 | 38.4400 | 36.5200 | 1.9200 | 5.2574 | 864491.14 | 3286654.568 |
9 | 601633.SH | 20220614 | 37.6000 | 41.9900 | 36.9900 | 41.2300 | 38.4400 | 2.7900 | 7.2581 | 923584.90 | 3606184.652 |
8 | 601633.SH | 20220615 | 41.0000 | 44.5200 | 39.4000 | 39.4400 | 41.2300 | -1.7900 | -4.3415 | 1122114.77 | 4677419.539 |
7 | 601633.SH | 20220616 | 39.1400 | 40.2600 | 38.3600 | 38.6100 | 39.4400 | -0.8300 | -2.1045 | 591751.33 | 2318071.822 |
6 | 601633.SH | 20220617 | 38.1100 | 39.7900 | 38.0000 | 39.1000 | 38.6100 | 0.4900 | 1.2691 | 506979.99 | 1981230.766 |
5 | 601633.SH | 20220620 | 39.1000 | 39.7100 | 38.4000 | 38.9400 | 39.1000 | -0.1600 | -0.4092 | 410093.72 | 1600731.789 |
4 | 601633.SH | 20220621 | 38.7600 | 38.9200 | 37.0800 | 38.3200 | 38.9400 | -0.6200 | -1.5922 | 514513.57 | 1956043.991 |
3 | 601633.SH | 20220622 | 38.3100 | 39.2800 | 37.8900 | 37.9900 | 38.3200 | -0.3300 | -0.8612 | 382944.07 | 1475721.830 |
2 | 601633.SH | 20220623 | 38.5000 | 40.4900 | 38.5000 | 40.4100 | 37.9900 | 2.4200 | 6.3701 | 737531.29 | 2922807.528 |
1 | 601633.SH | 20220624 | 40.8000 | 41.1900 | 39.4900 | 39.9100 | 40.4100 | -0.5000 | -1.2373 | 594487.88 | 2390130.687 |
0 | 601633.SH | 20220627 | 39.9500 | 42.3300 | 39.0600 | 40.9500 | 39.9100 | 1.0400 | 2.6059 | 722113.37 | 2927615.901 |
# 计算收益率并且合并数据
df_byd['r_byd']=(df_byd['close'] - df_byd['close'].shift(1)) / df_byd['close'].shift(1)
df_ca['r_ca']=(df_ca['close'] - df_ca['close'].shift(1)) / df_ca['close'].shift(1)
df_cc['r_cc']=(df_cc['close'] - df_cc['close'].shift(1)) / df_cc['close'].shift(1)
df_byd=df_byd.dropna()
df_ca=df_ca.dropna()
df_cc=df_cc.dropna()
df_portfolio=pd.DataFrame([df_byd['r_byd'],df_ca['r_ca'],df_cc['r_cc']]).T
df_portfolio.head()
r_byd | r_ca | r_cc | |
---|---|---|---|
38 | -0.012893 | 0.039289 | 0.007009 |
37 | 0.047504 | 0.099801 | 0.080069 |
36 | 0.023868 | 0.100282 | -0.002414 |
35 | -0.027010 | 0.022572 | -0.038368 |
34 | -0.038624 | -0.033964 | -0.020160 |
min(df_portfolio.r_byd)
-0.04810298102981026
import scipy.optimize as sco
# 投资组合
rets=df_portfolio
n=len(rets.columns)
# 优化的约束条件:资金的权重和为1,下面表示np.sum(x)-1 eq 0
cons=({'type':'eq','fun':lambda x:np.sum(x)-1})
#参数取值范围
bnds=tuple((0,1) for x in range(n))
# 生成初始权重
w_initial=n*[1./n,]
# 计算最有权重
opts_sharpe=sco.minimize(min_func_sharpe,w_initial,method='SLSQP',bounds=bnds,constraints=cons)
opts_sharpe
fun: -9.70554120401185
jac: array([-6.16312027e-05, 2.01463699e-05, 1.61020207e+00])
message: 'Optimization terminated successfully'
nfev: 25
nit: 6
njev: 6
status: 0
success: True
x: array([0.24684656, 0.75315344, 0. ])
# fun对应最优夏普比率,注意取负值,x为权重
opts_sharpe['x'].round(2)
array([0.25, 0.75, 0. ])
# 以上面投资组合计算预期收益率
rets=df_portfolio
portfolio_stat([0.25,0.75,0])
# 得到p_ret,p_vol,p_sr 预期收益率,风险,夏普比率
# 根据结果而言,这年画收益率是真的不高,我还是故意选择的这三个股票在这段时间涨的比较好的。
# 这里我没有检验各个样本是否符合正态分布,可能是组合表现不佳的原因之一,就不多加叙述了
array([5.63126075, 0.58021321, 9.70550256])