生存者バイアスとは?バックテストが嘘をつく最大の理由【Python検証】


バックテストの結果が「思ったより良い」とき、戦略が優秀なのではなく、検証に使ったデータが最初から勝者だけを集めていた——ということがよくあります。これが 生存者バイアス(survivorship bias) です。

過剰最適化やコスト計上漏れと違って、生存者バイアスはコードをどれだけ丁寧に書いても防げません。データの入手方法そのものに原因があるからです。この記事では、その仕組みと影響の大きさをPythonで実際に測ってみます。

⚠️ 本記事は教育目的の情報共有です。投資は自己責任で行ってください。

目次

  1. 生存者バイアスとは
  2. なぜバックテストで必ず起きるのか
  3. Pythonで影響の大きさを測る
  4. 身近な生存者バイアス(ファンドランキング・成功談)
  5. 対策:完全には消せない、それでもできること
  6. まとめ

1. 生存者バイアスとは

生存者バイアスとは、「最後まで残ったものだけを見て、全体を判断してしまう」という誤りです。

有名な例が第二次大戦中の爆撃機の話です。帰還した機体の被弾箇所を集計して「よく撃たれる場所を補強しよう」と考えた——しかしこれは逆でした。帰還できた機体は、そこを撃たれても飛べたのです。本当に補強すべきは、帰還機に一つも被弾跡がない場所、つまりそこを撃たれた機体が落ちてしまった場所でした。

株式のバックテストでもまったく同じことが起きます。私たちが手にできるデータは、たいてい帰還した機体のデータだけなのです。

2. なぜバックテストで必ず起きるのか

たとえば「S&P500構成銘柄で20年前からモメンタム戦略を検証する」としましょう。多くの人はこうします。

# 今のS&P500構成銘柄リストを取得して…
tickers = get_sp500_tickers()      # 2026年時点の500銘柄
data = yf.download(tickers, start="2006-01-01")

一見まっとうですが、この時点で検証は壊れています。理由は単純で、get_sp500_tickers() が返すのは 2026年の今、S&P500に入っている銘柄 だからです。

つまりこのリストには、

  • 20年の間に倒産した企業
  • 業績悪化で指数から外された企業
  • 買収されて消えた企業

が一社も入っていません。過去20年を勝ち抜いた企業だけを選んで、過去20年を検証していることになります。「20年後に生き残る銘柄をあらかじめ知っていた」状態で運用しているのと同じで、これは典型的な先読み(look-ahead)です。

似た問題は個別銘柄のデータ取得でも起きます。上場廃止された銘柄は、多くの無料データソースからティッカーごと消えるため、そもそも取得できません。「データが取れた銘柄だけで検証する」という自然な流れが、そのまま生存者バイアスになります。

3. Pythonで影響の大きさを測る

「理屈はわかったが、どれくらい効くのか」が肝心です。実データで正しく測るには上場廃止銘柄を含むデータベースが要るので、ここではシミュレーションで大きさを体感します。

500銘柄・20年、毎年2%の銘柄が消える(破綻・買収・指数除外)という設定で、次の2つを比べます。

  • (A) 正しい検証:その年に実在した銘柄すべてを等ウェイトで持つ
  • (B) 生存者バイアスあり:20年後まで生き残った銘柄だけで、最初から検証する
import numpy as np

rng = np.random.default_rng(42)

N, YEARS = 500, 20      # 銘柄数・年数
MU, SIGMA = 0.08, 0.30  # 年率リターンの平均・標準偏差
FAIL = 0.02             # 毎年2%の銘柄が上場廃止

ret = rng.normal(MU, SIGMA, (N, YEARS))          # 各銘柄・各年のリターン
alive = np.ones((N, YEARS + 1), dtype=bool)      # 生存フラグ

for t in range(YEARS):
    # 消える銘柄はその年 -60% で終わる(破綻・整理は無傷では終わらない)
    dying = alive[:, t] & (rng.random(N) < FAIL)
    ret[dying, t] = -0.60
    alive[:, t + 1] = alive[:, t] & ~dying

survivor = alive[:, -1]   # 20年後まで生き残った銘柄

# (A) 正しい検証: その年に実在した銘柄すべてを等ウェイトで持つ
correct = np.array([ret[alive[:, t], t].mean() for t in range(YEARS)])

# (B) 生存者バイアスあり: 「今のリスト」で最初から検証
biased = ret[survivor].mean(axis=0)

