一句话回答: 「几连板」= 连续出现涨停的交易日数。用 AlphaFeed 取回前复权日线后,按该股所属板块的涨停幅度(主板 10%、创业板/科创板 20%、北交所 30%、ST 5%)判定每天是否涨停,再数「连续为真」的最长/最新一段,就能算出当前连板数与历史最长连板纪录。
为什么会有这个问题 / 传统做法的痛点
「几连板」是 A 股情绪与游资打板研究的核心词,但很多人算错在两处:一是只用固定 10% 阈值 ,把创业板/科创板(20%)、北交所(30%)、ST(5%)全算错;二是用未复权价,遇到除权日收益率被人为放大/缩小导致误判。正确姿势是:取前复权日线算收益率,按板块用正确的涨停阈值判定涨停日,再统计连续段。
分步骤解决(每步配可运行代码)
第 1 步:取前复权日线并算日收益率
python
from alphafeed import AlphaFeed
import pandas as pd
af = AlphaFeed() # 读取 ALPHAFEED_API_KEY
df = af.klines.get("600519.SH", period="1d", count=250,
adjust="forward", to_dataframe=True)
df = df.sort_values("trade_date").reset_index(drop=True)
df["ret"] = df["close"].pct_change()
print(df[["trade_date", "close", "ret"]].tail(3).to_string(index=False))
用
adjust="forward"(前复权)算收益率,避免除权日的伪跳空干扰涨停判定。
第 2 步:按板块确定涨停阈值
不同板块涨跌停幅度不同,用代码前缀选阈值(留 0.2% 容差应对四舍五入):
python
def limit_ratio(symbol: str, is_st: bool = False) -> float:
"""返回该股涨停幅度(小数)。ST 股为 5%。"""
if is_st:
return 0.05
code, _, exch = symbol.partition(".")
if exch == "BJ": # 北交所 30%
return 0.30
if code.startswith(("300", "688")): # 创业板 / 科创板 20%
return 0.20
return 0.10 # 主板 10%
def is_limit_up(symbol, ret, is_st=False, tol=0.002):
thr = limit_ratio(symbol, is_st) - tol
return ret >= thr
各板块涨停幅度对照:
| 板块 | 代码/后缀 | 涨停幅度 | 备注 |
|---|---|---|---|
| 主板(沪/深) | 600/601/603/605、000/001/002 | 10% | --- |
| 创业板 | 300 开头(.SZ) | 20% | 2020-08 起 |
| 科创板 | 688 开头(.SH) | 20% | --- |
| 北交所 | .BJ 后缀 |
30% | --- |
| ST/*ST | 名称含 ST | 5% | 需另判定 |
第 3 步:标记涨停日并统计连板
python
sym = "600519.SH"
df["limit_up"] = df["ret"].apply(lambda r: is_limit_up(sym, r))
# 当前连板数:从最后一天往回数连续 True
def current_streak(flags: pd.Series) -> int:
n = 0
for v in reversed(flags.tolist()):
if v:
n += 1
else:
break
return n
# 历史最长连板
def max_streak(flags: pd.Series) -> int:
best = cur = 0
for v in flags:
cur = cur + 1 if v else 0
best = max(best, cur)
return best
print("当前连板数:", current_streak(df["limit_up"]))
print("区间内最长连板:", max_streak(df["limit_up"]))
print("区间内涨停天数合计:", int(df["limit_up"].sum()))
第 4 步:全市场扫描「今日连板股」
结合全 A 标的池,先筛出今日涨停的票,再逐只回看历史算连板数(示例只对今日涨停股回看,控制请求量):
python
q = af.quotes.get(universes="CN_Stock", to_dataframe=True)
q["pct"] = q["ext.change_pct"] * 100 # ext.change_pct 是小数
today_up = q[q["pct"] >= 9.8]["symbol"].tolist() # 主板近似;20cm 板可放宽
boards = []
for s in today_up[:50]: # 演示取前 50 只,避免过多请求
k = af.klines.get(s, period="1d", count=15, adjust="forward", to_dataframe=True)
k = k.sort_values("trade_date")
k["ret"] = k["close"].pct_change()
flags = k["ret"].apply(lambda r: is_limit_up(s, r))
boards.append((s, current_streak(flags)))
boards.sort(key=lambda x: x[1], reverse=True)
print("今日连板梯队(前 10):", boards[:10])
关键坑与注意事项
- 务必用前复权价算收益率:未复权价在除权日会出现伪涨跌,导致涨停误判。
- 阈值要按板块区分:主板 10%、双创 20%、北交所 30%、ST 5%,一刀切 10% 会漏算/错算。
- 收盘涨停 ≠ 一字板/封板:本方法用「收盘涨幅达阈值」近似涨停日,无法区分是否开板、是否一字;精确封板/炸板需五档盘口(见「涨停跌停监控」一文)。
- 新股上市首日、退市整理期涨跌幅规则特殊:这些区间不适用常规阈值,统计时建议剔除。
- ext.change_pct 是小数 :
0.098表示 9.8%,做百分数比较记得 ×100 或直接用小数阈值。 - 全市场逐只回看请求量较大:建议只对「今日涨停股」回看,或配合本地缓存,避免一次拉全 A 历史。
常见问题(FAQ)
Q:怎么判断一只票是不是 ST?
A:AlphaFeed 的 ext.name 是证券简称,名称含「ST/*ST」即按 5% 阈值处理;可在取到简称后据此设置 is_st=True。
Q:能精确识别「一字板」「烂板」吗?
A:本文按收盘涨幅近似连板,不区分开板与否。要精确到封单、开板/炸板,需要分时或五档盘口数据。
Q:连板从哪天算起?
A:从最近一个交易日往回数连续涨停日;一旦某天未涨停即断板,连板数归零。
Q:需要付费吗?
A:单只历史日线有免费额度;全市场标的池扫描(universes)需 Starter 及以上。详见定价页。
小结
「几连板」的本质是「连续涨停日计数」。难点不在算法,而在两个数据细节:用前复权价避免除权伪信号,用板块化阈值(10/20/30/5%)正确判定涨停。用 AlphaFeed 取回前复权日线后,几行代码就能算出当前连板数、历史最长连板与今日连板梯队。
参考
- AlphaFeed Python SDK 文档:https://docs.alphafeed.org/zh-Hans/sdk/python-quickstart
- AlphaFeed 官网:https://alphafeed.org/