投资理财

幸存者偏差自查清单

逐条核对你的股票池有没有把退市、暂停上市、被并购的样本剔干净,并估算漏掉它们会让历史成绩虚高多少。

  • 免费免注册
  • 结果可分享链接
  • 浏览器本地计算

第一步:逐条核对你的样本池

每条都按「你确实做到了」才勾。拿不准的一律留空——自查清单往乐观里填,等于给自己发了一张假合格证。

样本池怎么定
样本的生老病死怎么记
数据源本身干不干净
样本泄漏风险分级
风险分 100 / 100
0 / 10
已做到
未做到的权重 21 / 21
3
未做到的关键项
关键项各自都足以单独毁掉一份回测
10 条里只做到了 0 条,含 3 条关键项未做到。样本很可能只剩活下来的那批公司,历史成绩会系统性虚高,此时任何参数优化都是在给一份失真的数据调参。

还没做到的 10 条,各自会怎么污染结果

  • 退市的公司仍然留在样本里,退市前那段跌幅也照样计入收益。关键项

    后果:退市股是幸存者偏差最直接的来源。它们通常在退市前经历了漫长而剧烈的下跌,把这批样本抹掉,等于把最差的那部分收益从分子里删掉,整条净值曲线会凭空抬升,而且回撤看起来还更小。

    怎么补:拿一份含已退市证券的全量代码表,逐个核对你的池子里有没有它们;退市整理期的成交价要照实计入,不能用停牌前的价格一直挂到最后。

  • 用到指数成分时,取的是「当时那一天的成分」,不是今天的成分表往回套。关键项

    后果:这是最隐蔽的一类。拿今天的成分股名单回测十年前,等于提前知道了哪些公司熬过了十年还留在指数里——被调出指数的那批公司连同它们被调出前的跌幅一起消失了。表面上你测的是指数策略,实际上测的是「十年后的赢家组合」。

    怎么补:找带生效日期的历史成分与权重表,回测里每个调仓日只允许看到那一天已经公布的成分;做不到就退一步,用可跟踪的指数基金净值代替自己合成的成分组合。

  • 确认过数据源提供的是全历史证券,而不是只有「当前在市」的那一份列表。关键项

    后果:很多免费接口给出的股票列表天然就是「今天还能查到行情的那些」,退市的公司连代码都查不到。你以为自己做了全市场回测,实际上样本从第一行就已经被筛过一遍,而且这个筛选完全不可见。

    怎么补:直接做个反向验证:随便找几只你确知已退市的代码去查,如果一条历史行情都取不到,那这个数据源做长周期回测就是不合格的,换源或者接受结论不可用。

  • 暂停上市与长期停牌期间有明确处理规则,复牌后的补跌照实记入。

    后果:停牌期间价格不动,很多回测直接把停牌日当成「零波动」跳过,复牌当天的跌停缺口就被吞掉了。更糟的处理是停牌即从样本剔除、复牌再加回来,等于系统性地跳过了最难看的那一段。

    怎么补:写清楚三件事:停牌日的净值按什么价格计、停牌期间能不能调仓、复牌首日按什么价成交。三条里任何一条含糊,回测结果都不该拿去比较。

  • 被吸收合并、私有化、换股退出的标的,按当时的对价折算进收益,而不是直接消失。

    后果:并购退出的样本如果只是从池子里消失,那这部分资金在回测里就等于凭空蒸发或凭空归零,两种处理都会让结果失真。方向不一定是虚高,但一定是不可解释的偏差。

    怎么补:把每一次退出都当成一次交易来记:现金对价按到账金额算,换股按换股比例转成新标的继续持有,找不到对价资料的就把这段样本单独标注出来,别混在总收益里。

  • 剔除 ST 类标的时,用的是「当时是否已被标记」,不是今天的名单一次性剔掉。

    后果:拿今天的名单一次性剔除,等于在公司还正常的时候就提前知道了它未来会出问题。这既是幸存者偏差,也是典型的前视偏差:你用未来信息给过去的样本做了筛选。

    怎么补:把标记与撤销标记都当成带日期的事件:在被标记之前照常持有,标记生效日之后再按规则处理,而不是从样本第一天起就当它不存在。

  • 标的退出后的资金去向有明确规则,不会静默地从组合里消失。

    后果:退出资金怎么处理,直接决定组合的分母。默认归入现金、按剩余标的等比再分配、还是维持空仓,三种做法的结果可以差出很多;如果代码里根本没写这条规则,往往就变成了「悄悄按剩余标的重算权重」,等于自动向幸存者集中。

    怎么补:在策略里显式写出清算日、清算价与资金去向,并在净值曲线上标出每一次退出发生的时点,方便事后核对。

  • 样本里如果有基金,已清盘或已转型的那些也留着,不是只统计仍在运作的。

    后果:基金层面的幸存者偏差比股票更严重,因为业绩差的产品会被清盘或转型,从统计口径里彻底退出。只统计现存产品算出来的平均业绩,天然是一份「优等生名单」。

    怎么补:统计区间内成立过的产品全部纳入,清盘的按清盘公告净值截止,转型的按转型日切段,并在结论里注明样本一共包含多少只、其中多少只中途退出。

  • 新股上市之前的那段区间留空,没有用 0 收益或首日价格往前填。

    后果:用 0 填充等于给样本凭空加了一段无风险的横盘,会压低波动率、抬高夏普;用首日价格前推则更糟,相当于把上市首日的定价当成上市前就存在的事实。

    怎么补:上市前的日期一律置为空值,在计算等权或加权组合时按当日实际有效样本数归一化,而不是按固定的池子只数。

  • 用样本只数随时间的变化做过交叉核对,早年的池子确实比今天小。

    后果:这是最省力的一次体检。如果你的池子在样本期第一天就有和今天一样多的股票,那几乎可以断定名单是拿今天的列表往回套的——市场在扩容,早年的可交易证券数量本来就更少。

    怎么补:把每个交易日的有效样本数画成一条曲线,看它是不是随时间自然增长;出现平直的一条横线,说明样本池根本没有按时间重建。

