跳转至


课程  因子投资  机器学习  Python  Poetry  ppw  tools  programming  Numpy  Pandas  pandas  算法  hdbscan  聚类  选股  Algo  minimum  numpy  algo  FFT  模式识别  配对交易  GBDT  LightGBM  XGBoost  statistics  CDF  KS-Test  monte-carlo  VaR  回测  过拟合  algorithms  machine learning  strategy  python  sklearn  pdf  概率  数学  面试题  量化交易  策略分类  风险管理  Info  interview  career  xgboost  PCA  wavelet  时序事件归因  SHAP  Figures  Behavioral Economics  graduate  arma  garch  人物  职场  Quantopian  figure  Banz  金融行业  买方  卖方  story  量化传奇  rsi  zigzag  穹顶压力  因子  ESG  因子策略  投资  策略  pe  ORB  Xgboost  Alligator  Indicator  factor  alpha101  alpha  技术指标  wave  quant  algorithm  pearson  spearman  tushare  因子分析  Alphalens  涨停板  herd-behaviour  momentum  因子评估  review  SMC  聪明钱  trade  history  indicators  zscore  波动率  强化学习  顶背离  freshman  resources  others  AI  DeepSeek  network  量子计算  金融交易  IBM  weekly  LLT  backtest  backtrader  研报  papers  UBL  quantlib  jupyter-notebook  scikit-learn  pypinyin  qmt  xtquant  blog  static-site  duckdb  工具  colors  free resources  barra  world quant  Alpha  openbb  数据  risk-management  llm  prompt  CANSLIM  Augment  arsenal  copilot  vscode  code  量化数据存储  hdf5  h5py  cursor  augment  trae  Jupyter  jupysql  pyarrow  parquet  数据源  quantstats  实盘  clickhouse  notebook  redis  remote-agent  AI-tools  Moonshot  回测,研报,tushare 

strategy »

KS Test, 广义双曲分布和抄底沪指


Table of Content

R50 上一篇笔记我们抛出一个问题,沪指大跌 4%时,能不能抄底?今天的笔记,我们就通过 KS 检验,找出沪指的概率分布,进而回答这个问题。在后面的笔记中,我们还将换一个方法继续回答这个问题。

K-S 检验

第一个方法,是通过 K-S 检验,来碰碰运气,看看沪指涨跌是否刚好符合某个已知的分布。如果能找到,我们就可以轻松地由其连续密度分布函数 CDF,来计算出继续下跌的概率,即:

\[ P = cdf(-0.04) \]

K-S 是一种非参数检验,是统计检验中的一种。它可以用来检验一组样本是否来自某个概率分布 (one-sample K-S test),或者比较两组样本的分布是否相同 (two-sample K-S test)。K-S 检验是以它的两个提出者,俄国统计学家 (Kolmogorov 和 Smirnov) 的名字来命名的。

我们可以通过 scipy.stats.kstest 来执行 k-S 检验。该方法的签名如下:

1
kstest(rvs, cdf, args=(), N=20, alternative='two-sided', method='auto')

这里 rvs 是随机变量状态,在我们接下来的示例中,我们将传入沪指 1000 个交易日的涨跌幅。在 cdf 参数中,我们传入要测试的随机分布名称。

返回结果为一个 KstestResult 类,它包括 statistic, pvalue 等重要属性。

现在,我们就通过 kstest,对 scipy.stats 中已实现的分布模型,逐一进行 One-Sample test,看看能否有通过检验的:

1
2
3
4
5
pct = close[:-1]/close[1:] - 1
dist_names = ['burr12', 'dgamma', 'dweibull', 'fisk', 'genhyperbolic', 
              'genlogistic', 'gennorm', 'hypsecant', 'johnsonsu', 
              'laplace', 'laplace_asymmetric', 'logistic', 'loglaplace',
              'nct', 'norminvgauss']

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
xmin, xmax = min(pct), max(pct)
dist_pvalue = []

for name in dist_names:
    dist = getattr(scipy.stats, name)
    if getattr(dist, 'fit'):
        params = dist.fit(pct)
        ks = scipy.stats.kstest(pct, name, args=params)
        dist_pvalue.append(round(ks.pvalue, 2))

df = pd.DataFrame({
    "name": dist_names,
    "pvalue": dist_pvalue
})

df.sort_values("pvalue", ascending=False).transpose()

我们将得到以下输出:

图可能有点宽,导致手机上没法看清楚。不过我们只要知道,这里的第一行,genhyperbolic,即广义双曲分布的 pvalue 最高,达到了 0.97。

注意 scipy.stats.kstest 中的 pvalue 可能跟我们在别处理解的 pvalue 不太一样,在它的说明和示例中,p 值大于 0.95,则可以认为在 95%的置信度下,认同原假设:即 rvs 来自于 CDF 所表明的那个分布


因此,上述输出表明,genhyperbolic,即广义双曲分布,是所有假设中,沪指最接近的分布。

我们可以通过绘图来验证一下这个结论是否正确:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from scipy.stats import genhyperbolic

params = genhyperbolic.fit(pct)
rv = genhyperbolic(*params)

fig, ax = plt.subplots(1,1)
x = np.linspace(rv.ppf(0.01), rv.ppf(0.99), 100)
ax.plot(x, rv.pdf(x), label = 'genhyperbolic pdf', color="#EABFC7")

ax2 = ax.twinx()
_ = ax2.hist(pct, bins=50)

75%


不能说十分相似,简直是一模一样。pdf 函数曲线刚好框住了实际分布直方图的外轮廓。

L50

实际上,并非只有沪指符合广义双曲分布。根据 Souto 发表在《金融数学》(2023年2月)杂志上的文章,《Distribution Analysis of S&P 500 Financial Turbulence》, 标普 500 也是最接近这个分布


Warning

Satou 没有使用 scipy.stats 中的 ks-test,而是自己实现了一个。证据之一就是,尽管他得出了标普接近于 GH 分布这一结论,但此时他计算出的 p-value 为零,而不是接近 1。细心的读者应该注意到,我们前面指出过,即 scipy 中的 ks-test 中的 pvalue,与其它地方看到的可能不一致。

类似的不一致还发生在对凸函数的定义上。一部分人(包括我)总是把图形看起来像凸字的函数叫成凸函数,但有些人认为它应该是凹函数,因为它的二阶导是负的。我曾经失去过一位既美丽又聪明的女同事,不知道是否就因为这个分歧。总之,既然你知道了,不妨今后也注意下,不要因小失大。

现在,我们就来求广义双曲分布下,跌幅小于-4%的累积概率,也就是继续下跌的概率:


1
2
3
4
5
from scipy.stats import genhyperbolic

params = genhyperbolic.fit(pct)
rv = genhyperbolic(*params)
print(f"继续下跌的概率为:{rv.cdf(-0.04):.2%}")

结果表明,继续下跌的概率仅为 0.16%。所以,结论是:本答案仅依据历史数据,仅为演示和说明量化算法,不构成任何投资建议!

Tip

看不太懂为什么 cdf(-0.04) 代表继续下跌的概率?我们的课程会从直方图讲起,直到你看懂为止。

Revisit Connor's RSI

如果你对我们的 Connor's RSI 的笔记还有印象,可能还记得,Connor's RSI 的三因子之一,是当天涨跌幅在近 20 天里的排名(prank)。这个排名,实际上就是经验 CDF 函数的一个线性映射。看来,发明一个伟大的指标,其实也只需要掌握简单的统计学原理即可。