@Channelchan
2018-09-30T12:13:36.000000Z
字数 5370
阅读 78719
正态分布是最常见的分布形式之一,在开始分析数据时快速判断分布的形式有时能节省很多功夫。
JarqueBera检验可以帮助我迅速判断一个分布是否属于正态分布,JarqueBera检验返回一个P-value,P-Value越小代表越不可能是正态分布。这里我取0.05作为阈值.
假设回报率是满足正态分布,然而当p_value<0.05则拒绝原假设,该股票回报率不为正态分布。
用t检验600036股票收益率均值是否为0,假设平均收益率为0,然而当p_value>0.05则无法拒绝原假设,该股票平均收益率为0。
import tushare as ts
import pandas as pd
from statsmodels.stats.stattools import jarque_bera
from scipy import stats
import numpy as np
import matplotlib.pyplot as plt
data = ts.get_k_data('600036', start='2016-01-01', end='2016-12-31', ktype='D',autype='qfq')
data.index = pd.to_datetime(data['date'],format='%Y-%m-%d')
data['percentage']=data['close'].pct_change()
returns = data['percentage'][1:]
_, pvalue, _, _ = jarque_bera(returns)
if pvalue > 0.05:
print ('判断样本分布服从正态分布')
else:
print ('判断样本分布不服从正态分布')
判断样本分布不服从正态分布
另一个人们关心的属性就是收益率的均值,t_test可以帮助我们快速判断一组数据的均值位置,单样本t_test可以传入2个参数,第一个是待检验的数据,第二个是原假设均值。比如下面我第二个参数传入0,检验的就是样本均值为0的概率。
t_test = stats.ttest_1samp(returns, 0)
if t_test.pvalue > 0.05:
print ('判断样本均值为0')
else:
print ('判断样本均值不为0')
判断样本均值为0
除了人们最关心的均值和方差,这里我再介绍两个统计量,偏度和峰度。
用 表示随机变量X的均值和方差。
偏度用于描述一个分布是否左右对称,一个左右对称的分布偏度(skewness)的值为 0.
正倾斜偏度分布意味 mean > median > mode。
负倾斜偏度分布意味 mean < median < mode。
反过来讲,一个偏度为0的分布就是左右对称的吗?在大多数情况下这是正确的,也是符合直觉的。但如果你是一个喜欢刨根问底的有着浓厚数学基因的人,好吧,确实存在偏度为0但是不左右对称的分布,我们下面简单给出的一个例子,你可以尝试验证一下。
峰度用于衡量分布的尖峰或平扁的程度。
当峰度>3时,可以认为尖峰’很尖了‘。
# 峰态(Kurtosis)
xs = np.linspace(-6,6,300)
normal = stats.norm.pdf(xs)
# Plot some example distributions
fig = plt.figure(figsize=(15, 5))
plt.plot(xs, stats.laplace.pdf(xs), label='Leptokurtic')
print ('Excess kurtosis of leptokurtic distribution:', (stats.laplace.stats(moments='k')))
plt.plot(xs, normal, label='Mesokurtic (normal)')
print ('Excess kurtosis of mesokurtic distribution:', (stats.norm.stats(moments='k')))
plt.plot(xs,stats.cosine.pdf(xs), label='Platykurtic')
print ('Excess kurtosis of platykurtic distribution:', (stats.cosine.stats(moments='k')))
plt.legend()
plt.show()
Excess kurtosis of leptokurtic distribution: 3.0
Excess kurtosis of mesokurtic distribution: 0.0
Excess kurtosis of platykurtic distribution: -0.5937628755982794
#计算600036的偏峰与峰态
import tushare as ts
data = ts.get_k_data('600036', start='2016-01-01', end='2016-12-31', ktype='D',autype='qfq')
data.index = pd.to_datetime(data['date'],format='%Y-%m-%d')
data['returns'] = data['close'].pct_change()[1:]
returns = data['returns'].dropna()
print ('Skew:', stats.skew(returns))
print ('kurtosis:', stats.kurtosis(returns))
fig = plt.figure(figsize=(15, 5))
plt.hist(returns, 30)
plt.show()
Skew: -0.08398804531191496
kurtosis: 2.8607833058726095
Scipy是世界上著名的Python开源科学计算库,建立在Numpy之上。它增加的功能包括数值积分、最优化、统计和一些专用函数。提供很多常用而且强大的功能,方便好用。
import numpy as np
import random
import scipy.stats as stats
random.seed(7)
# 生成符合正态分析的随机数
generated = np.random.normal(loc=0,scale=1,size=1000)
# 可以使用fit()方法对随机取样序列x进行拟合,返回的是与随机取样值最吻合的随机变量的参数
Mean,std = stats.norm.fit(generated)
print('Mean =',Mean,',std =',std)
# 得到数据所在区域中某一百分比处的数值
l = stats.scoreatpercentile(generated,95)
print('95% point: ',l)
# 反过来,得到数值所在的百分比
print(u'%s location:'%l,stats.percentileofscore(generated,l))
Mean = 0.000664258193341 ,std = 1.00992857822
95% point: 1.75098752215
1.75098752215 location: 95.0
sample1 = np.random.normal(loc=0,scale=1,size=1000)
sample2 = np.random.normal(loc=2,scale=2,size=1000)
使用ttest_ind可以检验两组不同的样本是否有相同的均值.返回的p-value表示两组样本均值相同的概率。
a = stats.ttest_ind(sample1,sample2)
print('pValue of Ttest_ind is %s'%a.pvalue)
pValue of Ttest_ind is 1.42142772403e-155
使用Kolmogorov-Smirnov检验判断两组样本是否来自同一个分布,返回的p-value表示两组样本来自同一分布的概率
a = stats.ks_2samp(sample1,sample2)
print('pValue of Kolmogorov-Smirnov Test :%s'%a.pvalue)
pValue of Kolmogorov-Smirnov Test :3.47313005428e-136
使用detrend方法去除趋势。
from scipy import signal
r_add1 = returns+1
cumulative_r = r_add1.cumprod() # 快速获得累积收益
detrend_returns=signal.detrend(cumulative_r)
plt.figure(figsize=(10,8))
plt.subplot(211)
plt.plot(cumulative_r)
plt.subplot(212)
plt.plot(detrend_returns)
plt.show()
probplot可以用来帮助我们确定样本数据的分布特性。
prob-plot和横坐标表示目标分布的分位数,纵坐标表示样本分布对应的分位数。
目标分布以参数的方式传入(dist),默认是norm正态分布。
如果看到一条45度角的直线,则说明样本分布和目标分布一致。
import pylab
stats.probplot(generated, dist="norm",plot=pylab)
pylab.show()
使用probplot可以直观的比较样本分布和正态分布的差异,判断样本分布峰度,偏度等特性。
import matplotlib.pyplot as plt
nsample = 1000
plt.figure(figsize=(10,8))
ax1 = plt.subplot(321)
x1 = stats.t.rvs(5, size=nsample) # 自由度低的t-分布, 厚尾
res = stats.probplot(x1, plot=plt)
ax2 = plt.subplot(322) # 自由度高的t-分布, 和正态分布很相近
x2 = stats.t.rvs(30, size=nsample)
res = stats.probplot(x2, plot=plt)
ax3 = plt.subplot(323)
x3 = stats.norm.rvs(loc=[0,5], scale=[1,1.5],size=(nsample//2,2)).ravel()
# 两个正态分布的混合
res = stats.probplot(x3, plot=plt)
ax4 = plt.subplot(324)
x4 = stats.norm.rvs(loc=0, scale=1, size=nsample) # 标准正态分布
res = stats.probplot(x4, plot=plt)
ax5 = plt.subplot(325)
x5 = stats.f.rvs(4,10,loc=0, scale=1, size=nsample) # skewness < 0
res = stats.probplot(x5, plot=plt)
ax6 = plt.subplot(326)
x6 = -stats.lognorm.rvs(s=0.7, loc=-10, scale=1, size=nsample) # skewness > 0
res = stats.probplot(x6, plot=plt)
同probplot一样,boxplot也可以用来区分样本分布的斜率峰度等属性。
import pandas as pd
boxData = pd.DataFrame({'1_t_5':x1,'2_t_30':x2,'3_mixNorm':x3,
'4_normal':x4,'5_leftS':x5,'6_rightS':x6})
print(boxData.head())
1_t_5 2_t_30 3_mixNorm 4_normal 5_leftS 6_rightS
0 -1.379984 0.525020 1.508090 -2.074363 0.961589 8.629098
1 -2.668370 -0.455317 3.325578 -1.155878 0.765616 7.787245
2 0.905854 2.933671 -1.787563 -0.840319 0.039525 8.456012
3 -1.868835 1.640838 7.686157 -0.557648 0.712965 9.483665
4 0.067156 0.273633 0.233261 0.027595 0.577027 3.814535
boxData.boxplot()
<matplotlib.axes._subplots.AxesSubplot at 0x1b263a6f8d0>