投資組合的收益率與風險
- 1 不同相關系數下投資組合標準差隨投資比例變動的情況
- 1.1 設定calc_mean函式為采用的投資組合方式
- 1.2 以x/50為權重(其中x屬于0到50)進行投資組合(其實就是0到1中間等距抽權重)
- 1.3 計算不同相關系數的股票組合對應收益值
- 1.4 不同相關系數均值和標準差關系圖
- 2 Markowitz模型實作
- 2.1 獲取各只股票日線行情資料
- 2.2 計算每只股票的日收益率(個股回報率)并將其合并
- 2.3 了解各股票的日收益率及累計收益率時序圖
- 2.4 了解各股票之間的相關性
- 2.5 定義MeanVariance類,通過輸入收益率序列計算最優資產比例,繪制最小方差前緣曲線
- 2.5.1 定義MeanVariance類及類內函式
- 2.5.2 呼叫minvar函式計算最小方差
- 2.5.3 呼叫frontierCurve繪制效率前沿曲線
- 2.5.4 將資料拆分為訓練和測驗資料,輸出根據訓練資料計算的效率前沿曲線
- 2.5.5 給定收益率下,計算方差最小時對應的五種股票的比例權重
- 2.5.6 繪制收益率曲線
- 2.5.7 與隨機生成的組合進行比較
- 3 Black-Litterman模型
- 3.1 創建blacklitterman函式,計算后驗收益期望及協方差
- 3.2 創建blminVar函式,輸出最優資產配比
- 3.2.1 看不懂 就拆開看的:
- 3.2.2 帶例子計算結果去啦!
不同相關系數下投資組合標準差隨投資比例變動的情況
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib
%matplotlib inline
設定calc_mean函式為采用的投資組合方式
def calc_mean(frac):
return (0.08* frac+0.15*(1-frac))
0.08* (1/50)+0.15*(1-(1/50))
0.14859999999999998
以x/50為權重(其中x屬于0到50)進行投資組合(其實就是0到1中間等距抽權重)
mean=list(map(calc_mean,[x/50 for x in range(51)]))
mean
[0.15,
0.14859999999999998,
0.1472,
0.14579999999999999,
0.1444,
0.14300000000000002,
0.1416,
0.1402,
0.1388,
0.1374,
0.136,
0.1346,
0.13319999999999999,
0.1318,
0.13040000000000002,
0.129,
0.1276,
0.12619999999999998,
0.1248,
0.1234,
0.122,
0.12060000000000001,
0.1192,
0.1178,
0.1164,
0.11499999999999999,
0.1136,
0.1122,
0.1108,
0.1094,
0.108,
0.1066,
0.1052,
0.1038,
0.10239999999999999,
0.101,
0.0996,
0.09820000000000001,
0.0968,
0.0954,
0.094,
0.0926,
0.0912,
0.0898,
0.0884,
0.08700000000000001,
0.0856,
0.08420000000000001,
0.0828,
0.0814,
0.08]
[x/50 for x in range(51)] #0-1之間組合資料
[0.0,
0.02,
0.04,
0.06,
0.08,
0.1,
0.12,
0.14,
0.16,
0.18,
0.2,
0.22,
0.24,
0.26,
0.28,
0.3,
0.32,
0.34,
0.36,
0.38,
0.4,
0.42,
0.44,
0.46,
0.48,
0.5,
0.52,
0.54,
0.56,
0.58,
0.6,
0.62,
0.64,
0.66,
0.68,
0.7,
0.72,
0.74,
0.76,
0.78,
0.8,
0.82,
0.84,
0.86,
0.88,
0.9,
0.92,
0.94,
0.96,
0.98,
1.0]
計算不同相關系數的股票組合對應收益值
公式為(0.12x+0.25(1-x))的完全平方展開式,其中交叉項還乘以了相關系數,0.12和0.25分別為兩種股票的收益率,x和(1-x)為標準差(或者權重,這里還沒弄懂),最終得值為均值,
import math
sd_mat=np.array([list(map(lambda x :math.sqrt( (x**2)*0.12**2 \
+ ((1-x)**2)*0.25**2\
+ 2*x*(1-x)*(-1.5+i*0.5)*0.12*0.25)
,[x/50 for x in range(51)])) for i in range(1,6)]) #range表示左閉右開區間
sd_mat
array([[0.25 , 0.2426 , 0.2352 , 0.2278 , 0.2204 ,
0.213 , 0.2056 , 0.1982 , 0.1908 , 0.1834 ,
0.176 , 0.1686 , 0.1612 , 0.1538 , 0.1464 ,
0.139 , 0.1316 , 0.1242 , 0.1168 , 0.1094 ,
0.102 , 0.0946 , 0.0872 , 0.0798 , 0.0724 ,
0.065 , 0.0576 , 0.0502 , 0.0428 , 0.0354 ,
0.028 , 0.0206 , 0.0132 , 0.0058 , 0.0016 ,
0.009 , 0.0164 , 0.0238 , 0.0312 , 0.0386 ,
0.046 , 0.0534 , 0.0608 , 0.0682 , 0.0756 ,
0.083 , 0.0904 , 0.0978 , 0.1052 , 0.1126 ,
0.12 ],
[0.25 , 0.24380886, 0.23763636, 0.231484 , 0.22535341,
0.21924644, 0.2131651 , 0.20711166, 0.20108864, 0.19509885,
0.18914545, 0.18323198, 0.17736245, 0.17154137, 0.16577382,
0.16006561, 0.15442331, 0.14885443, 0.1433675 , 0.13797232,
0.13268007, 0.12750357, 0.1224575 , 0.11755867, 0.11282624,
0.10828204, 0.10395076, 0.0998601 , 0.09604082, 0.09252654,
0.08935323, 0.08655842, 0.08417981, 0.08225351, 0.08081188,
0.07988116, 0.07947931, 0.07961432, 0.0802835 , 0.08147368,
0.08316249, 0.08532034, 0.08791268, 0.09090237, 0.09425158,
0.09792344, 0.10188307, 0.10609826, 0.11053977, 0.11518142,
0.12 ],
[0.25 , 0.24501175, 0.240048 , 0.23511027, 0.23020026,
0.22531977, 0.22047077, 0.21565537, 0.21087589, 0.20613481,
0.20143485, 0.19677896, 0.19217034, 0.18761247, 0.18310915,
0.17866449, 0.17428299, 0.16996953, 0.16572942, 0.16156844,
0.15749286, 0.15350948, 0.14962567, 0.14584937, 0.14218917,
0.13865425, 0.13525443, 0.13200015, 0.12890244, 0.12597285,
0.12322337, 0.12066632, 0.11831416, 0.11617934, 0.11427406,
0.11260995, 0.11119784, 0.11004744, 0.10916703, 0.10856316,
0.10824047, 0.10820148, 0.10844648, 0.10897357, 0.10977869,
0.11085576, 0.11219697, 0.11379297, 0.11563321, 0.11770624,
0.12 ],
[0.25 , 0.24620877, 0.24243564, 0.23868146, 0.23494714,
0.23123365, 0.227542 , 0.22387327, 0.22022861, 0.21660923,
0.21301643, 0.20945157, 0.2059161 , 0.20241156, 0.19893959,
0.19550192, 0.19210039, 0.18873696, 0.1854137 , 0.18213281,
0.17889662, 0.1757076 , 0.17256836, 0.16948168, 0.16645047,
0.16347783, 0.160567 , 0.1577214 , 0.15494464, 0.15224047,
0.14961283, 0.14706584, 0.14460373, 0.14223094, 0.13995199,
0.13777155, 0.13569436, 0.13372524, 0.13186903, 0.13013055,
0.12851459, 0.12702582, 0.12566877, 0.12444774, 0.12336677,
0.12242957, 0.12163947, 0.12099934, 0.12051158, 0.12017803,
0.12 ],
[0.25 , 0.2474 , 0.2448 , 0.2422 , 0.2396 ,
0.237 , 0.2344 , 0.2318 , 0.2292 , 0.2266 ,
0.224 , 0.2214 , 0.2188 , 0.2162 , 0.2136 ,
0.211 , 0.2084 , 0.2058 , 0.2032 , 0.2006 ,
0.198 , 0.1954 , 0.1928 , 0.1902 , 0.1876 ,
0.185 , 0.1824 , 0.1798 , 0.1772 , 0.1746 ,
0.172 , 0.1694 , 0.1668 , 0.1642 , 0.1616 ,
0.159 , 0.1564 , 0.1538 , 0.1512 , 0.1486 ,
0.146 , 0.1434 , 0.1408 , 0.1382 , 0.1356 ,
0.133 , 0.1304 , 0.1278 , 0.1252 , 0.1226 ,
0.12 ]])
sd_mat.shape
(5, 51)
不同相關系數均值和標準差關系圖
label為相關系數,橫軸為標準差,縱軸為均值,
plt.plot(sd_mat[0,:],mean,label="-1")
plt.plot(sd_mat[1,:],mean,label="-0.5")
plt.plot(sd_mat[2,:],mean,label="0")
plt.plot(sd_mat[3,:],mean,label="0.5")
plt.plot(sd_mat[4,:],mean,label="1")
plt.legend(loc="upper left")
<matplotlib.legend.Legend at 0x18896d0b7c0>

