私は未来を過去へと漏れ込ませた

初期の頃、あまりに出来が良すぎて、本来なら私を喜ばせるはずだったバックテストの結果があった。ところが数分間それを見つめているうちに、それは私を深く不安にさせた。シミュレーション上の利益は大きく、滑らかで、あまりにもクリーンすぎた——現実の、ノイズだらけで敵対的な市場では決して起こらない類のパフォーマンスだった。そして、それが現実の市場では起こらない理由は、私のテストが、ひそかに、私の気づかぬうちに、未来を見ることができたからだ。

意図したわけではない。私は「次に何が起こるかわかっているなら、ズルをしろ」などとは書いていない。未来は、無害そうに見える数十もの小さな継ぎ目を通って過去へと漏れ込んでおり、そのひとつひとつが、実際に金が懸かったときには決して持ち得ない種類の千里眼に対して、私のシステムに報酬を与えていたのだ。

バックテストにおける最も魅惑的なバグ

これの一般的な呼び名は、先読みバイアス、あるいはリークだ。シミュレーション内の判断が、現実なら判断を下したその瞬間にはまだ存在していなかったはずの情報を使うことを許されたとき、いつでもこれは起こる。

これはよく腰を据えて考えてみる価値がある。なぜなら、聞こえる以上に微妙だからだ。バックテストとは、歴史の忠実な再現であるべきものだ。各瞬間において、システムはその瞬間に実際に知り得たことだけを知ってよく、そしてそれだけを使って行動しなければならない。リークとは、その壁にできたあらゆる亀裂のことだ——明日の情報のひとかけらが今日の判断へと滑り込む、あらゆる場所のことだ。そしてそれが起きた瞬間、あなたのバックテストは「これはどうなっていただろうか」を測るのをやめ、「もし覗き見ができたなら、これはどうなるだろうか」を測りはじめる。

未来はどうやって忍び込むか

ここで自分自身のシステムの詳細を語らないよう注意したいので、これらのリークが取る一般的な形のレベルにとどめておこう。なぜなら、それらは驚くほどありふれているからだ。

典型的な形のひとつ。あなたが判断を下しているふりをしているその瞬間よりになって初めて実際に確定した値を、判断に使ってしまうこと。もうひとつ。データをスケーリングしたり正規化したりして準備する際に、履歴全体——シミュレーション上のその瞬間にはまだ起きていなかった部分を含む——にわたって計算された統計量(平均、レンジ、典型的な大きさなど)を使ってしまうこと。さらにもうひとつ。後知恵の恩恵を受けてデータをフィルタリングしたりラベル付けしたりして、結果がどうなったかをすでに知っていなければできないようなやり方で、ひそかにケースを除外してしまうこと。

これらのそれぞれは、もっともらしく見えるたった一行のコードだ。書いているときには、どれもズルをしているようには感じられない。そしてそのひとつひとつが、あなたのシステムに、未来からの小さく安定した情報の流れを手渡しているのだ。

なぜそれを捕まえるのがこれほど難しいのか

リークの最も残酷な点は、それがバグのようには見えないことだ。コードはエラーなしで走る。何もクラッシュしない。そしてそれが生み出す結果は、警告サインではなく——素晴らしい数字なのだ。素晴らしい数字は、たいていの人にとって疑念を呼び起こさない。それらは祝福を、スクリーンショットを、何かを掴んだかもしれないという静かな感覚を呼び起こす。

それこそが、この種のバグをこれほど危険にしているものだ。それは成功のように見える結果の中に隠れている。それはバグが隠れるには最悪の場所だ。なぜなら、成功とは、あなたが最も問いただす気になれない唯一の結末だからだ。クラッシュは修正されることを要求する。美しいエクイティカーブは、見るのをやめるようあなたを誘う。

兆候: 出来が良すぎる結果

長いあいだ、私が持っていた唯一の信頼できる警報は、私自身の信じがたさだった。バックテストが、合理的に期待し得るどんなものよりも劇的に良い結果——市場が許すはずのないほど滑らかで、収益性が高く、一貫している結果——を返してきたとき、最初に立てるべき正しい仮説は「私は何か素晴らしいものを見つけた」ではない。「どこかで情報が漏れている、そしてそれを見つける必要がある」だ。

これは本当に役立つ事前確率であり、私は今ではこれを強く抱いている。バックテストにおいて、卓越さとは、エッジの証拠であるよりも、はるかに頻繁にバグの症状なのだ。市場は難しい。それが簡単だと示唆する結果は、たいてい市場についてではなく、あなたのコードについて何かを語っている。

リークを見つける

リークを狩る実際の作業は退屈で、まったく華やかさのないものであり、それに代わる気の利いた近道を私は見つけていない。その規律はこうだ。判断に流れ込むひとつひとつの値を取り上げ、それが現実においていつ知られることになったであろうか、その正確な瞬間まで遡ってたどる。それから、率直にこう問う。「私が行動しているふりをしているまさにその瞬間に、私は本当にこの数字をまだ持ち得ただろうか?」

たいていのリークは、ついに追い詰めてみると、タイムスタンプひとつ分のズルだったと判明する——本当に存在するようになる一瞬前に使われた値、許されているよりも一歩先までデータに手を伸ばした計算。小さな継ぎ目だ。しかし、小さな継ぎ目も、何千もの判断にわたって繰り返されれば、丸ごと想像上の財産を作り出すには十分なのだ。

より深い原則: 時間の矢を尊重せよ

このすべての根底にあるのは、私が今では神聖に近いものとして扱っている、ただひとつの原則だ。時間の矢を尊重せよ。バックテストとは、本質的にひとつの約束だ——あなたは現在において行動するために過去だけを使い、決して未来を使わなかった、という約束。あらゆるリークは小さな破られた約束であり、あなたのコードがひそかに時間を先へと手を伸ばして、自分を有利にした場所なのだ。

だから、信頼できるシミュレーションを構築することは、結局のところ、巧妙なモデリングについてではなく、ある境界を守ることについてのものだと判明した。ある瞬間において知られていたものと、後になってただ知り得たにすぎないものとの間の境界線だ。エンジニアリングの労力の大部分——誰も賞賛のスレッドを書かない部分——は、ただその境界を、覗き見しようとするあなた自身のコードの絶え間ない無造作な傾向から守ることなのだ。

なぜ私は今、自分の最良の結果を信用しないのか

このすべてから生じた持続的な変化は、良い知らせに対する私の関係が逆転したことだった。残念なバックテストは、ただ残念なだけだ。私はそれを見て、肩をすくめ、先へ進む。素晴らしいバックテストは、今では私を喜ばせる前に不安にさせる。結果が良ければ良いほど、私はそれを生み出したリークをいっそう必死に探しにいく。

それは味気なく聞こえるし、実際そうであることもある。だがそれは、このゲームが自己欺瞞をどのように罰するかについての、苦労して得た敬意から来ている。システムがあなたに告げる最も危険な嘘は、醜い失敗ではない。それは華麗な成功だ——あなたが見つけたいと願っていたものとまさにそっくりに見え、そのために、あなたが疑おうと思う最後のものとなるような成功だ。

— シグナルなし、リターンなし、投資助言ではありません。