← 返回目录
q1.3动手⏱ 约 9 分钟

数据体检:揪出数据里的病灶

六项检查,把上一节埋的三个真实问题一个个挖出来

🔎 最后验证 2026-07📚 来源:pandas 官方文档(pandas.pydata.org)、中证指数有限公司:沪深300指数于2005-04-08发布、本节代码与全部数字于 2026-07 实测得出🧰 pandas、akshare(数据来自上一节)
为什么学这个

上一节结尾我说:你存下的 csi300.csv 里,天生带着三个数据问题,其中一个多达 721 天。

今天不讲新道理,就干一件事:像医生一样给数据做体检——六项检查逐项过,把这三个「病灶」全部揪出来。它们分别是:一个 17 天的「空洞」、一天 +9.39% 的「异动」、和 721 天诡异的「零」。

体检完你会发现:三个都不是数据错了,而是各有一段真实的历史。但如果你不体检就直接拿去回测——它们每一个都能把你的结论带进沟里。这就是 q0.4 那句「垃圾进,垃圾出」的实战版。

💡 打个比方

拿到数据就直接跑策略,像拿到二手车钥匙就直接上高速

老司机的做法是先绕车一圈:胎压、刹车、机油、里程表有没有被调过——不是怀疑一切,而是知道要看哪几个位置。今天这六项检查,就是数据的「绕车一圈」清单,以后你拿到任何一份行情数据,都先这么绕一遍。

六项体检,逐项跑

接着上一节的 csi300.csv,新建 check_data.py:

import pandas as pd

df = pd.read_csv("csi300.csv", parse_dates=["date"]).set_index("date").sort_index()

# ① 形状:多少行、多少列
print("① 形状:", df.shape)

# ② 缺失值:每列有多少空洞
print("② 缺失值:\n", df.isna().sum())

# ③ 重复:同一天出现两次?
print("③ 重复日期:", df.index.duplicated().sum())

# ④ 日期间隔:相邻两根K线隔了几天
gap = df.index.to_series().diff().dt.days
print("④ 最大间隔:", gap.max(), "天,出现在", gap.idxmax().date())

# ⑤ 极端涨跌:单日涨跌超过6%的日子
ret = df["close"].pct_change()
big = ret[ret.abs() > 0.06]
print("⑤ 单日涨跌>6%:", len(big), "天;最猛一天:",
      big.abs().idxmax().date(), round(big[big.abs().idxmax()] * 100, 2), "%")

# ⑥ 可疑的零:成交量为0的天数
zero = df[df["volume"] == 0]
print("⑥ 零成交量:", len(zero), "天",
      "" if zero.empty else f"({zero.index.min().date()}{zero.index.max().date()})")

我在 2026-07 实测的结果,以及每个数字背后的真相:

检查实测结果真相
① 形状5959 行 × 5 列正常,二十多年的日线
② 缺失值全为 0这份数据没有空值,运气不错
③ 重复日期0干净
④ 最大间隔17 天(2002-02-25 前)🔍 病灶一?——不,是 2002 年春节休市。长假不是数据丢失
⑤ 极端涨跌46 天;最猛 2002-06-24,+9.39%🔍 病灶二?——真实历史:当天宣布停止国有股减持,史称「6·24 行情」。异动≠异常
⑥ 零成交量721 天(2002-01-04 → 2004-12-31)🔍 病灶三:真问题!见下文

721 天的零,是怎么回事

三个「病灶」里,前两个体检完发现是「虚惊」——但第三个是真的:2002 到 2004 年底,整整 721 天成交量全是 0。

真相是:沪深300 指数 2005 年 4 月 8 日才正式发布。你拉到的 2005 年之前的行情,是指数公司事后回溯计算的——价格能回算,但当年并不存在这个指数的「成交量」,所以数据源填了 0。

