停牌日的K线去哪了?回测缺失值为什么让策略"避开"所有暴跌

迪雅数据 · A股数据口径系列 · 2026-10-13

先给结论:停牌日没有成交,交易所不生成K线,这是市场机制的真实表现。回测里真正的危险不是"数据少了几行",而是你用什么假设去填那个洞——填零、填充、还是留空,三种选择对应三条完全不同的回测命运。让策略在历史里"完美避开"所有暴跌日的,往往正是这个洞。

一、停牌日为什么没有K线

个股因重大事项停牌时,交易所停止该标的的竞价撮合。当天没有任何成交,就不会产生开盘价、收盘价,也就没有K线可言。行情软件上表现为K线直接断开、中间空白——这不是数据丢了,是那几天市场根本没有价格。

常见的停牌场景:

停牌类型典型时长触发原因
重大资产重组数周至数月并购、定增、换股吸收合并
异常波动核查1-5 个交易日股价异动监管核查
重要公告披露1 个交易日年报预披露、重大合同
盘中临时停牌10 分钟新股上市初期盘中涨跌幅达 30%/60%

二、数据接口对停牌日的三类返回行为

同一个停牌事件,不同数据源给你的数据长得完全不一样:

类型数据表现对回测的影响
舍弃型 停牌日整行消失,时间索引断裂 逐日遍历会把"复牌跳变"当成相邻两天计算,涨跌幅算出天量数字
空值型 日期存在,价格字段为 NaN,部分源附带停牌标识 指标计算批量产生空值;若下游把 NaN 当 0,直接制造假暴跌
填充型 日期与数值都连续,停牌段沿用前收盘价 序列看起来完美,但策略会"以为"价格没变,错过复牌风控窗口
拿到任何新数据源,先做这件事:拉一段已知有停牌的历史(比如长期停牌重组股),把返回的日期序列与交易日历逐日对比,三行代码判定它属于哪一类。类型没判定就开跑回测,等于带着未爆弹上路。
# 数据源停牌行为检测:对比交易日序列与预期交易日
import pandas as pd

df = pd.DataFrame(api_data)                      # 接口返回的日线
df["date"] = pd.to_datetime(df["date"])
full_days = pd.date_range(df["date"].min(), df["date"].max(), freq="B")  # 粗筛:工作日
missing = set(full_days) - set(df["date"])       # 日期缺口 → 舍弃型
nan_rows = df[df[["open","close","high","low"]].isna().any(axis=1)]      # 空值行 → 空值型
flat = df[df["high"] == df["low"]]               # 全天一字且无量 → 疑似填充型

三、两种处理方案:没有万能解,只有场景解

方案做法适用场景代价
保留缺失,不填充 时间轴保留停牌日,价格留空,指标分段计算 高精度仿真、需要严格区分可交易/不可交易日的合规回测 均线、ATR 等连续指标产生空值,预处理开发量大
前向填充 + 停牌标记 收盘价 ffill 补齐,同时加一列 suspended=True 绝大多数自研回测框架的通用做法 策略在停牌段会误判"价格没变",必须用标记列禁用交易信号

无论选哪种,有一件事绝对不能做:把缺失值当 0 填。价格填 0 等于告诉回测引擎"这天股价归零了"——净值曲线会画出一个不存在的-100%,收益率统计从此全是废纸。量化圈流传多年的"回测夏普 3.2、实盘亏 40%"的故事,根源多半就在这一行代码。

坑:剔除停牌日算均线。20 周期均线在停牌后被算成"20 根有效K线"的均值——这些K线可能横跨 25 个甚至 40 个自然交易日。短线策略的信号会提前或滞后,回测净值失去实盘推演价值。正确做法是时间轴连续、窗口按交易日数,停牌段的价格用方案二填充或方案一分段。
坑:停牌期间允许开平仓信号。停牌日根本挂不进单子。填充型数据上跑出的"停牌期间精准抄底"信号全是幻觉——实盘你连委托都提交不了。用停牌标记列把停牌段的交易信号强制置为不可执行。

四、复牌第一天:整个事件链里最危险的一天

长期停牌复牌首日,往往伴随大幅补跌或补涨(重组失败连续跌停、重组成功连续涨停)。三个口径要点:

五、常见问题

Q1:停牌期间为什么没有K线?

停牌期间没有竞价撮合、没有成交,交易所不生成当日K线,行情软件直接断开。这是市场机制的真实表现,不是数据缺失。

Q2:数据接口对停牌日一般返回什么?

常见三类:整行舍弃(时间索引断裂)、日期在但价格字段为空、用前收盘自动填充。先用本文的断档检测代码判定你的数据源属于哪一类。

Q3:回测该用前向填充还是保留缺失?

短停牌通用做法是前向填充加停牌标记;严格仿真则保留缺失分段计算。共同底线是绝不填零。

Q4:为什么我的均线信号在停牌段会提前或滞后?

剔除停牌日后,"20日均线"实际是20根有效K线的均值,窗口跨越的真实时间更长,信号相对日历日期偏移。

Q5:长期停牌的股票在回测里怎么处理?

视为不可交易标的:持仓冻结、禁止申报,复牌首日按可成交性重新评估,警惕连续跌停下的排队卖出假设。

Q6:复牌第一天的涨跌停价按什么昨收计算?

按停牌前最后一个交易日的真实收盘价(不复权口径)计算,与正常交易日规则一致。详见涨停价计算专篇。

Q7:怎么检测我的数据源在停牌日的返回行为?

拉一段已知有停牌的历史,日期缺口为舍弃型、数值为空为空值型、连续无波动为填充型——本文第二节给出了现成代码。

六、用接口落地:先检测,再选择填充策略

以A股历史交易数据接口为例,标准流程是:拉取目标标的完整日线 → 跑第二节的断档检测 → 按判定结果选择填充方案 → 回测引擎读取停牌标记列。指数停牌场景少见但存在(成分股大面积停牌的极端时期),指数历史行情接口同样适用本流程。

把流程固定进代码
停牌的诚实,在于承认那几天市场根本没有价格——你填进去的每一个数,都是你的假设,不是市场。
相关页面