Markowitz模型實作
先匯入股票,本次實作使用股票為600004、600015、600023、600033、600183,分別對應白云機場、華夏銀行、浙能電力、福建高速和生益科技股票,
目前我國000或002開頭的就是深證的,600開頭的是上證的,300開頭的是創業板zhi 200開頭的是深圳B股,900開頭的是上海B股,
獲取各只股票日線行情資料
import tushare as ts
pro = ts.pro_api('4c1fa508ab60e554d221c55a47dfa557a6c7bfd0c239b45657c2262d')
df = pro.daily(ts_code='600004.SH', start_date='20200101', end_date='20201231')
df.head()
| ts_code | trade_date | open | high | low | close | pre_close | change | pct_chg | vol | amount | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 600004.SH | 20201231 | 13.80 | 14.30 | 13.70 | 14.13 | 13.63 | 0.50 | 3.6684 | 186855.09 | 261417.827 |
| 1 | 600004.SH | 20201230 | 13.36 | 13.72 | 13.25 | 13.63 | 13.37 | 0.26 | 1.9447 | 105098.32 | 142205.693 |
| 2 | 600004.SH | 20201229 | 13.18 | 13.61 | 13.18 | 13.37 | 13.27 | 0.10 | 0.7536 | 97057.08 | 130418.052 |
| 3 | 600004.SH | 20201228 | 13.43 | 13.45 | 13.17 | 13.27 | 13.48 | -0.21 | -1.5579 | 120737.86 | 160222.485 |
| 4 | 600004.SH | 20201225 | 13.25 | 13.50 | 13.22 | 13.48 | 13.35 | 0.13 | 0.9738 | 57026.12 | 76510.480 |
byjc = df.set_index(["trade_date"])
byjc.index = pd.to_datetime(byjc.index)
byjc.head(10)
| ts_code | open | high | low | close | pre_close | change | pct_chg | vol | amount | |
|---|---|---|---|---|---|---|---|---|---|---|
| trade_date | ||||||||||
| 2020-12-31 | 600004.SH | 13.80 | 14.30 | 13.70 | 14.13 | 13.63 | 0.50 | 3.6684 | 186855.09 | 261417.827 |
| 2020-12-30 | 600004.SH | 13.36 | 13.72 | 13.25 | 13.63 | 13.37 | 0.26 | 1.9447 | 105098.32 | 142205.693 |
| 2020-12-29 | 600004.SH | 13.18 | 13.61 | 13.18 | 13.37 | 13.27 | 0.10 | 0.7536 | 97057.08 | 130418.052 |
| 2020-12-28 | 600004.SH | 13.43 | 13.45 | 13.17 | 13.27 | 13.48 | -0.21 | -1.5579 | 120737.86 | 160222.485 |
| 2020-12-25 | 600004.SH | 13.25 | 13.50 | 13.22 | 13.48 | 13.35 | 0.13 | 0.9738 | 57026.12 | 76510.480 |
| 2020-12-24 | 600004.SH | 13.35 | 13.41 | 13.18 | 13.35 | 13.35 | 0.00 | 0.0000 | 78080.01 | 104002.222 |
| 2020-12-23 | 600004.SH | 13.39 | 13.46 | 13.25 | 13.35 | 13.35 | 0.00 | 0.0000 | 122316.53 | 163204.891 |
| 2020-12-22 | 600004.SH | 13.96 | 13.96 | 13.31 | 13.35 | 14.12 | -0.77 | -5.4533 | 256419.53 | 348439.957 |
| 2020-12-21 | 600004.SH | 14.05 | 14.15 | 13.63 | 14.12 | 14.21 | -0.09 | -0.6334 | 128751.81 | 179205.692 |
| 2020-12-18 | 600004.SH | 14.43 | 14.43 | 14.15 | 14.21 | 14.43 | -0.22 | -1.5246 | 82641.45 | 117739.517 |
data = pro.daily(ts_code='600015.SH', start_date='20200101', end_date='20201231')
hxyh = data.set_index(["trade_date"])
hxyh.index=pd.to_datetime(hxyh.index) #時間型別
hxyh.head(10)
| ts_code | open | high | low | close | pre_close | change | pct_chg | vol | amount | |
|---|---|---|---|---|---|---|---|---|---|---|
| trade_date | ||||||||||
| 2020-12-31 | 600015.SH | 6.17 | 6.28 | 6.17 | 6.25 | 6.19 | 0.06 | 0.9693 | 323628.00 | 202126.611 |
| 2020-12-30 | 600015.SH | 6.14 | 6.19 | 6.12 | 6.19 | 6.15 | 0.04 | 0.6504 | 171216.96 | 105291.236 |
| 2020-12-29 | 600015.SH | 6.14 | 6.17 | 6.13 | 6.15 | 6.14 | 0.01 | 0.1629 | 138161.26 | 84991.588 |
| 2020-12-28 | 600015.SH | 6.16 | 6.18 | 6.12 | 6.14 | 6.17 | -0.03 | -0.4862 | 142068.40 | 87339.651 |
| 2020-12-25 | 600015.SH | 6.15 | 6.21 | 6.15 | 6.17 | 6.17 | 0.00 | 0.0000 | 166727.73 | 102964.436 |
| 2020-12-24 | 600015.SH | 6.18 | 6.22 | 6.14 | 6.17 | 6.18 | -0.01 | -0.1618 | 109642.01 | 67734.194 |
| 2020-12-23 | 600015.SH | 6.18 | 6.19 | 6.13 | 6.18 | 6.18 | 0.00 | 0.0000 | 151969.90 | 93657.059 |
| 2020-12-22 | 600015.SH | 6.23 | 6.24 | 6.16 | 6.18 | 6.24 | -0.06 | -0.9615 | 175320.62 | 108670.014 |
| 2020-12-21 | 600015.SH | 6.23 | 6.26 | 6.20 | 6.24 | 6.23 | 0.01 | 0.1605 | 131370.60 | 81852.468 |
| 2020-12-18 | 600015.SH | 6.23 | 6.27 | 6.21 | 6.23 | 6.24 | -0.01 | -0.1603 | 150797.28 | 94042.457 |
data = pro.daily(ts_code='600023.SH', start_date='20200101', end_date='20201231')
zndl = data.set_index(["trade_date"])
zndl.index=pd.to_datetime(zndl.index) #時間型別
zndl.head(10)
| ts_code | open | high | low | close | pre_close | change | pct_chg | vol | amount | |
|---|---|---|---|---|---|---|---|---|---|---|
| trade_date | ||||||||||
| 2020-12-31 | 600023.SH | 3.64 | 3.66 | 3.62 | 3.63 | 3.64 | -0.01 | -0.2747 | 276557.88 | 100496.614 |
| 2020-12-30 | 600023.SH | 3.63 | 3.69 | 3.62 | 3.64 | 3.64 | 0.00 | 0.0000 | 345081.00 | 126011.396 |
| 2020-12-29 | 600023.SH | 3.76 | 3.77 | 3.63 | 3.64 | 3.75 | -0.11 | -2.9333 | 486175.37 | 179125.733 |
| 2020-12-28 | 600023.SH | 3.65 | 3.81 | 3.64 | 3.75 | 3.63 | 0.12 | 3.3058 | 812157.21 | 304098.705 |
| 2020-12-25 | 600023.SH | 3.60 | 3.77 | 3.60 | 3.63 | 3.60 | 0.03 | 0.8333 | 802186.21 | 294034.916 |
| 2020-12-24 | 600023.SH | 3.66 | 3.66 | 3.59 | 3.60 | 3.66 | -0.06 | -1.6393 | 216392.19 | 78215.857 |
| 2020-12-23 | 600023.SH | 3.63 | 3.67 | 3.62 | 3.66 | 3.63 | 0.03 | 0.8264 | 246516.04 | 89848.931 |
| 2020-12-22 | 600023.SH | 3.70 | 3.71 | 3.62 | 3.63 | 3.71 | -0.08 | -2.1563 | 236203.13 | 86417.953 |
| 2020-12-21 | 600023.SH | 3.72 | 3.73 | 3.68 | 3.71 | 3.74 | -0.03 | -0.8021 | 306758.67 | 113636.876 |
| 2020-12-18 | 600023.SH | 3.70 | 3.78 | 3.69 | 3.74 | 3.68 | 0.06 | 1.6304 | 496335.82 | 185874.480 |
data = pro.daily(ts_code='600033.SH', start_date='20200101', end_date='20201231')
fjgs = data.set_index(["trade_date"])
fjgs.index=pd.to_datetime(fjgs.index) #時間型別
fjgs.head(10)
| ts_code | open | high | low | close | pre_close | change | pct_chg | vol | amount | |
|---|---|---|---|---|---|---|---|---|---|---|
| trade_date | ||||||||||
| 2020-12-31 | 600033.SH | 2.63 | 2.64 | 2.61 | 2.63 | 2.64 | -0.01 | -0.3788 | 66428.48 | 17454.118 |
| 2020-12-30 | 600033.SH | 2.62 | 2.65 | 2.61 | 2.64 | 2.62 | 0.02 | 0.7634 | 64786.08 | 17069.822 |
| 2020-12-29 | 600033.SH | 2.61 | 2.64 | 2.60 | 2.62 | 2.61 | 0.01 | 0.3831 | 61694.88 | 16166.056 |
| 2020-12-28 | 600033.SH | 2.62 | 2.63 | 2.60 | 2.61 | 2.63 | -0.02 | -0.7605 | 47187.00 | 12331.493 |
| 2020-12-25 | 600033.SH | 2.59 | 2.63 | 2.59 | 2.63 | 2.60 | 0.03 | 1.1538 | 57316.73 | 14985.076 |
| 2020-12-24 | 600033.SH | 2.62 | 2.62 | 2.59 | 2.60 | 2.61 | -0.01 | -0.3831 | 37202.50 | 9677.080 |
| 2020-12-23 | 600033.SH | 2.62 | 2.63 | 2.60 | 2.61 | 2.61 | 0.00 | 0.0000 | 35652.00 | 9312.229 |
| 2020-12-22 | 600033.SH | 2.65 | 2.65 | 2.61 | 2.61 | 2.66 | -0.05 | -1.8797 | 36789.00 | 9663.675 |
| 2020-12-21 | 600033.SH | 2.64 | 2.66 | 2.63 | 2.66 | 2.65 | 0.01 | 0.3774 | 39729.19 | 10508.296 |
| 2020-12-18 | 600033.SH | 2.64 | 2.66 | 2.63 | 2.65 | 2.64 | 0.01 | 0.3788 | 48981.25 | 12971.882 |
data = pro.daily(ts_code='600183.SH', start_date='20200101', end_date='20201231')
sykj = data.set_index(["trade_date"])
sykj.index=pd.to_datetime(sykj.index) #時間型別
sykj.head(10)
| ts_code | open | high | low | close | pre_close | change | pct_chg | vol | amount | |
|---|---|---|---|---|---|---|---|---|---|---|
| trade_date | ||||||||||
| 2020-12-31 | 600183.SH | 28.20 | 28.48 | 27.70 | 28.16 | 28.09 | 0.07 | 0.2492 | 236546.60 | 666296.114 |
| 2020-12-30 | 600183.SH | 27.60 | 28.44 | 27.52 | 28.09 | 27.72 | 0.37 | 1.3348 | 298485.52 | 837217.068 |
| 2020-12-29 | 600183.SH | 28.05 | 28.11 | 27.38 | 27.72 | 28.16 | -0.44 | -1.5625 | 274469.65 | 762046.593 |
| 2020-12-28 | 600183.SH | 27.30 | 28.66 | 27.26 | 28.16 | 27.50 | 0.66 | 2.4000 | 368864.23 | 1038064.670 |
| 2020-12-25 | 600183.SH | 25.54 | 27.64 | 25.53 | 27.50 | 25.53 | 1.97 | 7.7164 | 405867.59 | 1091263.537 |
| 2020-12-24 | 600183.SH | 25.53 | 26.28 | 25.48 | 25.53 | 25.48 | 0.05 | 0.1962 | 218026.21 | 562524.467 |
| 2020-12-23 | 600183.SH | 26.35 | 26.38 | 25.00 | 25.48 | 26.03 | -0.55 | -2.1129 | 420599.35 | 1067254.221 |
| 2020-12-22 | 600183.SH | 26.90 | 27.00 | 26.00 | 26.03 | 27.18 | -1.15 | -4.2311 | 237254.71 | 627783.299 |
| 2020-12-21 | 600183.SH | 26.83 | 27.71 | 26.63 | 27.18 | 27.00 | 0.18 | 0.6667 | 276529.00 | 753021.804 |
| 2020-12-18 | 600183.SH | 27.07 | 27.58 | 26.80 | 27.00 | 26.85 | 0.15 | 0.5587 | 220284.43 | 598219.499 |
計算每只股票的日收益率(個股回報率)并將其合并
import ffn
byjc_Dretwd=ffn.to_returns(byjc.close)
hxyh_Dretwd=ffn.to_returns(hxyh.close)
zndl_Dretwd=ffn.to_returns(zndl.close)
fjgs_Dretwd=ffn.to_returns(fjgs.close)
sykj_Dretwd=ffn.to_returns(sykj.close)
sh_return=pd.concat([fjgs_Dretwd,zndl_Dretwd,sykj_Dretwd,hxyh_Dretwd,byjc_Dretwd],axis=1) #重組為一個df
sh_return.columns = ['fjgs','zndl','sykj','hxyh','byjc'] #重命名列名
sh_return=sh_return.dropna()#dropna函式用來洗掉有缺失值的行
sh_return.head()
| fjgs | zndl | sykj | hxyh | byjc | |
|---|---|---|---|---|---|
| trade_date | |||||
| 2020-12-30 | 0.003802 | 0.002755 | -0.002486 | -0.009600 | -0.035386 |
| 2020-12-29 | -0.007576 | 0.000000 | -0.013172 | -0.006462 | -0.019076 |
| 2020-12-28 | -0.003817 | 0.030220 | 0.015873 | -0.001626 | -0.007479 |
| 2020-12-25 | 0.007663 | -0.032000 | -0.023438 | 0.004886 | 0.015825 |
| 2020-12-24 | -0.011407 | -0.008264 | -0.071636 | 0.000000 | -0.009644 |
了解各股票的日收益率及累計收益率時序圖
sh_return.plot()
plt.title('Daily Return of 5 sStocks(2020)')
plt.legend(loc='lower center',bbox_to_anchor=(0.5,-0.3),
ncol=5,fancybox=True,shadow=True)
plt.show()
<ipython-input-17-18e69f52f319>:5: UserWarning: Matplotlib is currently using agg, which is a non-GUI backend, so cannot show the figure.
plt.show()

