我正在研究财务问题,我要实现一个功能,以便在每种股票的信号收益的正态分布之间使用Kolmogorov-Smirnov检验(KS检验)。我将针对每只股票的信号收益按正态分布运行KS测试,对于该测试,我将使用scipy.stats.kstest进行KS测试。
我的功能如下:
def calculate_kstest(long_short_signal_returns):
"""
Calculate the KS-Test against the signal returns with a long or short signal.
Parameters
----------
long_short_signal_returns : DataFrame
The signal returns which have a signal.
This DataFrame contains two columns, "ticker" and "signal_return"
Returns
-------
ks_values : Pandas Series
KS static for all the tickers
p_values : Pandas Series
P value for all the tickers
"""
#TODO: Implement function
ks_v = []
p_v = []
#print(long_short_signal_returns)
column = []
df = long_short_signal_returns.copy()
print(df)
#df['signal_return'] = (df['signal_return'] - df['signal_return'].mean()) / (df['signal_return'].max() - df['signal_return'].min())
for name, group in df.groupby('ticker'):
sub_group = group['signal_return'].values
ks,p = kstest(sub_group,'norm')
ks_v.append(ks)
p_v.append(p)
column.append(name)
ks_values = pd.Series(ks_v,column)
p_values = pd.Series(p_v, column)
return ks_values, p_values
但是,我的答案与预期的输出不匹配。
输入为:
INPUT long_short_signal_returns:
signal_return ticker
0 0.12000000 DNTM
1 -0.83000000 EHX
2 0.37000000 VWER
3 0.83000000 DNTM
4 -0.34000000 EHX
5 0.27000000 VWER
6 -0.68000000 DNTM
7 0.29000000 EHX
8 0.69000000 VWER
9 0.57000000 DNTM
10 0.39000000 EHX
11 0.56000000 VWER
12 -0.97000000 DNTM
13 -0.72000000 EHX
14 0.26000000 VWER
我的输出是:
OUTPUT ks_values:
DNTM 0.20326939
EHX 0.34826827
VWER 0.60256811
dtype: float64
OUTPUT p_values:
DNTM 0.98593727
EHX 0.48009144
VWER 0.02898631
dtype: float64
预期输出为:
EXPECTED OUTPUT FOR ks_values:
DNTM 0.28999582
EHX 0.34484969
VWER 0.63466098
dtype: float64
EXPECTED OUTPUT FOR p_values:
DNTM 0.73186935
EHX 0.49345487
VWER 0.01775987
dtype: float64
有人告诉我必须先使用适当的规范化,然后才能使用正确的p_values和ks_values,但我不理解这种适当的规范化的含义以及如何解决此问题。谁能帮忙?
答案 0 :(得分:1)
不带任何附加参数的KS测试将根据标准正态分布(均值为0和标准偏差为1的正态分布)测试您的数据。如果您的数据正态分布具有不同的均值和标准差,则KS测试会告诉您数据的分布显着不同(您将获得较小的p值)。
您要测试的是分布的“形状”,而不是均值和标准差。两种选择:在将数据放入kstest之前对其进行标准化(减去均值然后除以标准差),或者在调用KS test的调用中添加参数(scipy.stats.kstest(data, 'norm', args=(mean, standard deviation))
答案 1 :(得分:1)
我找到了解决问题的方法。不知何故,我不得不在整个数据集中采用该列的均值和标准差。在这种情况下,我必须要做
k, p = kstest(rvs=subgroup,
cdf='norm',
args=(np.mean(df['signal_return']), np.std(df['signal_return'])))
df = long_short_signal_returns
答案 2 :(得分:1)
我遇到了同样的问题,并尝试将分布标准化为均值= 0和std = 1
但是,测试中的期望值仍然(略)不同。测试中是否有错误,还是您获得了完全相同的值?您是如何通过考试的?
groups = long_short_signal_returns.groupby('ticker')
normal_args = (np.mean(long_short_signal_returns['signal_return']),np.std(long_short_signal_returns['signal_return']))
for name, group in groups:
ks_value, p_value = kstest(group['signal_return'].values, 'norm', normal_args)
测试结果略有偏离(+-0.05):
OUTPUT ks_values:
AVYK 0.63919407
JUWZ 0.29787827
VXIK 0.35221525
dtype: float64
OUTPUT p_values:
AVYK 0.01650327
JUWZ 0.69536353
VXIK 0.46493498
dtype: float64
EXPECTED OUTPUT FOR ks_values:
JUWZ 0.28999582
VXIK 0.34484969
AVYK 0.63466098
dtype: float64
EXPECTED OUTPUT FOR p_values:
JUWZ 0.73186935
VXIK 0.49345487
AVYK 0.01775987
dtype: float64
答案 3 :(得分:1)
normal_args = (np.mean(long_short_signal_returns['signal_return']), np.std(long_short_signal_returns['signal_return'], ddof =1))
尝试添加ddof = 1
。这是一个样本,而不是总体,因此在计算标准差时,需要使用(n-1)而不是'n'。