過去のレースを使って買い方や予測ルールを試す作業は、一般にバックテストと呼ばれます。ただし、表計算が正しく動き、回収率の式が合っていても、その結果が実戦で再現できるとは限りません。レース前には知らなかった情報が入力に混ざると、過去へ戻って未来を知っていたかのような検証になるためです。
この記事では、この問題を「データ漏洩」として整理します。特に起きやすいのが、レース後に取得した確定オッズの混入、結果を見てからの条件変更、欠場・取消行の削除です。対策の中心は、高度な予測モデルではありません。「その時点で何を知ることができたか」を列で残し、ルールを結果より先に固定することです。
ここで示す回収率や件数は書式を説明する架空例であり、実在レースの成績ではありません。検証表の基本項目はレース検証の記録のつけ方、回収率の分母と読み方は回収率という物差しも参照してください。
データ漏洩の意味
データ漏洩とは、判断する時点では利用できなかった情報を、予測ルールの作成や評価に使ってしまうことです。機械学習ライブラリscikit-learnの公式文書も、予測時点で利用できない情報をモデル構築に使うと、評価が過度に楽観的になると説明しています。また、テスト用データをモデル選択に使わず、前処理より先に訓練用とテスト用へ分けることを推奨しています(2026年7月23日確認:scikit-learn「Common pitfalls and recommended practices」)。
レース検証では「モデル」を作っていなくても同じ問題が起きます。たとえば、次のような情報は取得時点によって役割が変わります。
| 情報 | レース前の保存値 | レース後に判明する値 | 漏洩になる使い方 |
|---|---|---|---|
| オッズ | 自分が判断した時刻の表示オッズ | 最終オッズ、払戻金 | 最終オッズで買えたと仮定する |
| 出走状態 | その時点の出馬表、変更情報 | 取消・除外を反映した確定状態 | 取消馬を最初から存在しなかったことにする |
| 着順 | 不明 | 確定着順、競走中止等 | 的中馬の特徴を見てから条件に足す |
| 馬場・気象 | 判断時点の発表値 | 発走時や結果画面の値 | 後の状態を前から知っていた入力にする |
重要なのは、結果データを使うこと自体が悪いのではない点です。着順や払戻金は成績を採点するために必要です。問題は、採点用の情報を「買うかどうかを決める入力」へ戻すことにあります。検証表では、少なくとも「判断に使える列」と「結果確定後に更新する列」を分けます。
次の三つの時刻を一行ごとに持つと、境界が見えやすくなります。
decision_at:買う・見送るを決めた時刻observed_at:オッズや出馬表を実際に取得した時刻settled_at:結果と払戻しを記入した時刻
observed_atがdecision_atより後なら、その値は当時の判断材料として使えません。空欄を後から埋めても、取得時刻を過去へ書き換えないことが原則です。
確定オッズを混ぜる失敗
JRA公式サイトは、開催中のページでは「最新の情報」を表示し、終了したレースでは「最終オッズ」を表示すると案内しています(2026年7月23日確認:JRA「ホームページでオッズを見ることができますか?」)。つまり、レース後に結果ページから集めたオッズは、レース前のある時刻に画面で見たオッズと同じとは限りません。
さらにJRAの用語辞典では、オッズは100円に対する概算払戻率であり、発売締切後に表示される最終オッズも、その後の競走除外で変動し得ると説明されています。同着など結果によっては、発表された最終オッズと異なる率の払戻金になる場合もあります(2026年7月23日確認:JRA競馬用語辞典「オッズ」)。
したがって、次の検証は意味が異なります。
- 判断時点オッズを使う検証:その時刻に見えていた条件で選べたかを調べる
- 最終オッズを使う集計:市場の最終評価や結果との関係を振り返る
- 払戻金を使う精算:実際の的中時にいくら戻ったかを確定する
たとえば「単勝オッズ5.0倍以上を買う」というルールを調べるなら、判断時刻に4.8倍だった馬を、最終オッズが5.2倍だったから対象へ加えてはいけません。反対に、判断時刻に5.1倍でも最終オッズが4.7倍へ下がることがあります。最終オッズしか保存していないデータからは、このルールを当時そのまま実行できたか判断できません。
対策はオッズ列を一つにしないことです。
| 列名の例 | 内容 | 用途 |
|---|---|---|
odds_observed | 判断前に実際に確認した表示値 | 買い目選定 |
odds_observed_at | その値を取得した日時 | 利用可能時点の監査 |
odds_final | レース後に確認した最終オッズ | 事後分析 |
payout_per_100 | 100円当たりの確定払戻金 | 収支精算 |
odds_source_url | 確認した公式ページ | 出典確認 |
判断時点オッズがない行は、0や最終オッズで補完せず「未取得」にします。その行はオッズ条件付きルールの評価対象から外し、除外件数を表示します。最終オッズしかない場合は、「最終オッズによる事後分類」と明記し、実行可能性を測るバックテストとは分けてください。
結果後に条件を変える失敗
過去データを見ながら条件を調整すると、偶然よく見える組み合わせを選べます。最初は「1番人気かつ単勝3倍以上」だったのに、成績が悪い月を見て「重馬場を除く」、さらに外れを見て「特定距離も除く」と変えていけば、同じデータへの当てはまりは良くなります。しかし、そのルールが未知の期間でも働く証拠にはなりません。
条件変更には、少なくとも三種類あります。
- 誤りの修正:券種の判定式や払戻計算のバグを直す
- 仮説の変更:距離、人気、オッズなどの採用条件を変える
- 集計定義の変更:取消、返還、同着、欠測の扱いを変える
誤りの修正は必要ですが、修正前後の版と影響件数を残します。仮説や集計定義を変えた場合は、同じ検証期間の成績を新ルールの合格点として使いません。変更後のルールは、まだ見ていない期間で改めて評価します。
「結果を見た後で気づいた良い条件」を捨てる必要はありません。ただし、それは検証済みの結論ではなく、次の検証に回す仮説です。記録上は次のように分けます。
旧ルール v1.0:距離と人気だけで判定。2024年分を探索に使用。
新仮説 v1.1:馬場状態を追加。2024年分を見て着想したため、同期間の成績は参考値。2025年分を未見の検証期間とする。
条件を何通り試したかも残してください。20通りを試して最も良かった1通りだけを示すのと、最初から決めた1通りが同じ成績だったのとでは、証拠の強さが違います。試行数を後から正確に復元できない場合は「条件探索あり・試行数不明」と注記し、単独の成功例を再現性のある傾向と断定しません。
条件探索と評価を同じデータで行う問題は、予測モデルの設定調整でも共通します。scikit-learnの公式例は、同じデータで設定を選び、その性能も評価する非ネスト型の交差検証では、データへの過適合によって評価が楽観的になり得ると説明しています。内側で設定を選び、外側の未使用データで評価するネスト型交差検証は、その分離を保つ方法の一つです(2026年7月24日確認:scikit-learn「Nested versus non-nested cross-validation」)。表計算で条件を比較する場合も、考え方は同じです。
よくある漏洩の見分け方
| 検証結果に見える兆候 | 考えられる原因 | 記録で確認する項目 | 修正後の扱い |
|---|---|---|---|
| 過去成績だけが不自然に良い | 結果を見ながら条件を追加した | ルール作成日時、変更履歴、試行数 | 変更後に未使用期間で再評価 |
| オッズ条件の境界付近で対象が増える | 最終オッズを判断時点の値として使用した | odds_observed_at、odds_final | 判断時点値がない行は未取得 |
| 取消や欠測が一件もない | 不都合な行を削除した | 原票件数、状態別件数、除外理由 | 原票へ戻し、集計時に状態別処理 |
| 集計をやり直すと数字が変わる | データや計算式を上書きした | データ版、ルール版、集計版 | 旧版を残して影響件数を比較 |
| 検証期間を変えるたび条件も変わる | 評価期間が探索期間へ戻っている | 期間ごとの役割、ルール確定日時 | 次の未使用期間を検証に回す |
検証用期間を分ける
最も扱いやすい対策は、時系列に沿って期間を分けることです。過去側でルールを作り、それより未来側で一度だけ評価します。レースは時間順に発生するため、全期間を無作為に混ぜると、未来側の開催傾向やデータ処理結果が過去側の設計へ入りやすくなります。
scikit-learnの公式文書も、時系列データを通常の交差検証で分けると「未来のデータで学習し、過去で評価する」形になり得るため、時間順の分割を用いると説明しています(2026年7月23日確認:scikit-learn「TimeSeriesSplit」)。これは特定のソフトを使う場合だけの話ではなく、表計算でも守れる考え方です。
期間は、次の三つに分けると役割が明確になります。
| 期間 | 役割 | してよいこと |
|---|---|---|
| 探索期間 | 傾向を見て仮説を作る | 条件を比較し、ルール案を作る |
| 検証期間 | 固定したルールを評価する | 事前登録した集計だけを実行する |
| 運用記録期間 | 実際の判断手順を確認する | 判断時点の入力と見送りを含めて保存する |
架空例として、2023年を探索、2024年を検証、2025年を運用記録にします。2024年の結果を見て条件を変えたら、その時点で2024年は探索済みです。変更後ルールの検証には、まだ条件調整へ使っていない2025年以降が必要になります。
開催制度、データ形式、オッズ取得方法などが期間途中で変わった場合は、単純に結合しません。変更日を境界として版を分け、同じ定義で比較できるか確認します。公式資料で変更日や適用範囲を確認できない場合は「※要確認」とし、推測した境界で結論を出さないでください。
期間の前後に間隔を空ける方法もあります。たとえば、前日までの集計値を当日の特徴量に使う処理で当日結果まで誤って含める危険があるなら、集計対象終了日と評価開始日の間を空けます。何日空けるべきかはデータ更新の仕組みによるため、一律の正解はありません。必要な間隔を決めた根拠と、集計処理が参照する最終日時を検証票へ書きます。
欠場・取消データを残す
欠場や取消を単に行削除すると、「レース前には候補だったが、後で買えなくなった」という経過が消えます。JRAは、出走取消を装鞍所へ入る前、競走除外を装鞍所へ入ってから発走までに出走を取りやめることと説明しています(2026年7月23日確認:JRA「出走取消(あるいは競走除外)の意味」)。
JRAのレース結果の見方では、「失格」「中止」「除外」「取消」を別の状態として表示すると案内されています(2026年7月23日確認:JRA「レース結果の見方」)。これらをすべて着順0や外れへ変換すると、出走しなかった馬と出走後に競走中止となった馬を区別できません。
原票には行を残し、状態を別列にします。
| 列名の例 | 記録例 | 注意点 |
|---|---|---|
status_at_decision | 出走予定 | 判断時点で見えていた状態 |
final_status | 正常、取消、除外、中止、失格 | 公式結果の表記を保持 |
status_announced_at | 日時または未取得 | いつ知り得たかを区別 |
ticket_status | 購入、見送り、返還、購入不能 | 予測結果と収支を分ける |
exclusion_reason | 取消のため評価対象外 | 空欄、0、対象外を混同しない |
出走取消馬を的中率の分母へ含めるかは、何を評価するかで変わります。「予測が当たった割合」なら出走しなかった馬を着外扱いするのは不自然です。一方、「候補抽出後に実際に投票まで進めた割合」を測るなら、取消も運用上の発生件数として残す必要があります。原票を消さず、集計ごとの採用条件を明記すれば、両方を計算できます。
収支では、取消・除外を単純な外れとして扱わないようにします。JRA公式「馬券のルール」は、発売開始後に出走取消または競走除外があった場合、単勝・複勝では出走しない馬番、馬連・馬単・ワイド・3連複・3連単などではその馬番を含む組合せが返還対象になると案内しています。枠連は同じ枠に残る馬の数などで扱いが異なります(2026年7月24日確認:JRA「馬券のルール」)。検証表では、購入額、返還額、収支対象額を別列にし、券種ごとの公式ルールを反映してください。
レース結果が確定するまでの状態も区別します。JRA公式は、到達順位の表示後に確定ランプが点灯するとレースが確定し、その後に払戻金が発表されると説明しています(2026年7月23日確認:JRA「レースの確定」)。速報の着順を確定結果として保存せず、result_statusを「速報」「確定」に分けると上書き事故を防げます。
ルールと版を固定する
再現可能な検証には、ルールの文章と計算ファイルの版が必要です。「人気薄を買う」「悪天候を除く」のような言葉だけでは、実行する人によって対象が変わります。各条件を、機械的に同じ判定ができる形へ直します。
最低限、次を固定します。
- 対象競技、競馬場、期間、券種
- 1レースを一行にするか、1頭・1組合せを一行にするか
- 判断時刻と、その時刻までに利用できる情報
- オッズ条件に使う列と、欠測時の扱い
- 的中、購入額、払戻額、返還の計算式
- 取消、除外、中止、失格、同着の処理
- 条件に一致しない見送り行を保存するか
- 小数の丸め方と、率の分母
- 探索期間と検証期間
- ルール版、データ版、集計版
ルールIDはrule-001-v1.0のように付け、条件を変えたら上書きせずv1.1へ進めます。修正履歴には「何を」「なぜ」「どの結果を見る前に」変えたかを書きます。計算式だけを直した場合も、旧版の出力を残して影響行数を比較します。
データにも版を付けます。同じファイル名へ最新値を上書きすると、以前の集計を再現できません。取得日時、対象期間、出典URL、ファイルの識別値を残します。ファイル識別値としてハッシュ値を使う場合は、同じ内容から同じ値を得られる方式とツール名を記録します。方式が未定なら「※要確認」とし、架空の値を置きません。
ルールを固定しても、将来の利益や的中を保証するものではありません。過去の環境と今後の環境は同一ではなく、オッズ条件を満たす買い目が毎回得られるとも限りません。バックテストの役割は「決めた手順を過去データへ同じように適用した結果」を測ることであり、未来を確定することではありません。
再現可能な検証票を作る
最後に、第三者や数か月後の自分が同じ集計をやり直せる検証票へまとめます。結果の数字だけでなく、入力、時刻、除外、版を一枚で追える形にします。
検証票のひな型
| 項目 | 記入内容 |
|---|---|
| 検証ID | 一意の番号 |
| 検証目的 | 何を確かめるかを一文で記載 |
| 仮説登録日時 | 結果集計を始める前の日時 |
| ルールID・版 | 例:rule-001-v1.0 |
| 探索期間 | 条件作成に使った期間 |
| 検証期間 | 条件調整に使わない期間 |
| 判断時刻 | 発走何分前ではなく実際の取得日時を推奨 |
| 入力列 | 判断時点で利用可能な列の一覧 |
| 結果列 | 確定後にだけ更新する列の一覧 |
| 欠測処理 | 除外、保留など。0埋めと区別 |
| 取消等の処理 | 状態別の分母・収支への反映 |
| データ出典 | 公式URL、取得日、対象期間 |
| 対象件数 | 全件、有効件、欠測、取消等を別掲 |
| 評価指標 | 的中率、回収率などの式と分母 |
| 試した条件数 | 採用しなかった条件も含む |
| 実行日時 | 集計を実行した日時 |
| 変更履歴 | 変更内容、理由、変更前に見た期間 |
集計結果には、少なくとも「全候補件数」「購入条件一致件数」「実際に評価できた件数」「欠測件数」「取消・除外件数」を並べます。有効件だけを示すと、都合の悪い行を落としていないか確認できません。見送りも含めた全行を原票に残し、集計表は原票から作ります。
検品は次の順で行います。
- 検証期間の開始前にルール版が作成されているか
- 入力列の取得時刻が判断時刻以前か
- 最終オッズや確定着順が選定条件へ入っていないか
- 条件変更に使った期間が検証期間へ残っていないか
- 取消・除外・中止・欠測の原票が消えていないか
- 同じルール版とデータ版で再計算して同じ結果になるか
- 結果表に分母、除外件数、試行数が表示されているか
一つでも確認できない項目があれば、結果を捨てる必要はありません。「判断時点オッズ未取得」「条件探索回数不明」など、証拠として弱い理由を明記します。完全な記録に見せるより、どこまで再現できるかを正直に示す方が、次の検証を改善できます。
よくある質問
最終オッズしかないデータでもバックテストできますか
最終オッズと結果の関係を調べる事後分析はできます。ただし、判断時点のオッズ条件を当時実行できたかは確認できないため、「最終オッズによる事後分類」と明記し、実行可能性を評価する検証とは分けます。
探索期間と検証期間は何対何に分ければよいですか
一律の比率はありません。件数、条件数、開催制度の変更、配当のばらつきによって必要量が変わります。期間の比率を先に固定するより、時間順を守り、検証期間を条件調整に使わないことを優先します。件数の考え方は回収率は何レースで判断できるかも参照してください。
条件を一度変えたら、それまでのデータは使えませんか
使えなくなるわけではありません。条件変更に使った期間は探索済みとして、旧ルールとの比較や仮説作りに使えます。変更後ルールの評価だけを、まだ見ていない期間へ移します。
取消・除外・返還は回収率の分母へ入れますか
購入額をそのまま分母にするか、返還額を差し引いた実質投資額を分母にするかで値が変わります。採用する式を事前に決め、購入額・返還額・実質投資額を別々に表示してください。取消行そのものは原票から削除しません。
表計算だけでもデータ漏洩を防げますか
防げます。入力列と結果列の分離、取得日時、ルール版、期間の役割、欠測・取消の状態を残すことが中心です。途中オッズと最終オッズの記録例は最終オッズの変動を検証する記録方法、条件別集計の例は人気薄ほど有利に見える?本命・大穴バイアスの検証も参考になります。
この記事では、scikit-learnのデータ漏洩対策、時系列分割、条件探索と評価の分離、およびJRAのオッズ表示・定義、取消・除外、結果画面、レース確定、返還ルールの公式情報を参照しました。既存7件は2026年7月23日、追加2件は2026年7月24日に確認しています。ページの内容やデータ提供方法は今後変わる可能性があるため、実際の検証開始時にも取得日とURLを残してください。