跳转至


课程  因子投资  机器学习  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  复权  数据  tushare  akshare  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  因子分析  Alphalens  涨停板  herd-behaviour  momentum  因子评估  review  SMC  聪明钱  trade  history  indicators  zscore  波动率  lightgbm  强化学习  顶背离  另类数据  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  polars  滑动窗口  notebook  sqlite  sqlite-utils  fastlite  UV  Pydantic  Engineering  redis  remote-agent  AI-tools  Moonshot  回测,研报,tushare  dividend 

strategy »

在这一刻抄底,胜率高达95%


在4月8日,我们发表了一篇名为《1赔10,3月27日我抄底了》的文章,基于坚实的统计数据,说明了为什么当天应该抄底。时间过去了半年,中证1000又为我们提供了两个新的例证。这篇文章我们就来回顾一下。

原理和定义

我们先介绍一下原理。你可能观察到,当发生一段连续下跌时,那么下跌的幅度越大,则反弹的力度就越大,并且越可能发生反弹。这就像弹簧一样,或者像是蹦极 -- 在连续下跌到某个点之后,总会往回弹一点。

但我们需要求出连续下跌到什么程度时,反弹的概率会是多大。这样一来,我们的操作才有更有底气和依据。

首先需要定义什么是连续下跌。实际上,我们可以像前文所述,使用每日涨跌。但在这篇文章里,我们想尝试另一种方法,即通过连续阴线区间的跌幅来定义,这样可以过滤一些假信号。

具体的计算方法如下图:

我们先看图中序号1到序号2这一段。这是10月8号到10月11日的走势。10月8日这一天跳空高开,接着一路下跌直到10月11日,8号开盘买入的人,到11日收盘时,亏损达到15.8%。这个损失,就是我们所说的连续阴线区间的跌幅。

我们再看序号3到序号4这一段。这是11月14日到11月18日的情况,14日开盘买入者共亏损7.5%,连续阴线区间的跌幅就是7.5%。

如果我们使用连续下跌(而不是连续阴线的区间跌幅)来计算最大跌幅,将会是从11月12日起开始计算下跌,但提前一天(11月15日)就可能给出抄底信号,这个信号就有点过早。因为在这区间中,出现了一天的假阳线(13日,下跌但收阳线)。这一天筹码发生交换,假设前一日亏损者把筹码全部倒给了新入场者,那么活跃交易者的持仓成本是下降的,他们还能再扛一阵子。

这是我们这次改进中,使用连续阴线的区间跌幅的原因。但实际上两种定义各有优劣,你可以使用机器学习模型来决定何时使用哪一个。

代码实现

既然模型定义清楚,现在我们就开始实现。这段代码需要用到发现连续阴阳线的一个函数,我们把它定义为find_runs:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def find_runs(x):
    """Find runs of consecutive items in an array.
    """

    # ensure array
    x = np.asanyarray(x)
    if x.ndim != 1:
        raise ValueError("only 1D array supported")
    n = x.shape[0]

    # handle empty array
    if n == 0:
        return np.array([]), np.array([]), np.array([])

    else:
        # find run starts
        loc_run_start = np.empty(n, dtype=bool)
        loc_run_start[0] = True
        np.not_equal(x[:-1], x[1:], out=loc_run_start[1:])
        run_starts = np.nonzero(loc_run_start)[0]

        # find run values
        run_values = x[loc_run_start]

        # find run lengths
        run_lengths = np.diff(np.append(run_starts, n))

        return run_values, run_starts, run_lengths

为了让大家都能复现代码,我们使用了akshare来提供数据。这是一个免费、开源的行情数据源。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import akshare as ak
now = datetime.datetime.now().date()
start = now - datetime.timedelta(days=365*4)

start_date = start.strftime("%Y%m%d")
end_date = now.strftime("%Y%m%d")

# 通过akshare获取中证1000日线数据(近1000天)
bars = ak.index_zh_a_hist(symbol="000852", start_date=start_date, end_date=end_date)

bars.rename(columns = {
    "日期": "date",
    "开盘": "open",
    "最高": "high",
    "最低": "low",
    "收盘": "close",
    "成交量":"volume"
}, inplace=True)

bars["date"] = pd.to_datetime(bars["date"])
bars.set_index("date", inplace=True)

bars["flag"] = np.select([bars["close"] > bars["open"], 
                          bars["close"] < bars["open"]], 
                          [1, -1], 
                          0)
v, s, l = find_runs(bars["flag"] == -1)

cum_neg_returns = []
for vi, si, li in zip(v, s, l):
    if vi and li > 1:
        cum_neg_returns.append((bars.index[si], 
                                bars.index[si + li-1], 
                                bars.close[si + li -1 ]/bars.open[si] - 1))

r = pd.DataFrame(cum_neg_returns, columns=["start", "end", "cnr"])
r.cnr.hist()