cumreturn=(1+sh_return).cumprod()
cumreturn.plot()
plt.title('Cumulative Return of 5 Stocks(2020)')
plt.show()
<ipython-input-18-ccd1c3bea7db>:4: UserWarning: Matplotlib is currently using agg, which is a non-GUI backend, so cannot show the figure.
plt.show()

了解各股票之間的相關性
sh_return.corr()
| fjgs | zndl | sykj | hxyh | byjc | |
|---|---|---|---|---|---|
| fjgs | 1.000000 | 0.675856 | 0.363203 | 0.642483 | 0.450363 |
| zndl | 0.675856 | 1.000000 | 0.318658 | 0.608911 | 0.358668 |
| sykj | 0.363203 | 0.318658 | 1.000000 | 0.307890 | 0.295727 |
| hxyh | 0.642483 | 0.608911 | 0.307890 | 1.000000 | 0.424358 |
| byjc | 0.450363 | 0.358668 | 0.295727 | 0.424358 | 1.000000 |
若股票之間的相關性太高,投資組合降低風險的效果就比較有限,從香港系數矩陣可以看出,五只股票之間都是正相關,福建高速和浙能電力、華夏銀行相關性最高,
定義MeanVariance類,通過輸入收益率序列計算最優資產比例,繪制最小方差前緣曲線
定義MeanVariance類及類內函式
import ffn
from scipy import linalg
class MeanVariance:
#定義構造器,傳入收益率資料(dataframe格式的每日收益率)
def __init__(self,returns): #初始化資料集合,五種股票資料
self.returns=returns
#定義最小化方差的函式,即求解二次規劃
def minVar(self,goalRet): #計算最小方差
covs=np.array(self.returns.cov())
means=np.array(self.returns.mean())
L1=np.append(np.append(covs.swapaxes(0,1),[means],0),
[np.ones(len(means))],0).swapaxes(0,1)
L2=list(np.ones(len(means)))
L2.extend([0,0])
L3=list(means)
L3.extend([0,0])
L4=np.array([L2,L3])
L=np.append(L1,L4,0)
results=linalg.solve(L,np.append(np.zeros(len(means)),[1,goalRet],0))
return(np.array([list(self.returns.columns),results[:-2]]))
#定義繪制最小方差前緣曲線函式
def frontierCurve(self): #繪圖,根據線性求解
goals=[x/500000 for x in range(-100,4000)]
variances=list(map(lambda x: self.calVar(self.minVar(x)[1,:].astype(np.float)),goals))
plt.plot(variances,goals) #方差-收益率圖
#給定各資產的比例,計算收益率的均值
def meanRet(self,fracs): #fracs概率
meanRisky=ffn.to_returns(self.returns).mean()
assert len(meanRisky)==len(fracs), 'Length of fractions must be equal to number of assets'
return(np.sum(np.multiply(meanRisky,np.array(fracs))))
#給定各資產的比例,計算收益率方差
def calVar(self,fracs):
return(np.dot(np.dot(fracs,self.returns.cov()),fracs))
呼叫minvar函式計算最小方差
minvar=MeanVariance(sh_return)
呼叫frontierCurve繪制效率前沿曲線
minvar.frontierCurve() #橫軸為方差,縱軸為收益,曲線為收益方差最低點

將資料拆分為訓練和測驗資料,輸出根據訓練資料計算的效率前沿曲線
sh_return.shape
(242, 5)
train_set=sh_return[0:121]
test_set=sh_return[122:242] #訓練資料和測驗資料,各匯入一半
varMinmizer=MeanVariance(train_set)
varMinmizer.frontierCurve() #收益方差最低點

