バックテスト(過去データで売買ルールを再現する検証)の結果が再現しないとき、原因は戦略よりも先にデータ側にあることが多いです。結論を先に書くと、「期待される足の並び」を自分で定義してから差分を取る——これだけで、欠けた足・重なった足・時刻のずれの大半は機械的に見つかります。AIは点検コードを書くのは得意ですが、何が正常かを知らないので、放っておくと欠損を黙って埋めて「きれいなデータ」に見せてしまいます。順番は、定義 → 検出 → 判断(埋めない・除外・印を付ける)の三段です。
なぜ検証前のデータ点検が結果を左右する?
ルールの検証は、足が等間隔に並んでいることを暗黙の前提にしています。たとえば「直近20本の高値を抜けたら」という条件は、20本が20本分の時間に対応しているという前提の上に立っています。ここに配信欠落で数本抜けがあると、同じ条件が実質的に違う時間幅を見ていることになります。
やっかいなのは、この種のずれがエラーにならずに数字だけ変える点です。プログラムは落ちず、損益曲線も出る。けれど出てきた優位性が、データの穴に由来するのか相場の性質に由来するのかが分からない。バックテストが崩れるのは「未来が違う」からではないで扱った過剰最適化の切り分けも、入力データが安定していることが前提になります。点検は検証の前工程ではなく、検証の一部だと考えたほうが扱いやすいです。
欠けた足はどう見つける?
手順は二つです。
- 期待グリッドを作る:対象期間と時間足から、本来あるべきタイムスタンプの列を生成します。為替なら週末、株価指数なら取引所の休業日とセッション時間を除外した上で作ります。
- 実データとの差集合を取る:期待グリッドにあって実データに無い時刻を一覧化します。
これに加えて、タイムスタンプの差分(前の足との間隔)の分布を見るのが簡単で効きます。1分足なら差分は60秒が大半で、週末明けに大きな値が一つ出るのが正常形です。60秒の整数倍でない値が混ざっていれば、それは足の生成方法か結合処理のどちらかが壊れている合図です。
見つけた欠損は、原因で分けて扱います。市場が開いていない時間、取引はあったが気配が動かず足が作られなかった時間、配信側の欠落、自分の取得スクリプトの失敗。最後の一つは再取得で直せますが、前の二つは「データが無いこと自体が情報」なので、埋めてはいけません。前の値で埋める処理は、薄い時間帯をあたかも取引可能だったかのように見せ、薄商いの日は値幅でなく執行コストを見るで触れたような執行コストの問題を検証から消してしまいます。
重なった足・重複行の正体は何か
重複にはいくつか種類があり、対処が違います。
| 症状 | 見える形 | 主な原因候補 | 最初に確認すること |
|---|---|---|---|
| 完全重複 | 全列が同一の行が2つ | 取得の再実行、ファイル結合時の重ね貼り | 取得ログの期間が重なっていないか |
| 同時刻・別内容 | 時刻は同じでOHLCが違う | 提供元が異なる、ビッドとアスクの混在、修正後の再配信 | 由来を示す列を残しているか |
| 秋の時刻戻し | 同じ現地時刻が2回現れる | サマータイム終了日の1時間重複 | 時刻が現地時刻のまま保存されていないか |
| 擬似重複 | 秒やミリ秒だけ違う同一足 | 丸め処理の不一致 | 時刻の精度を揃えてから比較したか |
重複を見つけたら、まず削除せず、何件・どの期間に偏っているかを数える。特定の月に集中しているなら結合ミス、毎年同じ時期なら時刻制度、ランダムなら配信側の可能性が高い、という当たりが付きます。
時刻のずれはどう特定する?
時刻の問題は、欠損や重複と違って見た目が正常なので一番見つけにくいところです。確認したい点は三つあります。
- 基準はどこか:UTCか、提供元サーバの現地時刻か。時刻の表記規格としてはISO 8601、タイムゾーンの規則データとしてはIANA Time Zone Database(tz database)が広く使われています。保存はUTCに統一し、表示のときだけ変換するのが扱いやすい形です。
- ラベルは始まりか終わりか:同じ「09:00」の足が、09:00に始まる足なのか、09:00に終わる足なのかで、条件判定が1本分ずれます。提供元をまたいで結合すると、ここが混ざります。
- サマータイムの扱い:欧州と北米では切替日が一致しない期間があるため、サーバ時刻と市場の活動時間帯の関係は年内で何度か変わります。
ずれの検出には、時間帯プロファイルが使えます。1時間ごとに値幅(高値と安値の差)の平均やティック数を集計し、横軸に時刻を取って並べる。活発な時間帯の山が、自分の知っている市場の時間帯から何時間ずれているかで、オフセットが推定できます。年単位で区切って同じ集計をすれば、切替日の前後でプロファイルが動くかどうかも見えます。この集計手順は、セッション別の「性格差」は信じる前に自分のデータで測り直すで扱った時間帯分析とそのまま共通です。
AIに任せてよい部分と、任せると壊れる部分
任せやすいのは、定型の点検コードの生成と出力の読み解きです。「期待グリッドとの差分を出す」「差分の分布を集計する」「OHLCの整合(高値が始値・終値・安値のいずれをも下回らないか、安値がそれらを上回らないか)を検査する」といった処理は、仕様を文章で渡せば十分に書けます。異常行の一覧を貼って「分類の候補を挙げて」と頼む使い方も有効です。
壊れやすいのは次の三つです。
- 欠損の自動補完:指示していないのに内挿や前方補完を入れることがあります。生成されたコードは、補完処理が無いかを必ず目視で確認します。
- タイムゾーン変換の二重適用:すでにUTCの列にさらに変換をかける、サマータイムの曖昧な時刻を黙って落とす、といった挙動は結果に出にくいです。
- 「きれいにしました」という報告:何行をどう処理したかの内訳が無い報告は受け取らない。処理前後の件数を出させるのが最低限です。
この辺りの詰め方はAI生成の売買コードで最初に潰す3つの穴と同じ考え方で、仕様を自分の言葉で書けるものだけを任せるという線引きになります。
整えた後に残るリスク
点検を通したデータでも、検証結果の信頼性が保証されるわけではありません。ティックから足を作る際にビッド・アスク・仲値のどれを使ったかで数値は変わりますし、提供元が異なれば同じ時刻の高値・安値も一致しません。データを整える作業は誤差を消すのではなく、誤差の正体を把握できる状態にするものです。
また、欠損が多い期間を除外して検証すると、荒れた局面だけが抜け落ちて結果が良く見えることがあります。除外した期間の一覧は必ず残し、除外あり・除外なしの両方で結果を比べる。差が大きければ、その戦略はデータ品質に敏感だという情報そのものが得られます。なお、過去データで良い結果が出ても将来の成績を示すものではありません。検証はあくまで仮説の反証作業であり、結論を出す道具ではない点は変わりません。
まとめ
- まず期待される足の並びを自分で定義し、実データとの差分として欠損を出す
- タイムスタンプの差分分布を見れば、周期の乱れは一目で分かる
- 重複は削除より先に件数と時期の偏りを数え、原因を切り分ける
- 時刻は保存をUTCに統一し、ラベルが始値側か終値側かを明示する
- ずれの検出には時間帯ごとの値幅プロファイルが使える
- AIには点検コードと分類の下書きを任せ、補完処理と時刻変換は人が確認する
- 整えた後も、足の生成方法や提供元の違いによる差は残る
この手順が効きにくい場面もあります。取得できる履歴そのものが短い場合、欠損を除外すると検証に使える本数が足りなくなります。また、提供元が一社しかなく比較対象が無い場合、ずれがあっても「それが正常」としか判断できません。そのときは、整えようとするより検証の結論を弱める——条件を絞らず、結果を幅で見る——ほうが現実的です。
この記事は、AI で下書きを作り、益山康秀(運営者)が内容を確認して公開しています
この記事は情報の提供を目的としたもので、特定の金融商品の売買をすすめるものではありません。売買の判断は、ご自身の責任で行ってください。(運営者情報)