cagr = lambda r: ((1 + r).prod() ** (1 / YEARS) - 1) * 100

print(f"生き残った銘柄     : {survivor.sum()} / {N}")
print(f"(A) 全銘柄で検証   : CAGR {cagr(correct):5.2f}%")
print(f"(B) 現存銘柄で検証 : CAGR {cagr(biased):5.2f}%")

実行結果はこうなります。

生き残った銘柄     : 328 / 500
(A) 全銘柄で検証   : CAGR  6.35%
(B) 現存銘柄で検証 : CAGR  7.74%

年率で約1.4ポイントの水増しです。1.4%と聞くと小さく感じますが、20年複利では最終資産に1.3倍の差がつきます。

ここで重要なのは、この差は戦略の良し悪しとまったく無関係だということ。銘柄選択もタイミングも何もしていない、ただの等ウェイト保有ですらこれだけズレます。実際の投資信託を対象にした研究でも、生存者バイアスによる押し上げは年率1%前後と報告されることが多く、シミュレーションの数字はおおむね現実的な水準です。

なお、消滅率(FAIL)を上げるほど差は広がります。小型株・新興市場・仮想通貨のように退場率が高い市場ほど、生存者バイアスは深刻になります。

4. 身近な生存者バイアス(ファンドランキング・成功談)

このバイアスはバックテストの外にも溢れています。

投資信託の「過去10年リターンランキング」 成績が悪いファンドは繰上償還されて一覧から消えます。残ったファンドだけを平均すれば、当然カテゴリ全体の実力より良く見えます。

「この手法で1億円」という体験談 同じ手法で退場した人はSNSで発信しません。見えているのは常に帰還した機体だけです。手法の勝率を語るには、失敗した人の数が要ります。

個別株の長期チャート 「20年持っていればこうなった」という銘柄は、20年後まで存在したから今チャートを見られるわけです。当時それを選べたかは、まったく別の問題です。

5. 対策:完全には消せない、それでもできること

正直に言うと、無料データだけで生存者バイアスを完全に消すのは困難です。上場廃止銘柄を含む履歴データ(CRSP、Norgate、Sharadarなど)は基本的に有料だからです。それでも、できることはあります。

① 「今のリスト」で過去を検証しない これが最大の一手です。特定時点の構成銘柄リストを使うなら、その時点で実在したリストを用意する。用意できないなら、その検証結果は「上振れしている」と断ってから読む。

② 指数ETF(SPY・VTIなど)を検証対象にする ETFの価格そのものには、構成銘柄の入れ替えや倒産の影響が既に織り込まれています。個別銘柄群ではなく指数を対象にする戦略なら、生存者バイアスはほぼ回避できます。レジームフィルタのような指数ベースの手法が扱いやすいのはこのためです。

③ バイアスの分だけ結果を割り引く 消せないなら、見積もって差し引く。「大型株中心なら年1%前後、小型株なら数%」を成績から引いて、それでも成立するかを確認します。私は他のバイアスと合わせて、バックテストのCAGRを一律で3〜4割ほど割り引いて判断しています。

④ 「良すぎる結果」を疑う癖をつける CAGR 50%のような数字が出たら、戦略の発見ではなくデータか手続きのバグを疑う。生存者バイアス・過剰最適化・コスト計上漏れの3つが、good-to-be-trueの主犯です。

6. まとめ

  • 生存者バイアス=最後まで残ったものだけを見て全体を判断する誤り
  • 「今の銘柄リストで過去を検証する」だけで発生し、コードでは防げない
  • シミュレーションでは年率約1.4ポイント、20年で最終資産1.3倍の水増し
  • 退場率の高い市場(小型株・新興市場)ほど深刻
  • 対策は①当時のリストを使う ②指数ETFを対象にする ③割り引いて読む ④良すぎる結果を疑う

バックテストで戦う相手は市場ではなく、自分を騙しにくるデータです。生存者バイアスはその中でも最も静かで、最も気づきにくい相手だと思っています。

過剰最適化への対策はこちら → ウォークフォワード検証とは? 実運用前の最終確認はこちら → ペーパートレード(仮想売買)とは?


質問や感想は X (@QuantNobu) までどうぞ。

⚠️ 免責:本記事は教育目的の情報共有であり、投資助言ではありません。実際の投資判断はご自身の責任で行ってください。