4. 连板高度衰减曲线:题材由强转弱的高度阈值判定
把“高度”变成一条可判读的曲线
题材由强转弱,最先松动的往往不是涨停家数,而是连板高度。本节把题材每个交易日的“最高连板数”抽成一条时间序列,用衰减曲线刻画高度回落的速度,再给出一个可回测的阈值规则:当高度从峰值回落到阈值以下并持续确认,判定题材进入弱势阶段。
先明确三个口径,避免后续计算与图形不一致:
- 高度 H(t):第 t 个交易日,题材成分股中收盘仍封住涨停的最大连续涨停天数(首板记为 1,无涨停记为 0)。
- 峰值 Hpeak:观察窗口内 H(t) 的最大值,及其首次出现日 tpeak。
- 衰减率 k:以 tpeak 为起点,对后续交易日拟合指数衰减 H(t) ≈ Hpeak·e−k(t−tpeak),k 越大表示高度塌得越快。
阈值不拍脑袋定,用“峰值比例 + 绝对高度”双条件:H(t) ≤ max(2, ⌈0.5·Hpeak⌉) 视为跌破阈值,且需连续 2 个交易日满足才确认转弱,避免单日炸板造成的假信号。
示例数据与曲线拟合
下面是一段教学示例序列(假设数据,用于演示算法,非真实行情)。某题材 10 个交易日的最高连板高度为:
| t | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|---|---|---|---|---|---|---|---|---|---|---|
| H(t) | 2 | 4 | 6 | 7 | 5 | 4 | 3 | 2 | 2 | 1 |
峰值 Hpeak=7,出现在 tpeak=4。阈值 = max(2, ⌈3.5⌉) = 4。t=6 时 H=4 首次满足 ≤4,t=7 时 H=3 再次满足,连续 2 日确认,t=7 判定转弱。对 t≥4 的数据做对数线性回归 ln H = ln Hpeak − k·(t−tpeak),可得 k≈0.31/日,半衰期约 2.2 个交易日——高度大约每两天掉一半,属于快速衰减型。
阈值回测:触发之后题材怎么走
阈值只有经过回测才有意义。回测要固定三件事:触发定义(连续 2 日 H ≤ 阈值)、观察窗口(触发后 3 个交易日)、结果标签(题材内是否再出现 ≥ 触发日高度的新连板,或题材成交额是否继续萎缩)。下面给出可直接运行的 Python 实现,输入为高度序列,输出峰值、阈值、触发日与回测标签。
import math
def fit_decay(heights, peak_idx):
"""对峰值之后的数据做对数线性回归,返回衰减率 k 与半衰期。"""
xs, ys = [], []
hp = heights[peak_idx]
for i in range(peak_idx, len(heights)):
if heights[i] > 0:
xs.append(i - peak_idx)
ys.append(math.log(heights[i] / hp))
n = len(xs)
if n < 2:
return 0.0, float("inf")
mx = sum(xs) / n
my = sum(ys) / n
num = sum((x - mx) * (y - my) for x, y in zip(xs, ys))
den = sum((x - mx) ** 2 for x in xs)
k = -(num / den) if den else 0.0
half_life = math.log(2) / k if k > 0 else float("inf")
return k, half_life
def detect_weak(heights, confirm_days=2):
hp = max(heights)
peak_idx = heights.index(hp)
threshold = max(2, math.ceil(0.5 * hp))
k, half_life = fit_decay(heights, peak_idx)
trigger = None
streak = 0
for i in range(peak_idx, len(heights)):
if heights[i] <= threshold:
streak += 1
if streak >= confirm_days:
trigger = i
break
else:
streak = 0
return {
"peak": hp, "peak_idx": peak_idx,
"threshold": threshold, "k": round(k, 3),
"half_life": round(half_life, 2),
"trigger_idx": trigger,
}
# 教学示例数据(假设)
heights = [2, 4, 6, 7, 5, 4, 3, 2, 2, 1]
print(detect_weak(heights))
# {'peak': 7, 'peak_idx': 3, 'threshold': 4, 'k': 0.31,
# 'half_life': 2.24, 'trigger_idx': 6}
注意索引从 0 开始,trigger_idx=6 对应第 7 个交易日,与图中 t=7 一致。回测时把同一函数套到历史每个题材样本上,记录触发日之后 3 日的表现:若多数样本在触发后高度不再创新高、成交额占比继续下滑,说明阈值规则有效;若频繁出现触发后立刻反包创新高,则阈值偏松,应把确认天数提高到 3 日或把比例从 0.5 收紧到 0.4。
判读要点
- 看斜率不看单点:k 值大(半衰期短)说明高度塌得快,转弱更可信;k 小但高度长期横在阈值附近,属于钝化,需结合成交额判断。
- 峰值日即分水岭:tpeak 之后每一天都在消耗题材动能,触发日越靠近峰值,转弱信号越强。
- 回测标签要可量化:用“触发后 3 日是否出现 ≥ 触发日高度的新连板”作为主标签,避免用主观感受评价阈值好坏。