这意味着什么?如果你的策略用到成交量(比如「放量突破买入」),拿这段数据回测,2002–2004 年的结果全是垃圾——量能永远是 0,策略在那三年里根本不是在交易真实世界。

处理很简单,但必须是你知情后的主动选择:

# 只保留指数正式发布后的数据(2005-04-08 起)
df = df[df.index >= "2005-04-08"]

这就是体检的意义:数据不体检,你连自己在用「回溯编制的历史」都不知道。

⚠️ 避坑⚠️ 坑一:别把「长假」当「数据丢了」,也别把「异动」当「异常值删掉」

两个新手常见的误伤:

  • 看到日期断了 17 天就去「补数据」——那是春节,市场真的没开门。交易日历本来就不连续,周末、节假日都是合法空洞。
  • 看到 +9.39% 就当「异常值」删掉或截断——那是真实发生的行情。你删掉的不是噪声,是历史;而策略在实盘里恰恰要经历这种日子。

体检的产出不是「删掉一切可疑值」,而是给每个可疑值找到解释:能解释的保留,解释不了的(比如那 721 个零)再决定怎么处理。

⚠️ 避坑⚠️ 坑二:连「官方指数」都有回溯数据,别默认任何数据可信

很多人以为「指数是官方编的,数据总靠谱吧」——你今天亲手证明了:连沪深300 都有三年的回溯段,量能字段整段为零。

这不是数据源的错(价格回算是行业惯例),但它提醒你一件事:任何数据,在你验证它之前,都只是「据称如此」。下次有人给你一份「二十年回测」,你可以先问一句:数据的前几年,是真实交易出来的,还是回溯编制的?——这一问,就很内行了。

❓ 测验
你的「放量突破」策略在 2002–2004 年的沪深300 数据上回测,一次都没触发。按这节的体检思路,最该怀疑什么?
✏️ 填空
数据体检的产出,不是把可疑值都删掉,而是给每个可疑值找到 ___ ——能找到的保留,找不到的再决定怎么处理。

📌 免责:本课为技术科普,所有数据与数字均来自公开渠道的实测,仅用于教学;不构成任何投资建议;投资有风险,盈亏自负。

✅ 小结

这一节你完成了第一次真刀真枪的数据体检:六项检查,揪出三个「病灶」,并且给每个都找到了历史真相——17 天是春节,+9.39% 是 6·24 行情,721 个零是指数回溯段。你已经会做「给可疑值找解释」这件最专业的小事了。

数据买回来了、也体检干净了——是时候看看它长什么样了。

下一节,我们把这 5000 多根 K 线画出来:蜡烛图、均线、成交量,一张图看懂二十年。同时我也会提前打好一针疫苗:图是用来理解数据的,不是用来「看图找买点」的——这两者的区别,恰恰是科学和玄学的分界线。

下一节 → 画出你的第一张 K 线图
🔎 来源与核验· 3 条,点开核对
本节每个关键论断都对应一个可追溯的来源 —— 这是本课程"靠谱、不过时"的底线。
「沪深300指数由中证指数有限公司于 2005-04-08 正式发布,此前历史数据为回溯计算;新浪源该指数 2002-01-04 至 2004-12-31 共 721 个交易日成交量为 0」
📚 中证指数公司公开资料 + 本节 2026-07 实测✓ 已核验 2026-07
「2002-06-24 沪深300(回溯)单日 +9.39%,对应停止国有股减持公告(「6·24 行情」)」
📚 本节实测 + 中国证券市场公开历史✓ 已核验 2026-07
「2002 年春节休市造成相邻交易日最大间隔 17 天;交易日历天然不连续」
📚 本节实测 + 交易所休市安排常识✓ 已核验 2026-07
本节所有数字均为 2026-07 对公开数据的实测结果;数据口径以交易所与指数公司官方为准。
智图软件的赞赏码
都看到这了,打个赏呗!
接下来 · q1.4
画出你的第一张 K 线图
继续读下一节 →