バックテストが私に嘘をついた夜

ある夜、バックテストは私に、ささやかな初期残高を2,792兆ウォンに変えたと告げた——地球上のほとんどの国の年間生産高を上回る額だ。私はそれをじっと見つめた。数分のあいだ、私の中の静かで強欲な一部が、それが本物かもしれない理由を探しはじめた。

本物ではなかった。バグだった。そしてそのバグは、どんな勝ちパターンの戦略よりも教訓に満ちたものだとわかった。なぜならそれは、バックテストが存在する唯一の目的——現実を尊重すること——についてのバグだったからだ。

私を怖がらせるべきだった数字

私はパラメータ探索を走らせていた——何千もの設定(config)を、それぞれ過去データ上で再生し、最終結果で順位づけする。ほとんどは平凡な結果を返してきた。ひとつだけ、正気でない結果を返してきた。

自分に有利な方向に正気でない、というのは、システムが生み出しうる最も危険な出力だ。なぜなら、それは成功の顔をまとって現れるからだ。負けた実行はデバッグを促す。「うまくいった」実行は祝杯を促す。精査は非対称であり、しかもまさに間違った方向に働く——私たちは気に入らない結果を問い詰め、気に入った結果は素通りさせる。私はもう少しでこれを素通りさせるところだった。

私が——苦い思いをして——学ばねばならなかった本能は、その逆だ。結果が華々しいほど、何かが壊れていることがより確実になる。市場は、初めてシステムを作る者に小国のGDPを手渡したりはしない。あなたのシミュレーションがそうしていると言うなら、シミュレーションが嘘をついているのであり、あなたの唯一の仕事はその嘘の仕組みを突き止めることだ。

過ち その一:毎回、口座の全額を賭ける

最初の欠陥はポジションサイジングにあった。各トレードは事実上口座の全額を賭けるサイズで、利益はそのまま次の賭けへと複利で乗っていった。これをやった瞬間、あなたはトレードをモデル化するのをやめ、幾何級数をモデル化しはじめる。わずかに有利な結果——あるいは、たまたま十分な頻度で都合よく振れる純粋なノイズ——が十分長く続けば、それは成長するのではなく爆発する。数式は現実から逃げ去り、二度と振り返らない。

これが、完全複利のバックテストの魅惑的なところだ:素晴らしい数字を生み出すのに、良い戦略を必要としない。十分な数のトレードと、賭けを乗りつづけさせてくれるほど寛大なシミュレータさえあればいい。複利は、かすかで無意味な統計的な偏りを指数曲線へと変え、何千ものトレードにわたる指数曲線は、運命のように見えて何の意味も持たない数字を生み出す。あの天文学的な残高は、エッジの証拠ではなかった。ランダムネスに対して口座全額のエクスポージャーを適用した結果の証拠だった。

過ち その二:死ねないシミュレータ

二つ目の欠陥のほうが悪質だった。なぜなら、それは哲学的なものだったからだ。私のバックテスターには吸収壁がなかった——口座が単に死ぬという地点が存在しなかった。だから、悪いトレードの連続が残高を99.99%まで押し下げても、シミュレーションは止まらなかった。死体をテーブルに残したまま、それにトレードを続けさせた。そしてそのほぼゼロの残高から、幸運の連続が口座を「蘇生」させ、ばかげた高みへと連れ戻したのだ。

現実の口座では、その回復はあり得ない。ゼロはゼロだ。清算された残高に第二幕はない——あなたはゲームから永久に退場しており、未来のいかなる勝ちの連続も、時を遡ってあなたを救うことはできない。破産した口座にトレードを続けさせることで、私のコードはトレードのすべてにおいて最も重要なルールを密かに削除していた:破滅は最終的なものだ、というルールを。その下流にあるすべて——あの幻想のすべて——は、たった一つの欠けた制約から論理的に導かれていた。シミュレーションは、生き延びた戦略をモデル化していたのではなかった。死ぬことを許され、そして死んだままでいることを禁じられた戦略をモデル化していたのだ。

オプティマイザは私の盲点を狩っていた

ここが、理解するのに一番時間がかかった部分だ:パラメータ探索は、あの不条理な設定に偶然たどり着いたのではなかった。それを探しに行ったのだ。

