看 Python 量化金融投資,摘錄的一些統計函數。爲了以後更好的查找。
import numpy as np
import numpy.linalg as nlg
import scipy.stats as stats
import scipy.optimize as opt
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
plt.rcParams['font.sans-serif'] = ['FangSong'] # 設置中文
plt.rcParams['axes.unicode_minus'] = False # 設置中文負號
plt.style.use('bmh')
統計工具
隨機數
-
生成 n 個隨機數 random variables
rvs
-
連續型的隨機數
rv_continuous.rvs(size=n)
- 均勻分佈
uniform
- 正態分佈
norm
- 分佈
beta
- 等
-
離散型的隨機數
rv.discrete.rvs(size=n)
- 伯努利分佈
bernoulli
- 幾何分佈
geom
- 泊松分佈
poisson
- 等
-
例:
stats.uniform.rvs(size=10)
array([0.90782979, 0.08204289, 0.82901539, 0.19884267, 0.50562515,
0.82687688, 0.1920613 , 0.23374013, 0.45629651, 0.32507933])
np.random.seed(seed=2020)
stats.beta.rvs(size=10,a=4,b=2)
array([0.40765989, 0.81432442, 0.81389925, 0.925416 , 0.77791256,
0.71965217, 0.76665344, 0.80133481, 0.72746346, 0.82444686])
- 也可
np.random.seed(seed=2020)
beta = stats.beta(a=4,b=2)
beta.rvs(size=10)
array([0.40765989, 0.81432442, 0.81389925, 0.925416 , 0.77791256,
0.71965217, 0.76665344, 0.80133481, 0.72746346, 0.82444686])
假設檢驗
K-S 檢驗
- Kolmogorov-Smirnov test
kstest
- 單樣本 K-S 檢驗的原假設是 給定的數據來自和原假設相同的分佈
- 基於累積分佈函數,用以檢驗一個經驗分佈是否符合某種理論分佈或比較兩個經驗分佈是否有顯著性差異。參考來源
# 創建模擬正態分佈數據
data = stats.norm.rvs(size=200,loc=0.5,scale=2)
mu = np.mean(data)
sigma = np.std(data)
print(f'Mean: {mu:.2f}\n\
Median: {np.median(data):.2f}\n\
Standard Deviation: {sigma:.2f}')
plt.figure(figsize=(8,5))
sns.distplot(data)
plt.show()
Mean: 0.39
Median: 0.29
Standard Deviation: 1.99
# 使用 KS-test
stat_val, p_val = stats.kstest(data,'norm',(mu,sigma))
print(f'KS-statistic D = {stat_val:.4f}\n\
p-value = {p_val:.4f}')
KS-statistic D = 0.0502
p-value = 0.7065
- p_value 表示顯著水平(significance level),用於判斷假設是否成立的依據。
- p_value 是服從 區間上的正態分佈隨機變量。
- 在此例中 p_value 很大,因此接受原假設,該數據通過了正態性的檢驗。
T 檢驗
- T-test
- 在正態性的前提下,可進一步檢驗這組數據的均值是不是0.
- 典型的方法爲 T-test
ttest_1samp
單樣本的 t 檢驗函數- 單一樣本的t檢驗,檢驗單一樣本是否與給定的均值popmean差異顯著的函數,第一個參數爲給定的樣本,第二個函數爲給定的均值popmean,可以以列表的形式傳輸多個單一樣本和均值。
stat_val, p_val = stats.ttest_1samp(data, 0)
print(f'1-sample T_test -statistic D = {stat_val:.4f}\n\
p-value = {p_val:.4f}')
1-sample T_test -statistic D = 2.7951
p-value = 0.0057
-
P_value < 0.05
-
在給定顯著性水平 0.05 的前提下,應拒絕原假設:數據的均值爲 0。
-
其他 T test:
ttest_ind
: 獨立樣本的T檢驗,檢驗兩個樣本的均值差異,該檢驗方法假定了樣本的通過了F檢驗,即兩個獨立樣本的方差相同ttest_ind_from_stats
: 檢驗兩個樣本的均值差異(同上),輸出的參數兩個樣本的統計量,包括均值,標準差,和樣本大小ttest_rel
: 配對T檢驗,檢測兩個樣本的均值差異,輸入的參數是樣本的向量
-
再生成一組數據,嘗試一下雙樣本 t 檢驗
data2 = stats.norm.rvs(size=100,loc=-.2,scale=1.2)
plt.figure(figsize=(8,5))
sns.distplot(data2)
plt.show()
stat_val, p_val = stats.ttest_ind(data,data2,equal_var=False)
print(f'2-sample T_test -statistic D = {stat_val:.4f}\n\
p-value = {p_val:.4f}')
2-sample T_test -statistic D = 3.5436
p-value = 0.0005
- 這裏生成的第二組數據樣本大小,方差,和第一組均不等,在運用 t_test 時需要使用 韋爾奇 t_test (Welch’s t_test), 即指定
equal_var = False
。 - 同樣得到較小的 p_value, 在顯著性水平 0.05 前提下,拒絕原假設,即數據均值不等。
其他函數
累計分佈
- Cumulative distribution Function
cdf
- 給定一個分佈,求分位上的數值
g_dist = stats.gamma(a=2)
print('分位數:[2,4,5] ')
g_dist.cdf([2,4,5])
分位數:[2,4,5]
array([0.59399415, 0.90842181, 0.95957232])
概率密度
- Probability density function
pdf
print('概率:[25%,50%,95%] ')
g_dist.cdf([0.25,0.5,0.95])
概率:[25%,50%,95%]
array([0.02649902, 0.09020401, 0.245855 ])
分佈信息
moment
- 給定一個分佈,查看分佈的矩陣信息
- 例查看 N(0,1) 的六階原點矩
stats.norm.moment(6,loc=0,scale=1)
15.000000000895332
統計描述分析
describe
- 對數據集的統計描述分析,(大小,極值,均值,方差,偏度,峯度)
info = stats.describe(data)
print(f'總描述: {info}')
print(f'數據大小: {info[0]}')
print(f'最小值: {info[1][0]:.4f}')
print(f'最大值: {info[1][1]:.4f}')
print(f'平均值: {info[2]:.4f}')
print(f'方差: {info[3]:.4f}')
print(f'偏度: {info[4]:.4f}')
print(f'峯度: {info[5]:.4f}')
總描述: DescribeResult(nobs=200, minmax=(-4.522642873211459, 5.541935059612814), mean=0.3935187131823762, variance=3.964408344885493, skewness=0.1567664342974578, kurtosis=0.2158753158144524)
數據大小: 200
最小值: -4.5226
最大值: 5.5419
平均值: 0.3935
方差: 3.9644
偏度: 0.1568
峯度: 0.2159
極大似然估計
- 極大似然估計 Maximum Likelihood Estimate
fit
可以得到對應分佈參數的極大似然估計。- 例:數據服從正態分佈
norm_dist_data = stats.norm.rvs(size=100,loc=0,scale=1.8)
'均值:{:.4f}, 方差:{:.4f}'.format(*stats.norm.fit(norm_dist_data))
'均值:0.0516, 方差:1.7697'
線性關聯程度
pearsonr
Pearson correlation coefficientspearmanr
Spearman correlation coefficient- 這兩個相關係數 度量了兩組數據的線性關聯程度
exp_dist_data = stats.expon.rvs(size=100)
print('Pearson -相關性:{:.4f}, P-value:{:.4f}'.format(*stats.pearsonr(norm_dist_data,exp_dist_data)))
print('Spearman-相關性:{:.4f}, P-value:{:.4f}'.format(*stats.spearmanr(norm_dist_data,exp_dist_data)))
Pearson -相關性:0.0643, P-value:0.5248
Spearman-相關性:-0.0026, P-value:0.9796
- p_value 表示 原假設(兩組數據不相關)下相關性的顯著性。
線性迴歸
- 例
x = stats.chi2.rvs(3,size=50) # chi-squared
error = stats.norm.rvs(size=50,loc=0,scale=1.5)
y = 2.5 + 1.2*x + error
stats.linregress(x,y)
LinregressResult(slope=1.262568027049048, intercept=2.4399994448207343, rvalue=0.9310325019777308, pvalue=1.1890093549402353e-22, stderr=0.0714309380687254)
plt.figure(figsize=(8,5))
sns.regplot(x,y)
slope_y = x*1.26+2.44
sns.lineplot(x,slope_y)
plt.show()
- 可以看到 很方便得獲得線性迴歸的各個數值。