第二步:粗估这些漏掉的样本值多少个百分点

下面四栏都请按你自己样本的实际情况填,页面里的初始值只是为了让公式跑起来的演示假设, 不代表任何市场的实际退出率或跌幅。这一块是量级估算,不是精确修正——它的四条假设写在结果下方。

0.62 个百分点
年化虚高幅度
幸存口径年化 减去 全样本口径年化
11.38%
全样本口径年化
对照:幸存口径 12%
3.11 / 2.94
期末财富倍数(幸存 / 全样本)
期末财富被高估约 1.06 倍
0.62%
折合年均退出率
拿它跟你对市场的直觉比一比,差太远说明比例填错了
在这组假设下,幸存口径的年化比全样本口径高出约 0.62 个百分点。这是量级参考,不是可以直接从你回测结果里减掉的修正值。
幸存口径(只算活下来的)全样本口径(退出的也算)中间那块阴影就是被夸大的部分
1.3×2.5×3.8×0 年5 年10 年

这个估算的四条假设

  • 期初等权买入全部样本,中途不调仓、不再买入新标的。
  • 幸存样本整体按你填的年化匀速增长,不考虑年度间的波动。
  • 退出样本的价值在退出时定格在「期初的一减去平均跌幅」倍,此后不再变化,也不考虑清算残值。
  • 退出在样本期内按恒定的年均退出率均匀发生,不考虑集中退市的年份。

这四条在真实数据里都不严格成立,所以结果只用来判断量级:是零点几个百分点,还是好几个百分点。 它不能当作修正值直接从你的回测年化里减掉。

