「上場廃止した銘柄を外して検証すると、成績が実際より良く出る」——よく聞く話です。日本株で実際に測ったら、逆でした。消えた銘柄は、消える前の半年で平均 +24.5% 上がっていました。
- 1年で 4.1%(182銘柄)、5年で 12.1%(502銘柄)が一覧から消えます
- J-Quants の日足には、消えた182銘柄が全部入っていました(182/182)
- つまりバイアスはデータではなく、自分のコードが入れます
- 消えた銘柄の直前半年:同じ窓の全銘柄の中で上位 17.4%
- 差し引き +23.1%。ただし手続き自体に +7.2% の下駄があり、実質 +16.0%
- ただし直前1か月は何も起きません(上位 44.9%、中央値 ±0.00%)
サバイバーシップバイアスとは
「今ある銘柄」だけで過去を検証すると、途中で消えた銘柄が最初から存在しなかったことになります。
倒産して消えた銘柄が抜け落ちれば、成績は実際より良く出ます。これが通説です。海外株の教科書には必ず載っています。では日本株ではどうなのか。測りました。
まず、どれだけ消えるのか
J-Quants の /equities/master は date を渡すとその時点の銘柄一覧を返します。過去の断面と今を比べれば、消えた銘柄が分かります。
| 時点 | 銘柄数 | 今いなくなった数 | 新しく入った数 |
|---|---|---|---|
| 2021-10-01(5年前) | 4,132 | 502(12.1%) | 811 |
| 2024-10-01(2年前) | 4,393 | 286(6.5%) | 334 |
| 2025-08-01(1年前) | 4,414 | 182(4.1%) | 209 |
| 2026-08-31(今) | 4,441 | — | — |
ここで数えているのは「一覧から消えた」銘柄です。上場廃止だけでなく、持株会社化や合併による銘柄コードの変更も含みます。廃止だけを厳密に取り出すにはもう一段の資料が要りますが、「検証の銘柄リストから抜け落ちる」という意味では同じなので、この記事ではまとめて扱います。
★ データには全部入っていた
ここが一番の収穫でした。bulk で配られる日足に、消えた銘柄が入っているかを確かめました。
| 結果 | |
|---|---|
| 日足データに入っている銘柄 | 4,623 |
| 今の一覧にある銘柄 | 4,441 |
| 日足にあるが今の一覧に無い | 182 |
| 1年で消えた182銘柄のうち、日足にあるもの | 182 / 182(100%) |
J-Quants の日足そのものには、サバイバーシップバイアスがありません。
消えた銘柄の履歴は、消えた後もそのまま残っています。バイアスは、自分が銘柄リストを作る行で入ります。
具体的には、これをやると入ります。
# ★これをやると、その瞬間にバイアスが入る
master = jq.get_all("/equities/master") # 引数なし=「今」の一覧
codes = [r["Code"] for r in master] # 4,450銘柄
# この codes で2年前から検証する
# → 2年前に存在して、その後消えた銘柄が1本も入らない直し方は簡単です。
# 検証の開始時点の一覧を使う
master = jq.get_all("/equities/master", date="2024-10-01")
codes = [r["Code"] for r in master] # 4,393銘柄
# あるいは、日足データに入っている銘柄をそのまま使う
codes = sorted(daily["Code"].unique()) # 4,623銘柄(消えたものも含む)消えた銘柄は、消える前に何をしていたか
「倒産で消えるなら、直前に暴落しているはず」——そう思って測りました。1年ぶんの日足(1,111,120行・4,496銘柄)を使い、株式分割の調整をかけてから、各銘柄の最後の日から遡って何%動いたかを計算しました。
対照の作り方
「上がった/下がった」は、地合いを引かないと意味がありません。指数は作りませんでした。日次リターンを積み上げる指数は、作り方で数字が大きく動くからです(実際に3通り作ったら、同じデータから +2.7% と +27.3% が出ました)。
代わりに、いちばん素直な対照を取りました。その銘柄が消えた日と、その120営業日前。まったく同じ2日を使って、生き残った約4,100銘柄が実際に何%動いたかを全部計算します。
# 対照:同じ日付の窓で、生き残った全銘柄が実際に何%動いたか
# 指数を作らない。積み上げの歪みが入るため
px = daily.pivot_table(index="Date", columns="Code", values="AdjC")
p0, p1 = px.loc[start_date, alive], px.loc[end_date, alive]
ok = p0.notna() & p1.notna() & (p0 > 0)
control = (p1[ok] / p0[ok] - 1.0) * 100 # 約4,100銘柄ぶんの実リターン
rank = 100 - (control < own).mean() * 100 # 対照の中で上から何%か結果
| 遡る長さ | 消えた銘柄 | 同じ窓の全銘柄(中央値) | 差 | 対照の中での順位 |
|---|---|---|---|---|
| 直前 20営業日(約1か月) | −3.24% | −0.22% | −3.02% | 上位 50.4% |
| 直前 60営業日(約3か月) | +3.29% | +0.15% | +3.13% | 上位 48.6% |
| 直前 120営業日(約半年) | +24.46% | +1.33% | +23.13% | 上位 17.4% |
消えた銘柄は、消える半年前から上がっていました。市場全体の中で上位17.4%の位置です。倒産で暴落して消える、という絵ではありません。
理由はおそらくTOB・MBO・親子上場の解消です。買付価格にはプレミアムが乗るので、発表で株価が跳ねます。日本株では、上場廃止の多くがこの形で起きます。
★ ただし、この手続き自体に下駄がありました(追記)
この +23.13% をそのまま信じてよいか確かめるため、同じ手続きのまま「消えた銘柄」を「消えていない銘柄」に差し替えて20回やり直しました(プラセボ)。効果が無いものを入れたのだから、0% 前後になるはずです。
| 差し引き後の平均 | |
|---|---|
| 本物(消えた96銘柄) | +23.13% |
| プラセボ(無作為に選んだ生き残り・20回) | +7.16%(標準偏差 4.19 / 最小 +0.49 / 最大 +17.18) |
0% になりませんでした。+7.16% の下駄が履かされています。
理由は対照に中央値を使って、個別の超過を平均していることです。株のリターンは右に裾が長いので、どの窓でも「中央値を上回る銘柄」のほうが上回り幅が大きくなります。だから無作為に選んでもプラスに出ます。
それでも結論は変わりません。
下駄を引くと実質 +16.0%。プラセボ20回すべてを上回り(0/20)、ばらつきの 3.8倍の位置にあります。
そして「上位17.4%」という順位の数字は、この下駄の影響を受けません。順位は分布の形に左右されないからです。2つの測り方が別々に同じ向きを指しています。
プラセボを回さなければ、+23.13% をそのまま書いていました。効果があるかどうかではなく、手続きが何もないところから何を作り出すかを先に測るべきでした。
分布を見ると、両端が消える
| 差し引き後のリターン(120営業日) | 銘柄数 | 割合 |
|---|---|---|
| +50% 以上 | 19 | 19.8% |
| +20 〜 +50% | 38 | 39.6% |
| 0 〜 +20% | 15 | 15.6% |
| −20 〜 0% | 17 | 17.7% |
| −20% 以下 | 7 | 7.3% |
2割が +50% 以上、7% が −20% 以下。廃止銘柄を外すというのは、この両端をまとめて捨てるということです。平均が動くだけでなく、ばらつきが小さく見えます。
★ 直前1か月は、何も起きない
表をもう一度見てください。直前20営業日の順位は上位50.4%。ぴたりと真ん中です。中央値は ±0.00% でした。
区間を細かく切ると、形がはっきりします。
| いつ | 消えた銘柄 | 同じ窓の全銘柄 | 差 |
|---|---|---|---|
| 半年前 〜 5か月前 | +1.62% | +0.59% | +1.02% |
| 5か月前 〜 4か月前 | +10.57% | +0.53% | +10.04% |
| 4か月前 〜 3か月前 | +8.03% | +0.31% | +7.72% |
| 3か月前 〜 2か月前 | +6.96% | +0.49% | +6.47% |
| 2か月前 〜 1か月前 | −2.20% | −0.10% | −2.10% |
| 直前1か月 | −4.21% | −1.04% | −3.17% |
上がるのは5〜2か月前。直前2か月は止まります。TOBが発表された日に跳ねて、その後は買付価格に張り付くからです。実際、最後の10営業日で終値が1円も動かなかった銘柄が5本ありました。
これは検証の造りに直接効きます。
「消える直前に売れば助かる」わけではありません。値動きが止まっている=手仕舞いの機会そのものが無いのです。廃止銘柄を持ったままの扱いをどうするかは、除外するかどうかとは別に決める必要があります。
数字を鵜呑みにしないための注意
この結果には、はっきり言っておくべき限界があります。
- 1年ぶんしか見ていません。測った期間(2025年8月〜2026年8月)はTOBが活発な局面でした。リーマン後のような局面では倒産型が増え、逆の結果になり得ます
- 120営業日ぶんの日足が残っているのは182本中96本です。期間の前半に消えた銘柄は、遡るぶんのデータが手元にありません
- 対照の作り方で数字が動きます。中央値を基準にすると +23.1%、平均を基準にすると +17.1% でした。指数を積み上げる方式なら +2.7% まで落ちます。だからこの記事では指数を使っていません
- 「一覧から消えた」には銘柄コードの変更も含まれます
それでも、「廃止銘柄を外すと成績が良く出る」という向きの効果は、この期間の日本株では観測できませんでした。効果は逆向きで、しかも小さくありません。
検証を書くときの確認項目
- 銘柄リストをどこから作ったか。
/equities/masterを引数なしで呼んでいたら、その時点でバイアスが入っています - 検証開始時点の一覧を使っているか(
date=を渡す) - 消えた銘柄を、消えた日にどう扱うか決めているか。最終日の終値で手仕舞いか、直前で除外か。結果が変わります
- 値動きが止まる期間を踏まえているか。廃止の直前は、売りたくても値が動きません
- 分割調整をかけてから比べているか
- 地合いを引くとき、指数の作り方を書いているか。同じデータから +2.7% も +27.3% も出ます
まとめ
日本株のサバイバーシップバイアスについて、3つ分かりました。
- J-Quants のデータ自体にはバイアスがありません。消えた182銘柄は全部残っていました。入れるのは自分のコードです
- 通説と逆でした。消えた銘柄は直前半年で上位17.4%、下駄を引いた超過は +16.0%(プラセボ20回すべてを上回る)。外すと成績は良くではなく悪く出ます
- 直前1か月は値が動きません。除外するかどうかより、止まった銘柄をどう手仕舞うかのほうが効きます
通説をそのまま信じて「外しておけば安全側」と判断すると、安全側どころか逆側に倒れます。自分の市場・自分の期間で測ってください。測れるデータは配られています。
この記事の出どころ
- データ:J-Quants API V2 の
/equities/master(date指定で過去の断面)および bulk の日足。Light プラン+分足・ティックアドオン - 期間:日足 2025-08-01 〜 2026-08-31(1,111,120行・4,496銘柄)。銘柄一覧の断面は 2021-10-01 / 2024-10-01 / 2025-08-01 / 2026-08-31
- 対象:2025-08-01 の一覧にあって 2026-08-31 に無い182銘柄。うち期間中に日足が途切れた160本、さらに120営業日ぶん遡れる96本をリターンの集計に使用
- 調整:株式分割・併合は日足の
AdjFactorを後ろから累積して補正 - プラセボ:同じ手続きのまま対象を無作為の生き残り銘柄に差し替えて20回。そこで出た +7.16% が手続きの下駄
- 対照:各銘柄とまったく同じ2日で、今も上場している約4,100銘柄の実リターンを全数計算。指数は作っていない
- 環境:Windows 11 / Python 3.12 / pandas 3.0 / numpy 2.5
- 測定日:2026年9月21日
- 注意:掲載したのは集計結果です。個別銘柄の値動きや取得データそのものは配布していません。特定の銘柄の売買を勧めるものでもありません