目的
什么是协方差
协方差(Covariance)
在概率论和统计学中用于衡量两个变量的总体误差。而方差是协方差的一种特殊情况,即当两个变量是相同的情况。 协方差表示的是两个变量的总体的误差,这与只表示一个变量误差的方差不同。 如果两个变量的变化趋势一致,也就是说如果其中一个大于自身的期望值,另外一个也大于自身的期望值,那么两个变量之间的协方差就是正值。 如果两个变量的变化趋势相反,即其中一个大于自身的期望值,另外一个却小于自身的期望值,那么两个变量之间的协方差就是负值。
\(Cov(X,Y) = E[(X-E(X))(Y-E(Y))]\)
协方差的性质
\(Cov(X,Y)=Cov(Y,X)\)
\(Cov(aX,bY)=abCov(X,Y)\) ,(a,b是常数)
\(Cov(X_1+X_2,Y)=Cov(X_1,Y)+Cov(X_2,Y)\)
\(Cov(X+a,Y+b)=Cov(X,Y)\)
协方差的计算
可以使用pandas
,numpy
来计算两个变量的协方差,下面举例分别说明
获取数据
分别取顺丰控股(002352.SZ)
,沪深300指数(000300.SH)
自2018年12月28日至2019年12月31日的数据,这里是为了计算每日涨跌幅,故多取了2018年最后一个交易日的数据
1 2 3 4 5 6 7 8 9 10 import pandas as pdimport numpy as npimport QUANTAXIS as QAfrom IPython.core.interactiveshell import InteractiveShellInteractiveShell.ast_node_interactivity = "all" stock = QA.QA_fetch_stock_day_adv('002352' ,'2018-12-28' ,'2019-12-31' ) index = QA.QA_fetch_index_day_adv('000300' ,'2018-12-28' ,'2019-12-31' ) display(stock.data) display(index.data)
open
high
low
close
volume
amount
date
code
2018-12-28
002352
32.75
33.02
32.50
32.75
55314.0
181019008.0
2019-01-02
002352
32.50
32.71
32.21
32.71
16457.0
53470292.0
2019-01-03
002352
32.63
32.88
32.23
32.73
22575.0
73397384.0
2019-01-04
002352
32.59
32.99
32.11
32.95
36217.0
118465936.0
2019-01-07
002352
32.88
32.91
32.62
32.80
31058.0
101845472.0
...
...
...
...
...
...
...
...
2019-12-25
002352
38.39
38.45
37.73
37.90
70724.0
268576480.0
2019-12-26
002352
38.00
38.38
37.52
37.75
72621.0
274198528.0
2019-12-27
002352
37.75
38.03
37.38
37.51
97280.0
367301696.0
2019-12-30
002352
37.52
37.87
37.00
37.70
106665.0
399623008.0
2019-12-31
002352
37.80
37.85
37.00
37.19
78659.0
292803712.0
245 rows × 6 columns
open
close
high
low
vol
amount
up_count
down_count
date_stamp
volume
date
code
2018-12-28
000300
2994.80
3010.65
3024.35
2984.82
710537.0
7.814531e+10
200
81
1.545926e+09
710537.0
2019-01-02
000300
3017.07
2969.54
3018.78
2958.49
686630.0
7.610557e+10
70
216
1.546358e+09
686630.0
2019-01-03
000300
2963.02
2964.84
3000.44
2953.26
708671.0
7.666480e+10
145
142
1.546445e+09
708671.0
2019-01-04
000300
2940.19
3035.87
3036.81
2935.83
1033189.0
1.071410e+11
286
12
1.546531e+09
1033189.0
2019-01-07
000300
3055.15
3054.30
3061.75
3035.91
1011643.0
1.057039e+11
217
73
1.546790e+09
1011643.0
...
...
...
...
...
...
...
...
...
...
...
...
2019-12-25
000300
3988.66
3990.87
4000.56
3976.36
949388.0
1.318965e+11
117
168
1.577203e+09
949388.0
2019-12-26
000300
3993.67
4025.99
4025.99
3993.54
1088606.0
1.408150e+11
236
53
1.577290e+09
1088606.0
2019-12-27
000300
4029.25
4022.03
4066.80
4019.72
1509264.0
1.950904e+11
116
173
1.577376e+09
1509264.0
2019-12-30
000300
4015.52
4081.63
4083.69
4001.50
1559714.0
2.168147e+11
241
53
1.577635e+09
1559714.0
2019-12-31
000300
4077.75
4096.58
4098.14
4069.01
1232642.0
1.731193e+11
189
95
1.577722e+09
1232642.0
245 rows × 10 columns
每日涨跌幅的计算公式为:\(\frac{当日收盘价-前日收盘价}{前日收盘价}\)
可以有两种方式计算
1 2 3 returns_stock = (stock.data['close' ]-stock.data['close' ].shift(1 ))/stock.data['close' ].shift(1 ) returns_index = (index.data['close' ]-index.data['close' ].shift(1 ))/index.data['close' ].shift(1 ) display(returns_stock,returns_index)
date code
2018-12-28 002352 NaN
2019-01-02 002352 -0.001221
2019-01-03 002352 0.000611
2019-01-04 002352 0.006722
2019-01-07 002352 -0.004552
...
2019-12-25 002352 -0.012764
2019-12-26 002352 -0.003958
2019-12-27 002352 -0.006358
2019-12-30 002352 0.005065
2019-12-31 002352 -0.013528
Name: close, Length: 245, dtype: float64
date code
2018-12-28 000300 NaN
2019-01-02 000300 -0.013655
2019-01-03 000300 -0.001583
2019-01-04 000300 0.023957
2019-01-07 000300 0.006071
...
2019-12-25 000300 -0.000523
2019-12-26 000300 0.008800
2019-12-27 000300 -0.000984
2019-12-30 000300 0.014818
2019-12-31 000300 0.003663
Name: close, Length: 245, dtype: float64
1 2 3 returns_stock = stock.data.close.pct_change() returns_index = index.data.close.pct_change() display(returns_stock,returns_index)
date code
2018-12-28 002352 NaN
2019-01-02 002352 -0.001221
2019-01-03 002352 0.000611
2019-01-04 002352 0.006722
2019-01-07 002352 -0.004552
...
2019-12-25 002352 -0.012764
2019-12-26 002352 -0.003958
2019-12-27 002352 -0.006358
2019-12-30 002352 0.005065
2019-12-31 002352 -0.013528
Name: close, Length: 245, dtype: float64
date code
2018-12-28 000300 NaN
2019-01-02 000300 -0.013655
2019-01-03 000300 -0.001583
2019-01-04 000300 0.023957
2019-01-07 000300 0.006071
...
2019-12-25 000300 -0.000523
2019-12-26 000300 0.008800
2019-12-27 000300 -0.000984
2019-12-30 000300 0.014818
2019-12-31 000300 0.003663
Name: close, Length: 245, dtype: float64
使用numpy
计算协方差
1 2 covr_matrix = np.cov(returns_stock, returns_index) print(covr_matrix)
[[nan nan]
[nan nan]]
使用numpy计算协方差时,不会自动排除NaN
的数据,所以需要手动清洗数据。
1 2 covr_matrix = np.cov(returns_stock[1 :], returns_index[1 :]) print(covr_matrix)
[[3.19837928e-04 9.71284226e-05]
[9.71284226e-05 1.56416934e-04]]
1 2 covr = covr_matrix[0 ][1 ] print(covr)
9.712842264272448e-05
使用pandas
计算协方差
因为取出的数据是多含多重索引的series数据,在使用pandas.series.cov()
进行协方差计算时,如果索引不一致,会出现计算结果为nan
的情况
1 2 covr = returns_stock.cov(returns_index) print(covr)
nan
需要先去除多重索引,办法有多种,如使用droplevel()
,unstack()
等,以下分别举例说明。
1 2 covr = returns_stock.droplevel(1 ).cov(returns_index.droplevel(1 )) print(covr)
9.712842264272448e-05
1 2 3 4 5 df = pd.concat([returns_stock.unstack(), returns_index.unstack()],axis=1 ) display(df) df.cov() covr = df.cov().loc['002352' ,'000300' ] print(covr)
code
002352
000300
date
2018-12-28
NaN
NaN
2019-01-02
-0.001221
-0.013655
2019-01-03
0.000611
-0.001583
2019-01-04
0.006722
0.023957
2019-01-07
-0.004552
0.006071
...
...
...
2019-12-25
-0.012764
-0.000523
2019-12-26
-0.003958
0.008800
2019-12-27
-0.006358
-0.000984
2019-12-30
0.005065
0.014818
2019-12-31
-0.013528
0.003663
245 rows × 2 columns
code
002352
000300
code
002352
0.000320
0.000097
000300
0.000097
0.000156
9.71284226427245e-05
使用pandas.dataframe.cov()
或panadas.series.cov()
时,会自动排除NaN
的数据,这一点与用numpy来计算是有区别的。