风险提示

  • 清单只覆盖常见的几类样本泄漏,全部勾上也不等于样本一定干净,更不等于策略有效。
  • 把样本修干净只是让回测这份数据可信一点。回测不等于实盘,实盘还有滑点、成交不了以及临时改规则。
  • 估算部分是简化模型,四条假设与真实市场有距离,结果仅供判断量级。
  • 本工具只做核对与算术,不判断任何标的,不发出买卖信号,也不承诺任何收益。

教育演示:风险分 = 未做到条目的权重和 ÷ 权重总和,关键项另有单独的升级规则。 本工具仅为测算演示,不构成投资建议。

链接带当前参数,发给别人打开就是同一份结果。

怎么用

6 步
  1. 先想清楚样本池是怎么来的:在勾任何一条之前,先把你的股票池是从哪张表、按什么条件筛出来的说清楚。多数幸存者偏差不是算错了,而是在取数那一步就已经发生,后面再怎么调参数都补不回来。
  2. 逐条勾选,拿不准的一律留空:清单分三组:样本池怎么定、样本的生老病死怎么记、数据源本身干不干净。只有你确实做到了才勾,含糊的、想当然的都留空——自查往乐观里填,等于给自己发一张假合格证。
  3. 看风险分级和关键项:分级由未做到条目的权重和决定,同时有一条单独规则:三条关键项里任意一条没做到,等级至少是「中」,两条及以上直接判「高」。因为这三条各自都足以单独让整份回测失去参考价值,平均分再好看也没用。
  4. 照着「还没做到的几条」逐个补:每条没做到的条目下面都写了两件事:它会怎么污染结果、以及具体怎么补。按权重从高到低排,先修最上面那几条,改动最小、收益最大。
  5. 用第二块估个量级:填样本期长度、期间退出样本占比、退出前平均跌幅,以及你自己回测出来的年化,工具会算出全样本口径下的年化,两者之差就是虚高幅度。四栏都按你自己数据的实际情况填,页面初始值只是让公式跑起来的演示假设。
  6. 把假设读完再用这个数:估算基于四条简化假设,写在结果下方。它只回答「量级是零点几个百分点还是好几个百分点」,不能当成修正值直接从你的回测年化里减掉。
深入讲解

一份回测好不好看,先取决于样本里还剩谁

检验一个策略,多数人的第一反应是调参数、换指标、改止损。但在这些之前, 有一个更前置的问题决定了后面所有工作有没有意义:你测的这批样本, 是当年真实存在的那批,还是活到今天的那批?这两者的差别, 比任何参数调整带来的差别都大。

如果你的股票池是「今天还能查到行情的那些公司」,那么退市的、 被吸收合并的、被调出指数的样本已经全部消失了。它们消失的方式很安静: 代码查不到,接口不报错,代码照样跑得通,结果照样输出, 只是数字悄悄变好看了。剩下的全是熬过来的赢家, 于是历史成绩系统性虚高,而且这个虚高不会出现在任何一张回撤图上—— 因为最难看的那部分数据,压根就没进来过。

这就是幸存者偏差。它不是一个统计学名词那么抽象, 它是每一次「从行情接口拉一份股票列表」时都会发生的具体事故。 本页上半部分的清单,逐条列出了这个事故最常见的十个入口; 下半部分的估算,给这件事一个大致的量级感。

样本消失的三条路径

第一条是退市。 这是最直接的一类。公司走完退市流程后从行情列表里消失, 很多数据接口不再提供它的历史行情。而退市从来不是突然发生的, 它前面通常有一段漫长而剧烈的下跌,正是这段最该被计入的收益, 整段从样本里蒸发了。少掉它们,等于把最差的那部分从分子里删掉。

第二条是停牌与暂停上市。 停牌期间价格不动。如果回测把停牌日当成零波动直接跳过, 复牌当天的缺口就被吞掉了;如果处理成「停牌即剔除、复牌再加回」, 那更等于系统性地跳过了最难看的那一段。这条的关键不在于选哪种处理, 而在于必须显式地选一种,并且在结论里说明。