何千もの設定にわたる探索は、中立な観察者ではない。それは、あなたが渡したどんな指標に対しても最適化する敵対者だ。あなたの指標が「最終残高」で、あなたのシミュレータに弱点——非現実的なことが密かに許される場所——があるなら、探索はその弱点を見つけ出し、全体重をかけてそこに寄りかかる。それは最良の戦略に報酬を与えるのではない。あなたのシミュレーションと現実とのあいだの隙間を最も効率よく突く設定に報酬を与えるのだ。

だから、あの兆ウォンの結果は、ランダムに浮上した不運なバグひとつではなかった。それは、騙されうるシミュレータに強力なオプティマイザを向けたことの予測可能な帰結だった。バックテストに残したあらゆる弱点は、探索のもとで戦略になる。オプティマイザは、あなたが強制し忘れた前提を正確に発見するための機械なのだ。

兆候

これらの過ちを組み合わせると、奇跡を製造する機械ができあがる。それは何にでも生き延びられるので、すべてに生き延びる;それはすべてを賭けるので、生き延びるときには莫大に生き延びる;そして探索が、その両方をできるだけ激しくやるよう密かに調律している。その出力は、戦略のパフォーマンスではない。それは、バグそのものの姿が、とてつもなく大きな数字で描かれたものだ。

これこそ「まず生存」がスローガンではない理由だ。破産できないバックテストは、探索すべき設定が十分にあれば、必ずいつか天才に見えるものを浮上させる——その設定が良いからではなく、探索があなたのシミュレータの盲点を辛抱強く掘り当てているからだ。印象的な数字は症状だ。欠けている破産が病だ。

退屈な修正

修正は華やかさのないものだった。ポジションサイズは口座全額ではなく、口座のわずかな固定割合になった。これで勝ちがナンセンスへと雪だるま式に膨らむことも、負けが一か八かになることもなくなった。シミュレータは本物の破滅条件を得た:最低生存残高を下回ったら実行は終了、死亡と記録、それで終わり。そして最小注文サイズも得た。これで、現実の市場には存在しえないほど小さいトレードが、死にかけの口座を密かに延命させることもなくなった。

これらはどれも気の利いたアイデアではない。そこに洞察はなく、エッジもない。それらは、シミュレーションがついに、現実が決して緩めない制約に従うことを承諾したというだけのことだ——許してくれないコスト、無限ではない流動性、そして戻ってこられないゼロ。誠実なバックテストを作る作業のほとんどは、まさにこれだ:それを賢くすることではなく、それがズルをするのを拒むことだ。誠実なバックテストの第一の責務は、利益を見せることではない。破滅を見せることができる、ということだ。

なぜ私は良い知らせを信じるのをやめたか

ここが居心地の悪い部分だ。バグは簡単だった。難しかったのは、私がもう少しで見ようとしなかったということだ——なぜなら、その数字は私に有利で、私はそれが本当であってほしいと望んでいたからだ。あなたに反する結果は問い詰められる。あなたを甘やかす結果は信じられる。

その非対称性こそ、この仕事における自己欺瞞のほとんどが宿る場所だ。人々が自分のバグを見つけられないのではない;バグが報酬を払いはじめた瞬間に、探すのをやめてしまうのだ。市場はいずれ、あなたが一度も確かめなかった心地よい前提のすべてに、満額の請求をしてくる——だがバックテストは、その前提を何ヶ月も喜んで保持させてくれる。なぜならそれは、構造上、間違っていることが無料である唯一の場所だからだ。

それが実際に変えたもの

だから、偽の兆ウォンから私が保ち続けた規律は、ポジションサイジングとはほとんど関係がない。それは私の信頼の順序を変えた。見栄えの良い結果は、いまや無実が証明されるまで有罪だ:「どうやってこれをやったのか?」と問う前に、私は「ここで何が壊れているのか?」と問う——そして私は意図的に、市場がその機会を得る前に、自分自身でそれを壊そうとする。その敵対的な扱いを生き延びる結果だけが、私が信じることを自分に許す唯一のものであり、それは私が望むよりはるかに少ない。

すべてを失えないバックテスターは、楽観的なのではない。嘘をついているのだ。そしてそれがつける最も危険な嘘は、あなたがすでに聞きたいと願っていた嘘だ。

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