給定收益率下,計算方差最小時對應的五種股票的比例權重
goal_return=0.003
protfolio_weight=varMinmizer.minVar(goal_return) #計算最小方差.根據五種股票
protfolio_weight #權重,五種股票的比例權重
array([['fjgs', 'zndl', 'sykj', 'hxyh', 'byjc'],
['-0.185777320912347', '-1.8333107604295968',
'0.38673711936434396', '2.0333149700802164',
'0.5990359918973837']], dtype='<U32')
test_return=np.dot(test_set,np.array([protfolio_weight[1,:].astype(np.float)]).swapaxes(0,1))
#按照交換x,y
test_return
array([[-0.11011845],
[-0.02524191],
[-0.06059084],
[-0.00483673],
[-0.00067331],
[ 0.00451267],
[-0.02368934],
[ 0.02203717],
[ 0.00173678],
[ 0.07425185],
[ 0.0112505 ],
[-0.01023086],
[-0.04548689],
[ 0.04493778],
[-0.02015694],
[ 0.0052846 ],
[ 0.00265628],
[ 0.02267791],
[ 0.0288354 ],
[-0.00508686],
[ 0.02599153],
[ 0.02081656],
[-0.00166454],
[-0.04485105],
[-0.03813144],
[-0.04204255],
[ 0.03486829],
[-0.04028191],
[ 0.00842363],
[ 0.01696757],
[ 0.06047486],
[ 0.03047909],
[-0.05145005],
[-0.00333348],
[-0.00292845],
[ 0.00730291],
[ 0.02302764],
[ 0.00071038],
[ 0.01599063],
[-0.02301472],
[ 0.05399119],
[ 0.05057536],
[ 0.00619487],
[-0.04426579],
[-0.06304755],
[ 0.02011673],
[ 0.04067394],
[-0.02014949],
[-0.00400891],
[-0.0259005 ],
[-0.01740082],
[-0.05066975],
[ 0.03218413],
[ 0.02201851],
[-0.02564261],
[ 0.02496331],
[ 0.01314226],
[-0.01007401],
[-0.02022558],
[-0.02382847],
[-0.00250703],
[-0.01666069],
[-0.01190292],
[ 0.01046496],
[ 0.03835301],
[ 0.03398579],
[ 0.0005996 ],
[-0.04287169],
[-0.02749323],
[ 0.06616573],
[-0.00028395],
[ 0.05502029],
[ 0.0366752 ],
[ 0.03932765],
[ 0.08592724],
[ 0.02159489],
[ 0.01792505],
[ 0.00881541],
[-0.04477628],
[ 0.03570067],
[ 0.03264928],
[-0.00825414],
[ 0.00851066],
[-0.01358265],
[-0.04444564],
[ 0.00871176],
[-0.0079298 ],
[ 0.04009519],
[-0.00403245],
[-0.01284608],
[-0.01690251],
[-0.04568924],
[ 0.00241797],
[ 0.0133465 ],
[-0.0304876 ],
[-0.03241099],
[ 0.00303069],
[-0.00297659],
[-0.00146255],
[-0.00240845],
[-0.0395943 ],
[-0.01543629],
[ 0.03707392],
[ 0.00505044],
[-0.0290022 ],
[ 0.05648995],
[-0.01158704],
[ 0.00279889],
[-0.00393927],
[ 0.00092292],
[ 0.01125273],
[-0.00371833],
[ 0.03248409],
[-0.0327072 ],
[-0.03644614],
[-0.0076972 ],
[ 0.01118346],
[-0.00150503],
[ 0.00326623],
[ 0.00645175]])
sim_weight=np.random.uniform(0,1,(100,5)) #亂數
sim_weight
array([[9.02596959e-01, 3.76262930e-01, 6.78788501e-01, 3.72752382e-01,
3.81890155e-01],
[4.61790022e-01, 2.50318083e-01, 8.12363330e-01, 9.47705004e-01,
6.54625324e-01],
[7.70635263e-01, 6.78646675e-01, 5.35714827e-01, 4.40542592e-02,
5.79451488e-01],
[7.94560717e-01, 3.91893060e-02, 1.84737034e-01, 8.96622279e-01,
4.55253890e-01],
[5.00623474e-01, 4.57421136e-01, 9.37412800e-01, 4.68915861e-01,
2.51780445e-01],
[6.10727677e-01, 9.10018989e-01, 1.90229137e-01, 5.89624002e-01,
7.50811768e-01],
[6.54119584e-01, 6.99277911e-01, 7.86371064e-01, 5.42726325e-01,
5.25777733e-01],
[3.57751269e-01, 7.62158579e-01, 5.33726920e-01, 3.58773657e-01,
2.33096611e-01],
[4.93000589e-01, 6.86923780e-01, 4.68621878e-01, 5.60846914e-01,
9.08581075e-01],
[7.04448567e-01, 4.81023531e-01, 2.95615051e-01, 2.24994103e-01,
4.09386928e-01],
[7.75254913e-03, 5.32295178e-01, 8.22935438e-01, 1.13852844e-01,
6.70073088e-01],
[2.79925781e-01, 1.57646996e-01, 4.30745258e-01, 7.75570703e-02,
7.57233696e-02],
[9.02327119e-01, 6.22353094e-01, 8.11022610e-01, 4.79416372e-01,
9.90680610e-01],
[5.28365437e-03, 7.60598096e-02, 3.11953117e-01, 3.50564099e-01,
2.50126713e-01],
[4.09351464e-01, 4.05636701e-01, 8.53661068e-01, 8.72152555e-01,
9.30888148e-01],
[7.17377715e-01, 9.43990271e-01, 3.77244832e-01, 4.73779134e-01,
5.35254976e-01],
[8.19747596e-01, 8.36042977e-01, 8.14826653e-01, 2.83596123e-01,
2.33435627e-01],
[8.10657368e-01, 2.04881553e-01, 9.76210748e-01, 6.77514916e-01,
2.41308170e-02],
[5.06362334e-01, 7.48858420e-02, 8.69922564e-01, 1.36639804e-02,
1.39033752e-01],
[1.53885649e-01, 5.30735655e-01, 9.70589007e-01, 4.72322755e-01,
3.93527157e-01],
[1.17698436e-01, 9.84057538e-01, 9.50760636e-01, 6.81740321e-01,
6.91331760e-01],
[4.76974660e-01, 8.12390566e-01, 2.17269527e-01, 9.33557049e-01,
5.12890057e-01],
[6.65764616e-01, 5.91170479e-01, 4.83041600e-01, 8.15889943e-01,
5.79378415e-01],
[4.22279247e-01, 4.55583133e-01, 7.80749390e-01, 7.90695717e-01,
7.44457541e-02],
[8.33391878e-01, 8.61807069e-01, 9.47168723e-03, 5.56376255e-01,
3.55746683e-01],
[5.99938911e-01, 4.84690799e-01, 7.51076755e-01, 2.79942344e-01,
8.95771536e-01],
[1.65167861e-02, 1.03481429e-01, 8.87673006e-01, 4.59212157e-01,
4.87966300e-01],
[2.70083716e-01, 8.58539156e-01, 2.52079363e-02, 8.33757013e-01,
2.72905216e-01],
[7.50730234e-01, 4.24462497e-04, 3.26366654e-01, 2.58576867e-01,
1.30843726e-01],
[1.29889095e-01, 8.90247465e-01, 4.14531222e-01, 1.26835523e-01,
1.13266528e-02],
[1.39842913e-01, 5.86007597e-01, 2.93179565e-01, 4.46639656e-01,
5.45572753e-02],
[1.96100798e-01, 4.81756392e-01, 8.17861476e-01, 8.62922569e-01,
6.94755944e-02],
[8.80579877e-01, 2.77329884e-01, 1.09251298e-01, 7.67789095e-01,
8.58970487e-01],
[6.48493753e-01, 9.72395101e-01, 3.32044412e-02, 8.25528293e-01,
8.37446628e-01],
[2.70624530e-01, 8.58610165e-01, 9.51243666e-02, 3.32908942e-01,
4.65119505e-01],
[3.44186845e-01, 6.20875263e-01, 6.47787000e-01, 9.41466289e-01,
8.88133838e-02],
[6.96415284e-01, 3.35618259e-01, 4.27412104e-01, 9.75705624e-01,
9.98000317e-01],
[4.35619177e-01, 3.87558779e-01, 4.30763422e-01, 9.25248547e-01,
9.57756296e-02],
[9.57884243e-01, 2.11188490e-01, 5.44391353e-01, 7.41643153e-01,
8.12112030e-01],
[4.20178450e-01, 3.69513387e-02, 3.34522980e-01, 1.50243105e-01,
3.11842687e-02],
[2.49210170e-01, 6.01143933e-01, 5.96449615e-01, 6.67530386e-01,
1.98877734e-01],
[8.66697603e-01, 1.67607911e-01, 5.18357829e-01, 1.80723852e-01,
3.64400552e-01],
[8.51683579e-01, 2.28259511e-01, 4.94088371e-01, 8.87069298e-02,
4.05412532e-01],
[4.52325481e-02, 6.82542923e-01, 2.48142239e-01, 4.91822233e-01,
1.76566522e-01],
[1.76382700e-01, 4.23572994e-01, 1.86778371e-01, 6.42219544e-01,
6.63508978e-01],
[6.11881870e-01, 8.90490557e-01, 9.94668782e-01, 9.46196757e-01,
4.34194946e-01],
[5.02852239e-01, 1.98142332e-01, 9.92453904e-01, 8.84549444e-01,
6.97299807e-01],
[8.65473471e-01, 4.50734526e-01, 2.88710480e-01, 8.24001155e-01,
8.24163231e-01],
[2.52135339e-01, 1.52863848e-01, 8.61560440e-01, 1.92514934e-01,
8.44152804e-01],
[1.30846531e-01, 2.02477494e-01, 8.41907758e-01, 2.72048612e-01,
2.79161559e-01],
[5.22543328e-01, 9.79903944e-01, 7.57297551e-01, 9.09711783e-01,
8.11010876e-01],
[3.90452171e-01, 4.04869166e-01, 4.10778467e-01, 5.38810790e-02,
7.20165821e-01],
[9.84090706e-01, 2.07825930e-02, 3.73142851e-01, 4.66086568e-01,
3.01294420e-01],
[2.96729994e-02, 7.22559447e-01, 3.25238703e-01, 5.20593100e-01,
2.81266789e-01],
[6.45034069e-01, 8.88655388e-01, 7.98535281e-01, 9.18093455e-01,
5.51861958e-01],
[6.17507555e-01, 6.53052173e-01, 8.76951611e-01, 4.23447372e-01,
8.88272806e-01],
[9.95110802e-01, 8.13853611e-01, 9.42655235e-01, 4.41823485e-01,
1.32271916e-02],
[7.45223475e-01, 8.34551563e-01, 1.08675841e-01, 4.24253511e-01,
8.11314020e-01],
[9.22853995e-01, 8.24845800e-01, 3.35043686e-01, 1.88414328e-01,
7.77752679e-02],
[4.79855679e-01, 6.58275935e-02, 2.87447223e-01, 4.38889243e-02,
1.55655620e-01],
[9.71216934e-01, 8.30405436e-01, 3.09952015e-01, 7.86804698e-01,
6.75085450e-02],
[4.05749690e-01, 1.39407459e-01, 7.80232674e-01, 9.65163821e-01,
1.01830685e-01],
[3.20528051e-01, 5.39637812e-02, 4.31657841e-01, 7.04632230e-02,
5.40182605e-02],
[4.51025449e-01, 6.24396996e-01, 2.17317856e-01, 6.91048568e-01,
3.27145505e-01],
[5.78734756e-02, 5.66975138e-01, 5.82714729e-01, 1.06343643e-02,
8.73370778e-01],
[1.99935573e-01, 8.08797242e-01, 5.42644344e-01, 3.62700167e-01,
8.10791718e-01],
[7.87148319e-01, 7.49812561e-01, 6.93030256e-02, 6.96712770e-01,
3.50987536e-01],
[4.12114459e-01, 6.69651141e-01, 4.42083535e-01, 6.51143854e-01,
2.09044025e-01],
[4.57205547e-01, 4.53447780e-01, 4.41328214e-01, 3.19826298e-01,
6.95390510e-01],
[2.76607663e-01, 7.45829743e-01, 8.76821099e-01, 9.08213010e-01,
4.98635096e-01],
[6.12872530e-01, 8.77373005e-02, 6.52744603e-01, 1.77231628e-02,
3.63441882e-01],
[9.55249114e-01, 8.62395856e-01, 6.22376413e-01, 1.45106388e-01,
5.74500790e-01],
[5.05321770e-01, 1.72383345e-01, 2.69803510e-01, 9.48454018e-01,
8.18452610e-01],
[3.50867963e-01, 4.29409449e-01, 7.50936406e-01, 3.59995051e-01,
9.35785501e-01],
[1.49625448e-01, 1.45928612e-02, 8.11472733e-01, 9.26829363e-01,
1.66884799e-01],
[6.99032463e-02, 8.09651763e-01, 3.97792919e-01, 8.07733356e-01,
6.42889670e-01],
[3.21057772e-01, 9.68237260e-01, 8.70586733e-01, 2.91539429e-01,
9.20640741e-01],
[7.87248426e-01, 3.53537253e-01, 2.95357885e-01, 8.69106856e-01,
7.34115519e-01],
[2.36478799e-01, 3.40149684e-01, 9.44648843e-01, 7.53158760e-01,
1.06725521e-01],
[6.08081572e-01, 4.12868708e-01, 1.23856045e-01, 7.60754627e-01,
6.86373032e-01],
[7.15315473e-01, 2.17327945e-01, 1.65380585e-01, 1.33889168e-01,
9.76392372e-01],
[3.42413401e-01, 8.21412746e-01, 8.93184528e-01, 2.97280317e-01,
3.79123005e-01],
[2.93882121e-01, 5.44256489e-01, 5.56119146e-01, 6.85895129e-01,
4.18436783e-02],
[5.54351561e-01, 1.43035494e-01, 9.83685259e-01, 7.92416601e-01,
1.81446608e-01],
[8.02655646e-01, 6.99615383e-02, 8.49461656e-01, 3.91742126e-01,
2.36464094e-01],
[3.36669649e-02, 1.34884405e-01, 7.68615141e-01, 7.88732161e-01,
8.07690867e-01],
[6.91802860e-01, 4.60674563e-01, 2.91990705e-02, 3.55472558e-01,
2.97092808e-01],
[2.87012974e-01, 8.56598445e-01, 2.24723853e-01, 7.49230662e-01,
4.55577780e-01],
[6.61091320e-01, 1.15149507e-01, 4.02977806e-01, 8.95355549e-01,
4.27400442e-01],
[1.61653341e-01, 6.80827584e-01, 3.56344842e-01, 8.68873642e-01,
8.27962997e-01],
[5.81998497e-01, 2.72759624e-02, 7.98603526e-01, 6.36773965e-01,
1.06708038e-01],
[9.67964595e-01, 3.97669431e-01, 8.13862210e-02, 1.26654237e-01,
3.89938429e-01],
[6.69173975e-01, 1.26097567e-02, 4.72127236e-01, 1.78969329e-01,
9.95198099e-01],
[1.99196882e-01, 4.07419375e-01, 1.08011725e-01, 4.70669873e-01,
2.59156493e-01],
[5.36425977e-01, 9.75941413e-02, 6.99387359e-01, 7.08227556e-01,
1.70702509e-01],
[8.35400787e-01, 6.86454909e-02, 3.37686524e-01, 9.10780025e-01,
7.16111389e-01],
[2.89169565e-01, 4.92159303e-01, 6.06209542e-01, 7.16603968e-01,
1.19856973e-01],
[8.21844583e-01, 5.62624705e-01, 9.10118730e-01, 8.33129636e-01,
9.55516226e-01],
[8.68937084e-01, 9.50778274e-01, 9.84988311e-01, 5.21978793e-01,
7.38793945e-01],
[7.94385085e-01, 6.24590473e-01, 4.61838436e-01, 6.29618835e-01,
5.34655742e-01]])
test_return=pd.DataFrame(test_return,index=test_set.index) #新建dataframe
test_return
| 0 | |
|---|---|
| trade_date | |
| 2020-07-03 | -0.110118 |
| 2020-07-02 | -0.025242 |
| 2020-07-01 | -0.060591 |
| 2020-06-30 | -0.004837 |
| 2020-06-29 | -0.000673 |
| ... | ... |
| 2020-01-08 | -0.007697 |
| 2020-01-07 | 0.011183 |
| 2020-01-06 | -0.001505 |
| 2020-01-03 | 0.003266 |
| 2020-01-02 | 0.006452 |
120 rows × 1 columns
test_cum_return=(1+test_return).cumprod()#累積收益
test_cum_return.head
<bound method NDFrame.head of 0
trade_date
2020-07-03 0.889882
2020-07-02 0.867419
2020-07-01 0.814862
2020-06-30 0.810920
2020-06-29 0.810374
... ...
2020-01-08 0.965167
2020-01-07 0.975961
2020-01-06 0.974492
2020-01-03 0.977675
2020-01-02 0.983983
[120 rows x 1 columns]>
test_cum_return.index
DatetimeIndex(['2020-07-03', '2020-07-02', '2020-07-01', '2020-06-30',
'2020-06-29', '2020-06-24', '2020-06-23', '2020-06-22',
'2020-06-19', '2020-06-18',
...
'2020-01-15', '2020-01-14', '2020-01-13', '2020-01-10',
'2020-01-09', '2020-01-08', '2020-01-07', '2020-01-06',
'2020-01-03', '2020-01-02'],
dtype='datetime64[ns]', name='trade_date', length=120, freq=None)
test_cum_return.columns = ['cum_return'] #重命名列名
test_cum_return
| cum_return | |
|---|---|
| trade_date | |
| 2020-07-03 | 0.889882 |
| 2020-07-02 | 0.867419 |
| 2020-07-01 | 0.814862 |
| 2020-06-30 | 0.810920 |
| 2020-06-29 | 0.810374 |
| ... | ... |
| 2020-01-08 | 0.965167 |
| 2020-01-07 | 0.975961 |
| 2020-01-06 | 0.974492 |
| 2020-01-03 | 0.977675 |
| 2020-01-02 | 0.983983 |
120 rows × 1 columns
繪制收益率曲線
plt.plot(test_cum_return.index,test_cum_return)
[<matplotlib.lines.Line2D at 0x1889ad79250>]