第三条是变身:借壳与重大重组。 代码还在,价格序列也连续,但代码背后已经换了一家公司。 回测看到的是「跌到谷底后强力反弹」,实际上前半段属于原来那家已经不存在的公司, 后半段属于新装进来的资产。把两段接起来当成同一只股票的收益, 在经济意义上是不成立的。这一类最难处理,因为数据完全正常, 只有对照公告才能发现。

最隐蔽的一类:指数成分调整

前面三条至少还留下痕迹——数据查不到、序列有缺口。指数成分调整不留任何痕迹。 你想测一个基于某指数成分股的策略,最自然的做法是拿一份成分名单, 去取这些股票过去若干年的行情。但这份名单是今天的名单, 而指数会定期调整成分:表现变差、市值缩水的公司被调出,新的公司被调进来。

用今天的名单回测多年前,等于你在多年前就提前知道了哪些公司能熬到今天还留在指数里。 被调出的那批公司,连同它们被调出之前那段下跌,一起消失了。 表面上你测的是指数策略,实际测的是「若干年后的赢家组合」: 收益虚高、回撤偏小、风险调整后的指标也跟着偏高,而一切看起来都很正常, 因为被调出的公司今天还在正常交易,数据要多少有多少。

正确的做法是使用带生效日期的历史成分与权重表, 让回测在每个调仓日只看到那一天已经公布的成分。这份数据不便宜也不好找, 拿不到时有个务实的退路:直接用可跟踪的指数基金净值代替自己合成的成分组合。 它粗糙,但它至少不会因为样本泄漏而系统性偏乐观。

虚高幅度大概是个什么量级

页面下半部分给的是一个刻意简化的算法:假设期初等权买入全部样本, 其中一部分在样本期内退出,退出样本的价值定格在「期初的一减去平均跌幅」倍, 剩下的幸存样本按你填的年化匀速增长。两部分按比例加权得到全样本口径的期末财富, 再开样本期长度次方还原成年化,与幸存口径的年化相减,差额就是虚高幅度。 图里两条曲线之间的那块阴影,就是被夸大的部分。

它的四条假设都不严格成立,这一点必须说在前面:退出样本在暴跌之前往往也涨过, 定格在初始值会低估它们的贡献;退市清算有时还有残值; 退出也不是均匀发生的,行情差的年份会集中出现。所以这个数字只用来判断量级: 是零点几个百分点,还是好几个百分点。前者说明样本泄漏对你的结论影响有限, 后者说明这份回测的绝对收益已经不能拿来做任何横向比较。 它不是一个可以直接从回测年化里减掉的修正值。

估算里的四栏输入,请一律按你自己样本的实际情况填。 页面上的初始值只是为了让公式能跑起来的演示假设, 不代表任何市场、任何时间段的实际退出率或跌幅,也不应被当成参考基准引用。

几个常见误用

把自查清单当成合格证。 十条全勾上,只说明这十类常见的口子你都堵上了,不代表样本一定干净, 更不代表策略有效。清单能覆盖的永远是已知的那些错误, 真正麻烦的往往是你数据链路里某个特有的处理方式。

先调参数,再补样本。 顺序反了。在一份泄漏的样本上做参数优化,优化出来的参数是拟合泄漏本身的, 样本补全之后这些参数基本要全部作废。样本这一关必须最先过。

用估算值去「修正」回测结果。 估出来两个百分点,就把回测年化减掉两个百分点当成真实水平, 这是把粗估当精确用。正确的用法是拿它判断「这份回测还值不值得继续讨论」, 而不是给它打个补丁接着用。

只查股票,不查基金与指数。 基金层面的幸存者偏差往往更严重,因为业绩差的产品会被清盘或转型, 从统计口径里彻底退出。只统计现存产品算出来的平均业绩, 天然是一份优等生名单。做同类比较时尤其要注意这一点。