从生成的直方图来看,连续跌幅达到7.5%以后的次数就很少了,也就是,连续下跌超过7.5%,还能继续下跌是小概率事件。

我们看一下连续下跌最厉害的10次,分别是什么情况:

1
r.nsmallest(10, "cnr").sort_values("end", ascending=False)
start end cnr
107 2024-11-14 2024-11-18 -0.075433
106 2024-10-08 2024-10-11 -0.158511
89 2024-03-21 2024-03-27 -0.071948
88 2024-01-26 2024-02-05 -0.190592
87 2024-01-19 2024-01-22 -0.067846
78 2023-10-16 2023-10-23 -0.074109
45 2022-09-15 2022-09-19 -0.066983
37 2022-04-20 2022-04-26 -0.170335
34 2022-03-14 2022-03-15 -0.066983
33 2022-03-03 2022-03-09 -0.086669

我们看到2024年就发生了5次,分别是1月22日、2月5日、3月27日、10月11日和最近的11月18日。其中2月5日和10月11日这两次下跌幅度很大,后面的反弹也就很大,果然是风浪越大鱼越贵!

1月22日这次能出现在表中非常意外,毕竟这一次只下跌了两天。但是,随后也确实出现了一波持续3天的小反弹,涨幅超过6.1%,还比较可观。

底该怎么抄?

在11月8日收盘时,阴线连续下跌幅度为7.54%,盘中跌幅更大,所以,在盘中就出现了连续跌幅达到7.54%的情况。如果此时你决定抄底,成功的概率有多大?

有一个奇怪的pandas函数可以帮我们计算出来:

1
2
decline_ratio = -0.075433
r.cnr.le(decline_ratio).mean()

它的奇妙之处在于,le用来找出小于等于decline_ratio的数据,把它们标记为true,其它的标记为false,然后mean用在bool变量上,会求出真值的比例,也就是我们要找的概率!

这个概率是4.63%。如果你在此时抄底,那么还有4.63%的概率,你需要忍受继续下跌,这就是发生在10月9日的情况。按照概率的提示,你大概会在10月9日的盘中杀进来,然后要忍受此后两天的继续下跌,这个跌幅跟你之前看到的差不多(也是7.5%左右)。

不过,好消息是,如果你在10月9日杀进来,你有在10月10日选择小幅盈利出局的权利。如果你在这一天选择出局,把筹码倒给了新入场的人,他们还可以再抗7.5%的跌幅!这就是为什么股谚说多头不死,下跌不止。

如果你不会编程,可以通过下面的表格速查抄底成功概率:

1
2
3
4
5
6
data = []
for loss in np.linspace(-0.06, -0.076, 15):
    data.append((loss, 1- r.cnr.le(loss).mean()))

df = pd.DataFrame(data, columns=['最大亏损', '抄底胜率'])
df.style.format("{:.1%}")
  最大亏损 抄底胜率
0 -6.0% 87.0%
1 -6.1% 87.0%
2 -6.2% 87.0%
3 -6.3% 87.0%
4 -6.5% 88.0%
5 -6.6% 89.8%
6 -6.7% 90.7%
7 -6.8% 93.5%
8 -6.9% 93.5%
9 -7.0% 93.5%
10 -7.1% 93.5%
11 -7.3% 94.4%
12 -7.4% 94.4%
13 -7.5% 95.4%
14 -7.6% 96.3%

再往后胜率不变(因为数据量少),所以就没有列出了。在实际操作中,可以从-6%之后开始,使用马丁格尔交易法。

Tip

我在这里没有使用最高价和最低价。这两个价格的稳定性不如收盘价与开盘价(即成交量少)。但你也可以试试。

你还可以计算出抄底之后的可能获利。你可以这样定义:从连续下跌之后出现的连续阳线涨幅,即为抄底之后的盈利。这个计算比较简单,你可以先过滤出连续跌幅大的,再通过循环来计算此后的平均收益。

百闻不如一练。我讨厌读那些看上去很美好,但无法验证的文章。很多时候,读这些文章只是在浪费时间,因为你都不知道哪句是真的,反正都无法验证。

同往常一样,这篇文章同样提供可运行的代码。你只要登录Quantide Research平台,就可以运行本文的代码验证我们作出的结论,然后选择下载本文代码,持续跟踪连续下跌引起的反弹信号。

加入星球,就可以拿到门票。在星球(及Quantide Research平台)里,我们已经发布了可alpha101因子库(可运行)、5个年化超过15%的因子,还有三角形整理检测等代码。未来将继续以更新公众号的频率,持续同步发布笔记相关代码。

如果你不明白这里概率计算的原理,或者想为自己打下坚实的量化基础,可以考虑选修《量化24课》或者《因子分析与机器学习策略》。