2026年9月26日 · リサーチ

戦略のバックテスト再現に挑戦。数値がずれた原因はここにありました。

戦略のバックテスト再現に挑戦。数値がずれた原因はここにありました。

保存しておいたバックテストを再実行したところ、エクイティカーブが変わっていました。戦略コードも、期間も、銘柄も同じです。それでも最終残高は1.8%ずれ、3件の取引で約定バーが1本分移動していました。

これでは、リサーチ結果を信頼しにくくなります。チームメイトや将来の自分、ペーパートレードのサービスが実行結果を再現できなければ、変更によって戦略が改善したのか、実験条件が変わっただけなのかを判断できません。ずれの原因を探るために、私たちがたどった手順を紹介します。

1日目:「同じ実行」の意味を書き出す

最初の間違いは、戦略ファイルだけを実験の全体だと考えたことでした。実際には、入力データ、エンジンのバージョン、カレンダー、金融商品のメタデータ、執行設定にも結果は左右されます。コードが示すのは、計算の一部分にすぎません。

何も変更する前に、実行マニフェストを作成しました。戦略のコミット、データスナップショットの識別子、期間、取引所、手数料体系、資金調達率のデータソース、約定モデル、ソフトウェアのバージョンを記録しました。さらに、注文と約定の結果も保存しました。エクイティカーブだけでは、2つの実行結果が最初にどこで分岐したのか分からないからです。

成果物記録する内容重要な理由
市場データスナップショットID、スキーマのバージョン、調整内容ベンダーは過去データを修正し、コーポレートアクションを改訂する
執行手数料ティア、資金調達率の時系列、約定と価格インパクトの設定デフォルト設定や口座の前提で結果が変わる
実行環境コードのコミット、エンジンと依存関係のバージョンライブラリによって処理順序、丸め方、インジケーターが変わることがある
出力注文、約定、ポジション、各種指標実行結果が食い違い始めた箇所が分かる

2日目:Sharpeではなく取引を比較する

集計指標に目を奪われていました。2つの実行結果のSharpeはほぼ同じでしたが、約定ログを見ると、最初の不一致は資金調達率の決済時に起きていました。一方は決済タイムスタンプ時点で保有していたポジションに料率を適用し、もう一方はその時刻のリバランス後のポジションを使っていました。

戦略コードは変わっていません。変わったのはエンジンのイベント処理順でした。小さなバージョン更新によって、以前は2つのイベントの並び順に左右されていた処理が明示されていました。

実行条件に処理順を明記しました。決済時点に持ち越されたポジションに資金調達率を適用してから、その時刻の戦略判断を処理します。正確なルールは取引所やエンジンによって異なる場合があります。暗黙のままにしておくことが問題です。

3日目:「同じ」データファイルが別物だった

イベントの処理順を固定すると、残った不一致は一部の株式取引に集中していました。ベンダーが過去の株式分割調整を修正していたのです。ファイル名も行数も以前と同じだったため、変更されていないように見えていました。

今では、不変のデータスナップショットごとにフィンガープリントを取り、調整ポリシーも一緒に保存しています。ハッシュを見ればバイト列が変わったことは分かりますが、その理由までは分かりません。そのため、マニフェストにはデータソース、取得時刻、変換のバージョンも含めています。改訂されるデータでは、こうした情報も結果の一部です。

再現可能なバックテストには、「どの時点の過去データを参照したのか」への答えが必要です。

4日目:見落としていたデフォルト設定を発見

最後に見つかった差は、maker手数料が0に設定されていたことでした。戦略設定でこの項目を省略していたためです。新しいエンジンは口座のデフォルト手数料を適用していました。この1つのデフォルト設定により、境界付近の取引が変わり、最終残高の差の大部分が生じていました。

経済的に重要な設定は明示し、エンジンが解決後の設定を実行記録に出力するようにしました。デフォルト設定は探索中には便利です。時間をまたいで結果を比較するときの根拠としては不十分です。

3見つかったずれの原因
1.8%当初の最終残高の差
0Sharpeが一致するだけの価値

次回は省きたいこと

最初に異なる約定を確認する前に、集計指標の比較に半日を費やしました。そこから始めるべきではありません。2つのイベントログをタイムスタンプ順に並べ、最初の分岐を比較しましょう。その後に起きる違いの多くは、最初の原因から派生しています。

コンテナイメージだけで実行を再現できる、という考えも手放したいところです。ソフトウェア環境の多くは固定できますが、外部データファイルや実行時に取得される手数料体系、ベンダーが改訂した過去データまでは固定できません。

バックテストの結果が変わったら、両方の実行マニフェストとログを保存し、ずれの原因を1つずつ修正してください。再実行できるカーブだけが成果ではありません。どのデータと前提条件から結果が生まれたのか、次回の実行でなぜ違いが生じる可能性があるのかを説明できる記録も、大切な成果です。

再現性バックテストデータエンジニアリングペーパートレード
← 記事一覧