把它和前视偏差混为一谈。 幸存者偏差问的是「样本是怎么来的」,前视偏差问的是「这条信息当时可得吗」。 两者常同时发生、方向一致地让结果偏乐观,但要分开查、分开修。

边界与本工具的假设

清单里的权重是相对的,只用于在同一份清单内部排序与分级, 不代表任何可外推的统计结论,也不对应任何市场的实测数据。 分级规则也是人为设定的:关键项另有单独的升级条款, 因为它们各自都足以单独让一份回测失去参考价值。 估算部分的四条假设与真实市场有距离,结果仅供判断量级。

风险提示:把样本修干净只是让回测这份数据可信一点,回测不等于实盘。 本工具仅为测算演示,不判断任何标的,不发出买卖信号,不构成投资建议,也不承诺任何收益。

常见问题

6 条
幸存者偏差在 A 股具体长什么样?
主要有三种形态,分别对应样本消失的三条路径。第一种是退市:公司走完退市流程后从行情列表里消失,很多数据接口连它的历史行情都不再提供,于是它在退市前那段往往非常剧烈的下跌就整段从你的样本里蒸发了。第二种是暂停上市与长期停牌:停牌期间价格不动,回测如果把这些日子当成零波动跳过,复牌当天的跌停缺口就被吞掉;更糟的处理是停牌即剔除、复牌再加回来,等于系统性地跳过了最难看的那一段。第三种是借壳与重大重组:股票代码还在,价格序列也连续,但代码背后已经换了一家公司。回测看到的是「跌到谷底后强力反弹」,实际上前半段属于原来那家已经不存在的公司,后半段属于装进来的新资产,把两段接在一起当成同一只股票的收益,本身就没有经济意义。三种形态的共同点是:样本消失或变身的过程完全不产生报错,你的代码照样跑得通,结果照样输出,只是数字悄悄变好看了。
为什么免费数据源尤其危险?
因为免费接口通常是围绕「查行情」这个需求设计的,而不是围绕「做历史研究」。查行情只需要今天还能交易的证券,所以它给出的代码列表天然就是当前在市的那一份,已经退市的公司连代码都查不到。你调接口拿到一个几千只股票的列表,以为自己做的是全市场回测,实际上样本从第一行就已经被筛过一遍,而这个筛选完全不可见——没有报错、没有警告、没有缺失值。更隐蔽的是复权价:不同数据源的除权除息处理口径不一样,有的只提供前复权价,而前复权价是以今天为基准往回算的,数据源每次更新,历史数据都会跟着变,这会让你的回测结果不可复现。识别方法很简单,做一次反向验证:随便找几只你确知已经退市的代码去查历史行情,如果一条都取不到,那这个数据源做长周期回测就是不合格的。这不是说免费数据不能用,短周期的、只关心当前标的的用途它完全够用;但凡涉及跨越数年的样本统计,就必须先确认它含不含已退市证券。
指数成分调整为什么是最隐蔽的一类?
因为它连「样本消失」的痕迹都不留。你想测一个基于某指数成分股的策略,最自然的做法是拿一份成分股名单,去取这些股票过去十年的行情。问题在于这份名单是今天的名单,而指数是会定期调整成分的:表现变差、市值缩水、行业地位下滑的公司会被调出,新的公司会被调进来。用今天的名单回测十年前,等于你在十年前就提前知道了哪些公司能熬过十年还留在指数里——被调出的那批公司,连同它们被调出之前那段下跌,一起从样本里消失了。表面上你测的是一个指数策略,实际上测的是「十年后的赢家组合」,收益虚高、回撤偏小、夏普偏高,而且看起来一切正常。它比退市更隐蔽的地方在于:退市股至少还有「查不到数据」这个信号提醒你,成分调整则完全没有信号,被调出的公司今天还在正常交易,数据要多少有多少。正确做法是使用带生效日期的历史成分与权重表,回测中每个调仓日只允许看到那一天已经公布的成分;做不到就退一步,直接用可跟踪的指数基金净值代替自己合成的成分组合,虽然粗糙,但至少不会因为样本泄漏而系统性偏乐观。
第二块的估算是怎么算的,误差有多大?
算法本身很简单:假设期初等权买入全部样本,其中一部分在样本期内退出,退出样本的价值定格在「期初的一减去平均跌幅」倍,剩下的幸存样本按你填的年化匀速增长。把两部分按比例加权得到全样本口径的期末财富,再开样本期长度次方还原成年化,与幸存口径的年化相减,差额就是虚高幅度。四条假设都写在页面结果下方:等权不调仓、幸存样本匀速增长、退出样本定格不变、退出均匀发生。真实数据里这四条都不严格成立。退出样本在暴跌之前往往也跟着涨过一段,所以定格在初始值的做法可能低估它们的贡献;退市清算有时还有残值,这也会让实际结果好于估算;而退出不是均匀发生的,行情差的年份会集中出现,这又会让实际的虚高幅度更大。所以这个数字的正确用法是判断量级:如果算出来是零点几个百分点,说明样本泄漏对你的结论影响有限;如果是好几个百分点,那这份回测的绝对收益基本上不能用来做任何比较。它不是一个可以直接从你回测年化里减掉的修正值,别那么用。
做到什么程度才算样本干净?
一个可操作的判据是:你能说清样本池在每一个交易日分别包含哪些标的,并且这个名单只用到了那一天当时已经公开的信息。这句话拆开有三层要求。第一层是全历史覆盖:数据源必须包含已退市、已摘牌、已被吸收合并的证券,且它们的历史行情完整可取。第二层是逐日重建:样本池不是一份固定名单,而是每个调仓日按当天的规则重新生成一次,新上市的当天才进来,退市的按清算规则退出。第三层是退出规则显式化:清算日、清算价、退出后资金的去向,三件事都要在代码里写出来,而不是靠默认行为。做完这三层之后,还有一个几乎零成本的体检动作:把每个交易日的有效样本数画成一条曲线,看它是不是随时间自然增长。如果这条线从样本期第一天起就是一条与今天等高的水平线,那几乎可以断定名单是拿今天的列表往回套的。最后要说清楚的是,样本干净只意味着这份数据可以拿来讨论,它既不代表策略有效,也不代表回测结论能在实盘复现——回测不等于实盘,中间还隔着滑点、成交不了、以及你自己临时改规则。
幸存者偏差和前视偏差是一回事吗?
不是一回事,但经常同时发生,而且常常由同一个动作引起。幸存者偏差是样本的问题:一部分样本从池子里消失了,你统计的是剩下那批的成绩。前视偏差是时点的问题:你在某个时刻用到了那个时刻还不可能知道的信息,比如用财报正式披露前的数据、用事后修订过的宏观数据、或者用当天收盘价决定当天开盘时的买卖。两者的判断方法也不同:幸存者偏差要问「这个名单是怎么来的、当时的名单和今天一样吗」,前视偏差要问「这条信息在决策的那一刻已经公开了吗」。它们经常纠缠在一起。清单里那条 ST 标记的处理就是典型例子:拿今天的名单一次性把 ST 类标的全部剔除,既剔掉了那些后来出问题的公司,让样本只剩没出事的,这是幸存者偏差;同时又相当于在公司还正常的时候就用未来信息给它贴了标签,这是前视偏差。两种偏差的作用方向一致,都让回测结果偏乐观,所以体检时要分开查、分开修:先把样本补全,再逐条核对每个决策点用到的信息在那一刻是否已经可得。

本工具仅为测算演示,不构成投资建议。计算结果受输入假设影响,实际情况请以官方规定与金融机构公布为准。

回到计算器