與隨機生成的組合進行比較
sim_weight=np.random.uniform(0,1,(100,5)) #(0,1)之間生成亂數,大小是(100,5)
sim_weight=np.apply_along_axis(lambda x:x /sum(x),1,sim_weight)
#權重,numpy.apply_along_axis()函式回傳的是一個根據func()函式以及維度axis運算后得到的陣列.
sim_weight
array([[2.15710380e-01, 3.36014900e-02, 3.52812998e-01, 2.25394003e-02,
3.75335732e-01],
[1.58004653e-01, 2.29000886e-02, 2.25653116e-01, 2.54353241e-01,
3.39088901e-01],
[2.46635746e-01, 1.97933264e-01, 2.93933362e-01, 2.26955925e-01,
3.45417023e-02],
[1.81360931e-01, 2.40309226e-01, 1.99632515e-02, 1.76374715e-01,
3.81991875e-01],
[1.89561391e-01, 1.80771066e-01, 2.26772421e-01, 2.73908729e-01,
1.28986392e-01],
[2.84803939e-01, 6.36540873e-02, 1.30749020e-01, 2.03368025e-01,
3.17424929e-01],
[3.19401286e-01, 5.96941721e-02, 3.47614496e-01, 2.45560529e-01,
2.77295172e-02],
[1.50899206e-01, 2.27189539e-01, 2.58833824e-01, 8.99617418e-02,
2.73115689e-01],
[1.95500520e-01, 7.36123151e-02, 2.98103862e-06, 6.27570996e-01,
1.03313187e-01],
[2.08077300e-01, 2.12013901e-01, 2.51080153e-01, 3.17070738e-01,
1.17579076e-02],
[2.17765162e-01, 1.08443799e-01, 2.78651418e-01, 2.47894727e-01,
1.47244895e-01],
[1.95987198e-01, 1.54514812e-01, 2.07100145e-01, 2.33745196e-01,
2.08652650e-01],
[3.15280429e-01, 1.01903038e-01, 3.12310770e-01, 8.91078002e-02,
1.81397963e-01],
[2.37775282e-01, 1.70584380e-01, 2.58668719e-01, 3.08281958e-01,
2.46896611e-02],
[1.35432702e-01, 1.50142874e-01, 8.79858084e-02, 3.25280372e-01,
3.01158244e-01],
[9.48712818e-04, 3.11365673e-01, 1.06820413e-01, 2.64695497e-01,
3.16169704e-01],
[1.40243201e-01, 1.18591964e-01, 2.18570743e-01, 2.61465156e-01,
2.61128936e-01],
[1.64520440e-01, 3.44380420e-01, 2.51611086e-01, 1.66548599e-01,
7.29394541e-02],
[2.84951705e-01, 2.31736686e-01, 1.68303753e-01, 6.93825076e-02,
2.45625348e-01],
[1.96861615e-02, 2.44749740e-01, 5.07177341e-01, 1.02352289e-01,
1.26034469e-01],
[1.85485303e-01, 1.54990916e-01, 2.70442691e-01, 1.92948783e-01,
1.96132306e-01],
[2.50392802e-01, 3.48561942e-01, 4.09345075e-02, 2.15747002e-01,
1.44363747e-01],
[2.37950955e-01, 2.59599786e-01, 1.52431301e-01, 1.57300240e-01,
1.92717719e-01],
[2.19107407e-01, 1.25430955e-01, 2.77723211e-01, 1.38552750e-01,
2.39185677e-01],
[1.77089302e-01, 2.33276958e-01, 3.28293098e-01, 2.15310392e-01,
4.60302494e-02],
[2.55165676e-01, 2.84403926e-01, 1.13054630e-01, 1.67431827e-02,
3.30632585e-01],
[1.16642459e-01, 2.41868153e-01, 1.25568317e-01, 1.22613475e-01,
3.93307595e-01],
[2.86751792e-02, 1.46461087e-02, 4.22284580e-01, 1.08888568e-01,
4.25505564e-01],
[2.16435319e-01, 1.99630958e-01, 1.04932277e-01, 2.34668889e-01,
2.44332557e-01],
[2.50149591e-01, 2.87753083e-02, 3.24471163e-01, 2.78963962e-01,
1.17639976e-01],
[7.03347549e-02, 3.50697129e-01, 3.11758845e-01, 7.37654094e-02,
1.93443862e-01],
[1.35150010e-01, 1.63345906e-01, 2.69017254e-01, 2.10693778e-01,
2.21793052e-01],
[2.01212678e-01, 3.84996871e-01, 1.86379373e-01, 4.33139626e-02,
1.84097116e-01],
[3.09692458e-01, 6.53743845e-02, 2.11675699e-01, 1.84087741e-01,
2.29169717e-01],
[5.99411870e-02, 1.70114724e-01, 6.62921057e-02, 3.46750361e-01,
3.56901622e-01],
[2.23905659e-01, 1.55867394e-01, 2.08600894e-01, 1.94978637e-01,
2.16647417e-01],
[2.03086684e-01, 2.65281317e-01, 1.10597786e-01, 4.21024096e-01,
1.01169359e-05],
[2.43043492e-02, 2.06083107e-01, 3.37943170e-01, 2.43808012e-01,
1.87861362e-01],
[1.55071671e-01, 2.06030798e-01, 1.74062446e-01, 2.11290972e-01,
2.53544112e-01],
[5.86474461e-02, 4.41831496e-01, 2.52952511e-02, 4.23126216e-01,
5.10995910e-02],
[9.94975503e-02, 2.76636397e-01, 1.07207563e-01, 2.71420752e-01,
2.45237738e-01],
[2.29005892e-01, 2.89867826e-01, 5.58590928e-02, 1.51555992e-01,
2.73711196e-01],
[1.43747173e-01, 8.27803954e-02, 3.19485984e-01, 3.03883091e-01,
1.50103357e-01],
[2.75732323e-01, 1.29558909e-01, 1.63272991e-01, 2.99053295e-01,
1.32382481e-01],
[1.64526630e-01, 2.57521161e-01, 2.86481651e-01, 2.33509333e-01,
5.79612248e-02],
[6.34696266e-02, 2.19750011e-01, 2.72246965e-01, 2.85904176e-01,
1.58629222e-01],
[3.60572520e-01, 6.45109386e-02, 4.49786430e-02, 2.24713503e-01,
3.05224395e-01],
[1.34454684e-02, 1.94850081e-01, 3.01170712e-01, 3.01571049e-01,
1.88962689e-01],
[6.53210956e-02, 4.54132965e-01, 1.58957712e-01, 2.12879541e-01,
1.08708686e-01],
[7.65133979e-02, 2.29623966e-02, 1.94773977e-01, 2.57611700e-01,
4.48138529e-01],
[7.10028706e-03, 1.76159234e-01, 3.41841761e-01, 2.37419476e-01,
2.37479242e-01],
[2.01947698e-01, 1.73420997e-02, 4.03626199e-01, 2.72095535e-01,
1.04988468e-01],
[6.87892632e-02, 3.06799052e-01, 3.01944539e-01, 4.00451750e-02,
2.82421970e-01],
[2.27605475e-01, 2.42849226e-01, 3.48084101e-02, 1.68129285e-01,
3.26607605e-01],
[2.90479254e-01, 2.74752356e-01, 1.17176961e-01, 4.48938588e-02,
2.72697570e-01],
[2.40863650e-01, 8.53837457e-02, 7.72600590e-02, 2.37088894e-01,
3.59403651e-01],
[2.16620651e-01, 2.13497347e-01, 1.92780456e-01, 1.48951225e-01,
2.28150320e-01],
[1.68058333e-01, 3.61103135e-01, 1.09495019e-01, 2.86961973e-01,
7.43815394e-02],
[1.43299482e-01, 3.24870407e-01, 6.68362081e-02, 1.06270787e-01,
3.58723116e-01],
[1.93693122e-01, 3.28493561e-01, 1.17629308e-01, 3.32925482e-01,
2.72585273e-02],
[1.31238234e-01, 2.90987611e-01, 5.04308708e-02, 1.37452008e-01,
3.89891276e-01],
[3.20489444e-01, 1.27198019e-01, 3.18005768e-02, 3.03340522e-01,
2.17171438e-01],
[1.82661938e-01, 2.66020119e-01, 2.72516025e-01, 2.80374056e-02,
2.50764513e-01],
[3.95109126e-02, 2.27522271e-01, 1.48717548e-01, 3.14956277e-01,
2.69292991e-01],
[2.19056591e-01, 7.26045899e-02, 4.44426722e-01, 2.29366900e-02,
2.40975407e-01],
[2.59742063e-01, 2.95591668e-02, 5.08163842e-02, 1.75721814e-01,
4.84160573e-01],
[3.95285792e-01, 7.01380246e-02, 2.86333364e-01, 1.39871373e-01,
1.08371446e-01],
[2.74824695e-01, 6.30446266e-03, 2.10454587e-01, 2.14509417e-01,
2.93906838e-01],
[4.30142190e-01, 6.84748065e-02, 2.52081589e-01, 1.69448731e-01,
7.98526834e-02],
[4.23252875e-03, 2.24854782e-01, 3.24988744e-01, 3.29064622e-01,
1.16859324e-01],
[2.86516002e-01, 3.38568082e-01, 1.95953733e-01, 5.77201515e-02,
1.21242032e-01],
[2.52018486e-01, 1.30107025e-01, 2.16385880e-01, 2.51224181e-01,
1.50264428e-01],
[8.73392189e-02, 1.65495600e-01, 3.54225451e-01, 3.13233931e-01,
7.97057990e-02],
[2.29582252e-01, 3.33487817e-01, 7.13499342e-02, 1.35469401e-01,
2.30110596e-01],
[1.10334826e-02, 8.23627540e-02, 2.64219338e-01, 3.50534353e-01,
2.91850072e-01],
[2.51429396e-01, 1.08662457e-01, 2.37057162e-01, 2.25474778e-01,
1.77376207e-01],
[1.17829206e-01, 4.00904842e-02, 2.66774305e-01, 2.83143358e-01,
2.92162648e-01],
[1.22817097e-01, 6.62502141e-02, 3.23229286e-01, 1.73243087e-01,
3.14460315e-01],
[1.97963547e-01, 1.53187502e-01, 9.15982708e-02, 9.74238156e-02,
4.59826865e-01],
[1.63329768e-01, 2.52927873e-01, 8.48656786e-02, 2.85387407e-01,
2.13489273e-01],
[2.49089727e-01, 1.11324427e-01, 4.29936058e-01, 1.37002074e-01,
7.26477143e-02],
[2.82091585e-01, 2.16096986e-02, 1.97555562e-01, 2.52726967e-01,
2.46016187e-01],
[1.47518090e-01, 2.69419100e-01, 3.18056620e-01, 1.94893723e-01,
7.01124660e-02],
[5.26515083e-02, 2.79188405e-02, 4.10848226e-01, 1.75515007e-01,
3.33066418e-01],
[2.00436836e-01, 1.90147381e-01, 2.57453882e-01, 8.39497499e-02,
2.68012151e-01],
[5.34156737e-02, 3.55650593e-02, 3.98793566e-01, 3.34770108e-01,
1.77455593e-01],
[1.48785472e-01, 1.38299321e-01, 2.04166875e-01, 1.77291874e-01,
3.31456457e-01],
[6.31350973e-02, 3.00511024e-01, 7.92409052e-02, 3.23628905e-01,
2.33484068e-01],
[4.30981494e-02, 4.63168024e-01, 1.18329907e-01, 3.28276115e-01,
4.71278041e-02],
[2.92287901e-01, 2.65500202e-01, 1.69560284e-01, 2.19350264e-01,
5.33013490e-02],
[2.07227809e-01, 3.08249831e-01, 2.59191788e-01, 1.50275489e-01,
7.50550827e-02],
[2.63637285e-01, 1.78688209e-01, 6.10027610e-02, 3.18891618e-01,
1.77780127e-01],
[2.66101585e-01, 1.35994431e-01, 2.66853208e-01, 2.06925616e-01,
1.24125161e-01],
[3.98594221e-01, 7.20453832e-02, 5.43301947e-02, 1.20640837e-01,
3.54389364e-01],
[3.32397799e-01, 8.57398533e-02, 8.93782341e-02, 1.16078791e-01,
3.76405322e-01],
[3.12067107e-01, 1.43370430e-01, 2.96921812e-01, 9.30800499e-02,
1.54560602e-01],
[1.48366564e-01, 2.23040459e-01, 2.24621396e-01, 3.05071330e-01,
9.89002509e-02],
[2.52870783e-01, 7.50960949e-02, 6.44838403e-02, 3.66138716e-01,
2.41410566e-01],
[1.84012108e-01, 2.63814905e-02, 1.93513118e-01, 2.61234936e-01,
3.34858347e-01],
[1.13036969e-01, 2.18235168e-01, 2.39444596e-01, 6.05908522e-02,
3.68692414e-01]])
sim_return=np.dot(test_set,sim_weight.swapaxes(0,1)) #np二維陣列資料型別
sim_return=pd.DataFrame(sim_return,index=test_cum_return.index) #轉化為pandas dataFrame
sim_sum_return=(1+sim_return).cumprod() #累計收益
plt.plot(sim_sum_return) #綜合繪圖
[<matplotlib.lines.Line2D at 0x1889e3c0be0>,
<matplotlib.lines.Line2D at 0x1889e288ac0>,
<matplotlib.lines.Line2D at 0x1889e2886a0>,
<matplotlib.lines.Line2D at 0x1889e288d00>,
<matplotlib.lines.Line2D at 0x1889e288040>,
<matplotlib.lines.Line2D at 0x1889e288f70>,
<matplotlib.lines.Line2D at 0x1889e288f40>,
<matplotlib.lines.Line2D at 0x1889e2885b0>,
<matplotlib.lines.Line2D at 0x1889e288790>,
<matplotlib.lines.Line2D at 0x1889e288ca0>,
<matplotlib.lines.Line2D at 0x1889e3c0040>,
<matplotlib.lines.Line2D at 0x1889e288610>,
<matplotlib.lines.Line2D at 0x1889e288730>,
<matplotlib.lines.Line2D at 0x1889e288940>,
<matplotlib.lines.Line2D at 0x1889e2888e0>,
<matplotlib.lines.Line2D at 0x1889e288250>,
<matplotlib.lines.Line2D at 0x1889e288280>,
<matplotlib.lines.Line2D at 0x1889e288490>,
<matplotlib.lines.Line2D at 0x1889e288430>,
<matplotlib.lines.Line2D at 0x1889e2880a0>,
<matplotlib.lines.Line2D at 0x1889e316670>,
<matplotlib.lines.Line2D at 0x1889e316640>,
<matplotlib.lines.Line2D at 0x1889e316b20>,
<matplotlib.lines.Line2D at 0x1889e316ac0>,
<matplotlib.lines.Line2D at 0x1889e316fa0>,
<matplotlib.lines.Line2D at 0x1889e316eb0>,
<matplotlib.lines.Line2D at 0x1889e316c10>,
<matplotlib.lines.Line2D at 0x1889e3168b0>,
<matplotlib.lines.Line2D at 0x1889e316130>,
<matplotlib.lines.Line2D at 0x1889e316160>,
<matplotlib.lines.Line2D at 0x1889e3165b0>,
<matplotlib.lines.Line2D at 0x1889e316730>,
<matplotlib.lines.Line2D at 0x1889e316880>,
<matplotlib.lines.Line2D at 0x1889e316940>,
<matplotlib.lines.Line2D at 0x1889e291190>,
<matplotlib.lines.Line2D at 0x1889e291280>,
<matplotlib.lines.Line2D at 0x1889e291bb0>,
<matplotlib.lines.Line2D at 0x1889e291fa0>,
<matplotlib.lines.Line2D at 0x1889e291f40>,
<matplotlib.lines.Line2D at 0x1889e291100>,
<matplotlib.lines.Line2D at 0x1889e291040>,
<matplotlib.lines.Line2D at 0x1889e291b20>,
<matplotlib.lines.Line2D at 0x1889e291a90>,
<matplotlib.lines.Line2D at 0x1889e291eb0>,
<matplotlib.lines.Line2D at 0x1889e291760>,
<matplotlib.lines.Line2D at 0x1889e291880>,
<matplotlib.lines.Line2D at 0x1889e2917f0>,
<matplotlib.lines.Line2D at 0x1889e2919d0>,
<matplotlib.lines.Line2D at 0x1889e291370>,
<matplotlib.lines.Line2D at 0x1889e2914c0>,
<matplotlib.lines.Line2D at 0x1889e291430>,
<matplotlib.lines.Line2D at 0x1889e291610>,
<matplotlib.lines.Line2D at 0x1889e2911f0>,
<matplotlib.lines.Line2D at 0x1889e23bb50>,
<matplotlib.lines.Line2D at 0x1889e23ba60>,
<matplotlib.lines.Line2D at 0x1889e23b760>,
<matplotlib.lines.Line2D at 0x1889e23b3a0>,
<matplotlib.lines.Line2D at 0x1889e23b1f0>,
<matplotlib.lines.Line2D at 0x1889e23ba30>,
<matplotlib.lines.Line2D at 0x1889e23bb80>,
<matplotlib.lines.Line2D at 0x1889e23bca0>,
<matplotlib.lines.Line2D at 0x1889e23b4f0>,
<matplotlib.lines.Line2D at 0x1889e23b490>,
<matplotlib.lines.Line2D at 0x1889e23bd90>,
<matplotlib.lines.Line2D at 0x1889e23bac0>,
<matplotlib.lines.Line2D at 0x1889debf100>,
<matplotlib.lines.Line2D at 0x1889debfbb0>,
<matplotlib.lines.Line2D at 0x1889debfbe0>,
<matplotlib.lines.Line2D at 0x1889debfca0>,
<matplotlib.lines.Line2D at 0x1889debfe50>,
<matplotlib.lines.Line2D at 0x1889debff70>,
<matplotlib.lines.Line2D at 0x1889debfcd0>,
<matplotlib.lines.Line2D at 0x1889e4adfd0>,
<matplotlib.lines.Line2D at 0x1889e4adeb0>,
<matplotlib.lines.Line2D at 0x1889ccaf790>,
<matplotlib.lines.Line2D at 0x1889ccafe80>,
<matplotlib.lines.Line2D at 0x1889ccaf550>,
<matplotlib.lines.Line2D at 0x1889d14ec40>,
<matplotlib.lines.Line2D at 0x1889d14e910>,
<matplotlib.lines.Line2D at 0x1889d14e2e0>,
<matplotlib.lines.Line2D at 0x1889d14e130>,
<matplotlib.lines.Line2D at 0x1889d14e0d0>,
<matplotlib.lines.Line2D at 0x1889d14eee0>,
<matplotlib.lines.Line2D at 0x1889d14eb20>,
<matplotlib.lines.Line2D at 0x1889d14e580>,
<matplotlib.lines.Line2D at 0x1889d14ee50>,
<matplotlib.lines.Line2D at 0x1889d14e9a0>,
<matplotlib.lines.Line2D at 0x1889d14e640>,
<matplotlib.lines.Line2D at 0x1889d14e970>,
<matplotlib.lines.Line2D at 0x1889d14eb80>,
<matplotlib.lines.Line2D at 0x1889d14e880>,
<matplotlib.lines.Line2D at 0x1889d14e6d0>,
<matplotlib.lines.Line2D at 0x1889d6d7d00>,
<matplotlib.lines.Line2D at 0x1889d6d7fa0>,
<matplotlib.lines.Line2D at 0x1889d6d7f40>,
<matplotlib.lines.Line2D at 0x1889d6d7b80>,
<matplotlib.lines.Line2D at 0x1889d6d79a0>,
<matplotlib.lines.Line2D at 0x1889d6d75e0>,
<matplotlib.lines.Line2D at 0x1889d6d7130>,
<matplotlib.lines.Line2D at 0x1889d6d7f10>]

plt.plot(test_cum_return.index,test_cum_return,color="green")##收益率曲線
[<matplotlib.lines.Line2D at 0x1889e75bd00>]

經比較發現,我們用MeanVariance得到的收益率曲線處于所有隨機生成組合的中上部,
Black-Litterman模型
定義函式
創建blacklitterman函式,計算后驗收益期望及協方差
def blacklitterman(returns,tau, P, Q): #協方差
mu=returns.mean()
sigma=returns.cov()
pi1=mu
ts = tau * sigma
Omega = np.dot(np.dot(P,ts),P.T) * np.eye(Q.shape[0])
middle = linalg.inv(np.dot(np.dot(P,ts),P.T) + Omega)
er = np.expand_dims(pi1,axis=0).T + np.dot(np.dot(np.dot(ts,P.T),middle),
(Q - np.expand_dims(np.dot(P,pi1.T),axis=1)))
posteriorSigma = sigma + ts - np.dot(ts.dot(P.T).dot(middle).dot(P),ts)
return [er, posteriorSigma]
繼續延用前面五只股票資產分配的例子,zip里要加上投資者的個人觀點進行分析,現在假設某股票分析師認為白云機場、華夏銀行、浙能電力、生益科技四只股票的日均收益率將達到0.3%;兩只交通類股票白云機場和福建高速的日均收益將比浙能電力高0.1%,以此為根據構建個人觀點,
下面將構建投資人的個人觀點,構建資產選擇矩陣P,假設分析師認為:
- 前四只股票日均收益率為日均0.3%
- q1只交通股日均收益比浙能電力高0.1%
pick1=np.array([1,0,1,1,1])
pick1
array([1, 0, 1, 1, 1])
q1=np.array([0.003*4])
q1
array([0.012])
pick2=np.array([0.5,0.5,0,0,-1])
pick2
array([ 0.5, 0.5, 0. , 0. , -1. ])
q2=np.array([0.001])
q2
array([0.001])
P=np.array([pick1,pick2])
P
array([[ 1. , 0. , 1. , 1. , 1. ],
[ 0.5, 0.5, 0. , 0. , -1. ]])
Q=np.array([q1,q2])
Q
array([[0.012],
[0.001]])
- blacklitterman函式輸出值res第一個內容為后驗分布期望,第二個內容為后驗分布協方差
- blacklitterman函式輸入值第一個為股票歷史收益率,第二個為主觀觀點相對于先驗資訊的比重,第三、四個為代表投資人的看法,
res=blacklitterman(sh_return,0.1,P,Q)
res
[array([[0.00145304],
[0.0012935 ],
[0.00171238],
[0.00159785],
[0.00166382]]),
fjgs zndl sykj hxyh byjc
fjgs 0.000138 0.000114 0.000134 0.000093 0.000133
zndl 0.000114 0.000211 0.000145 0.000108 0.000132
sykj 0.000134 0.000145 0.001076 0.000118 0.000234
hxyh 0.000093 0.000108 0.000118 0.000154 0.000131
byjc 0.000133 0.000132 0.000234 0.000131 0.000643]
p_mean=pd.DataFrame(res[0],index=sh_return.columns,columns=['posterior_mean'])
p_mean
| posterior_mean | |
|---|---|
| fjgs | 0.001453 |
| zndl | 0.001294 |
| sykj | 0.001712 |
| hxyh | 0.001598 |
| byjc | 0.001664 |
以上就是五只股票的后驗收益期望值
res[1]
| fjgs | zndl | sykj | hxyh | byjc | |
|---|---|---|---|---|---|
| fjgs | 0.000138 | 0.000114 | 0.000134 | 0.000093 | 0.000133 |
| zndl | 0.000114 | 0.000211 | 0.000145 | 0.000108 | 0.000132 |
| sykj | 0.000134 | 0.000145 | 0.001076 | 0.000118 | 0.000234 |
| hxyh | 0.000093 | 0.000108 | 0.000118 | 0.000154 | 0.000131 |
| byjc | 0.000133 | 0.000132 | 0.000234 | 0.000131 | 0.000643 |
創建blminVar函式,輸出最優資產配比
以上就是五只股票的后驗分布協方差
得到了后驗收益的期望值和協方差之后,我們就可以利用Markowitz模型進行資產的配置,我們定義新的函式blminVar()以求解資產配置權重,
- 輸入變數有blacklitterman函式輸出值(blres)和投資人的目標收益率(goalRet),
- 輸出值為各只股票的資產配比,
def blminVar(blres,goalRet): #輸出最優資產配比
covs=np.array(blres[1])
means=np.array(blres[0])
L1=np.append(np.append((covs.swapaxes(0,1)),[means.flatten()],0),
[np.ones(len(means))],0).swapaxes(0,1)
L2=list(np.ones(len(means)))
L2.extend([0,0])
L3=list(means)
L3=means
#L3.extend([0,0])
L3=np.append(L3,0)
L3=np.append(L3,0)
L4=np.array([L2,L3])
L=np.append(L1,L4,0)
results=linalg.solve(L,np.append(np.zeros(len(means)),[1,goalRet],0))
return(pd.DataFrame(results[:-2],
index=blres[1].columns,columns=['p_weight']))
看不懂 就拆開看的:
means=np.array(res[0])
means
array([[0.00145304],
[0.0012935 ],
[0.00171238],
[0.00159785],
[0.00166382]])
covs=np.array(res[1])
covs
array([[1.38431847e-04, 1.14441282e-04, 1.33778102e-04, 9.26090407e-05,
1.33487719e-04],
[1.14441282e-04, 2.10899253e-04, 1.45080724e-04, 1.08488731e-04,
1.32170134e-04],
[1.33778102e-04, 1.45080724e-04, 1.07565619e-03, 1.18352813e-04,
2.34291648e-04],
[9.26090407e-05, 1.08488731e-04, 1.18352813e-04, 1.53747653e-04,
1.31375380e-04],
[1.33487719e-04, 1.32170134e-04, 2.34291648e-04, 1.31375380e-04,
6.43349060e-04]])
len(means)
5
np.zeros(len(means))
array([0., 0., 0., 0., 0.])
np.append(np.zeros(len(means)),[1,0.75/280],0)
array([0. , 0. , 0. , 0. , 0. ,
1. , 0.00267857])
L1=np.append(np.append((covs.swapaxes(0,1)),[means.flatten()],0),
[np.ones(len(means))],0).swapaxes(0,1)
L1
array([[1.38431847e-04, 1.14441282e-04, 1.33778102e-04, 9.26090407e-05,
1.33487719e-04, 1.45304284e-03, 1.00000000e+00],
[1.14441282e-04, 2.10899253e-04, 1.45080724e-04, 1.08488731e-04,
1.32170134e-04, 1.29350239e-03, 1.00000000e+00],
[1.33778102e-04, 1.45080724e-04, 1.07565619e-03, 1.18352813e-04,
2.34291648e-04, 1.71238140e-03, 1.00000000e+00],
[9.26090407e-05, 1.08488731e-04, 1.18352813e-04, 1.53747653e-04,
1.31375380e-04, 1.59785088e-03, 1.00000000e+00],
[1.33487719e-04, 1.32170134e-04, 2.34291648e-04, 1.31375380e-04,
6.43349060e-04, 1.66382178e-03, 1.00000000e+00]])
L2=list(np.ones(len(means)))
L2.extend([0,0])
#L3=list(means)
L3=means
#L3.extend([0,0])
L3=np.append(L3,0)
L3=np.append(L3,0)
L3
array([0.00145304, 0.0012935 , 0.00171238, 0.00159785, 0.00166382,
0. , 0. ])
L4=np.array([L2,L3])
L=np.append(L1,L4,0)
L3
array([0.00145304, 0.0012935 , 0.00171238, 0.00159785, 0.00166382,
0. , 0. ])
results=linalg.solve(L,np.append(np.zeros(len(means)),[1,0.75/252],0))
results
array([-2.28108358e-01, -4.11299682e+00, 5.06477940e-01, 4.29626690e+00,
5.38360342e-01, -1.99335214e+00, 2.86120684e-03])
帶例子計算結果去啦!
blminVar(res,0.75/252) #年收益率為75%,一年252天是交易日
| p_weight | |
|---|---|
| fjgs | -0.228108 |
| zndl | -4.112997 |
| sykj | 0.506478 |
| hxyh | 4.296267 |
| byjc | 0.538360 |
blminVar(res,0.75/280) #最優資產配置,0.75期望收益,280
| p_weight | |
|---|---|
| fjgs | -0.071785 |
| zndl | -3.272995 |
| sykj | 0.403138 |
| hxyh | 3.516868 |
| byjc | 0.424774 |
blminVar(res,0.15/280)
| p_weight | |
|---|---|
| fjgs | 1.053747 |
| zndl | 2.775015 |
| sykj | -0.340909 |
| hxyh | -2.094806 |
| byjc | -0.393046 |
以上就是各種配比,做完啦!!!!晚安好夢!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/266376.html
標籤:python
