メインコンテンツへスキップ
見出し画像

完成した競馬AIのソースコード + 使い方まとめ

    この記事では、完成した競馬AIのソースコードを実行手順つきで公開します。
    添付しているソースコードには、競馬AIの本格的な運用に必要な全ての工程が含まれています。

    • データ収集(スクレイピング)

    • データ前処理

    • 特徴量エンジニアリング

    • 機械学習モデル構築と学習

    • 的中率・回収率シミュレーション

    • レース直前オッズの取得

    • 予測実行と自動投票システム

    • サーバー上での自動運用

    • 作成したデータ・コードに対するテスト

    はじめに: Claude Codeで「勝てるAI」は作れるのか?

    Claude Code等のコーディングエージェントに頼めば、競馬AIを作ること自体はできる時代になりました。過去のデータを集めて、モデルを学習し、予想を出すところまでは、エンジニアリング・データサイエンスの経験がなくてもある程度進めることはできます。

    ただ、実際にやってみた方は痛感すると思いますが、本当に運用できる(勝てる)競馬AIを実装するには、「作れるか」より「作った後に回し続けられるシステムを設計できているか」という点が非常に重要となります。(これは競馬だけでなく、AIを使ったプロダクト開発一般に言えることですが)

    例えば、以下のようなポイントを押さえた設計が必要になります。

    • 締め切り前のオッズを見てちゃんとリターンが得られる馬券を計算し、自動投票する仕組みは整えられているか?(正直、今の競馬はここが整っていないと全く太刀打ちできないです)

    • 追加のデータを取得して新たな予測材料を加えるときに、ストレスなく追加できる構成になっているか?その際、元のコードへの影響範囲がなるべく少なくなるよう設計できているか?

    • 精度改善のための実験をする仕組みは整っているか?どの指標が上がれば「改善した」と言えるのか解明できているか?

    • 新たなモデルを実運用で試した結果、失敗して元のモデルに戻したい場合に元に戻せる構成になっているか?

    私も普段の開発業務で AI を使っていますが、AI が得意なのは「一旦動くもの」を作ることであり、来週も、半年後も、手を加えながら動き続けるかどうかは、最初にシステムをどう設計したかで決まります。AI に頼んで設計が整うかというと、ここはまだ厳しいものがあります。

    この記事で得られるもの

    この記事では、そのような「実際に運用し続けられる仕組み」まで含め、長年の試行錯誤を経て設計した競馬AIシステムを、実行手順つきでそのまま提供します。

    プログラミング初心者の方でも、以下の2ステップの実行だけで自分のPC上に競馬AIを構築することができます。

    ■ステップ1:以下のコマンドを実行してデータを収集

    # 2020年1月〜2025年12月のデータをまとめて取得する
    uv run python common/src/collect_data.py --from-ym 2020-01 --to-ym 2025-12

    ■ステップ2:画面上の「Launch 1 run」を押して予測モデルを構築

    画像

    データの加工や予測モデルの学習処理が自動で走り、PC上に競馬AIが構築されます。

    画像

    追加のファクターも取り入れやすい構成になっているので、特に競馬に詳しい方は、自分の知識を反映させて使うのもおすすめです。
    Claude Code等にコードを読ませて対話すれば、すぐに自分なりのカスタマイズにも取りかかれるでしょう。

    「元々自分で競馬AIを作ろうとしていた人」のための土台としても、これ以上のものは無いと言える自信作になっています。

    ■筆者のプロフィール
    東京大学大学院卒。現在は大手IT系事業会社で、機械学習を使った転職サイトのレコメンドエンジンや採用支援LLMエージェントの開発・運用を担当しています。競馬AIは2020年頃から開発・改良を続けており、以下のマガジンでは、その過程や設計の考え方を連載しています。

    ■免責事項
    本記事は教育・研究目的で解説するものであり、実際の馬券購入を推奨するものではありません。
    また、データ取得・馬券購入に関わる自動化プログラムは、サービス提供者のシステムに過度な負荷をかけないよう、適切な間隔をあけて実行するなどの配慮が必要です。
    なお、情報の正確さ・安全性の向上・不都合に対するサポートなどに対しては可能な限り力をいれておりますが、プログラムの実行に伴う損失や法的問題について、著者は一切の責任を負いませんので、このシステムを使用した馬券購入は自己責任で行ってください。特に自動投票を実行する際は、必ず少額から動作確認をしてください。


    ここからは早速、この競馬予想AIの使用方法を解説していきます。
    ソースコードは記事下部の「ソースコードのダウンロード」からダウンロードして解凍すれば、上記手順でそのまま実行できるようになっています。

    0. 環境設定

    この競馬AIシステムは、macOS / Windows のどちらでも動作します。

    0.1. uvのインストール(初回のみ)

    OSに応じて、ターミナルもしくはPowerShellで以下を実行します。

    macOS / Linux:

    curl -LsSf https://astral.sh/uv/install.sh | sh

    Windows (PowerShell):

    powershell -c "irm https://astral.sh/uv/install.ps1 | iex"

    インストール後はターミナルを開き直してから、uv --versionでバージョン番号が表示されることを確認してください。

    0.2. ライブラリのインストール

    ダウンロードしたzipを展開してkeibaAI-v3/‍配下にcdし、以下のコマンドを実行します。

    uv sync
    uv run playwright install

    これで必要なPython環境とライブラリをインストールすることができます。

    1. 競馬AI構築の実行手順

    まずは、配布したソースコードを使って競馬AIを構築する手順を解説します。やることは、

    • データを収集:コマンドを1行だけ実行する

    • 機械学習モデルを構築:ブラウザの画面でボタンを数回押して実行する

    の2ステップのみです。

    1.1. データの収集

    まずはcommon/配下のソースコードを実行して、必要なデータをnetkeiba.comから集めていきます。

    以下の1行をターミナルで実行すると、必要なデータがすべて順番に収集されます。

    # 2020年1月〜2025年12月のデータをまとめて取得する場合
    uv run python common/src/collect_data.py --from-ym 2020-01 --to-ym 2025-12

    指定するパラメータは次の3つです。

    • --from-ym(必須):取得を開始する月(yyyy-mm形式。例:2020-01)

    • --to-ym(任意):取得を終了する月。省略時は前月になります(当月はまだ開催日が確定していない可能性があるため、指定できません)

    • --status(任意):実際のスクレイピングは行わず、「いま何がどこまで取れているか」という取得状況だけを表示します

    最初から欲しい期間をまとめて取ってしまってもよいですし、まず動きを確かめたい方は、次のように1ヶ月分だけで試してもよいです。

    # 例として2025年9月の1ヶ月分だけ取得する
    uv run python common/src/collect_data.py --from-ym 2025-09 --to-ym 2025-09

    取得済みのデータは自動でスキップされるので、あとから期間を広げて同じコマンドを実行すれば、不足分だけが追加で取得されます。

    実行すると、次のように進捗が表示されながら、必要なデータが上から順に集まっていきます。

    対象期間: 2025-09 〜 2025-09
    
    race_id を取得
    追加スクレイピング対象月数: 1
    100%|██████████| 1/1 [00:01<00:00,  1.20s/it]
    取得した開催日数: 9
    [race_id plan]
      対象期間: 2025-09 〜 2025-09
      対象開催日 (kaisai_calendar から抽出): 9 日
      race_id スクレイピング予定: 9 日
    追加スクレイピング対象日数: 9
    100%|██████████| 9/9 [00:21<00:00,  2.34s/it]
    取得した race_id 数: 240
    
    race ページからのデータ取得
    [race plan]
      対象期間: 2025-09 〜 2025-09
      対象 race_id (race_id_list から抽出): 240 件
      HTML スクレイピング予定: 240 件
      results.csv create 予定: 240 件
      race_info.csv create 予定: 240 件
      return_tables.csv create 予定: 240 件
    100%|██████████| 240/240 [05:53<00:00,  1.47s/it]
    100%|██████████| 240/240 [00:08<00:00, 28.05it/s]
    100%|██████████| 240/240 [00:05<00:00, 44.26it/s]
    100%|██████████| 240/240 [00:07<00:00, 30.01it/s]
    
    horse ページからのデータ取得
    [horse plan]
      HTML 取得予定 horse_id: 2,784 件 (古い 0 + 未取得 2,784)
      horse_results.csv create 予定: 2,784 件
    100%|██████████| 2784/2784 [2:33:21<00:00,  3.30s/it]
    100%|██████████| 2784/2784 [00:59<00:00, 46.85it/s]
    
    血統ページからのデータ取得
    [ped plan]
      HTML スクレイピング予定: 2,784 件
      peds.csv create 予定: 2,784 件
    100%|██████████| 2784/2784 [2:41:06<00:00,  3.47s/it]
    100%|██████████| 2784/2784 [01:02<00:00, 44.30it/s]
    
    リーディングページからのデータ取得
    [jockey leading plan]
      scrape 予定 year: 1 年 [2024]
      jockey_leading.csv create 予定: 0 件
    scrape_html_leading[jockey, 2024]: 取得 4 件, スキップ 0 件
    [trainer leading plan]
      scrape 予定 year: 1 年 [2024]
      trainer_leading.csv create 予定: 0 件
    scrape_html_leading[trainer, 2024]: 取得 5 件, スキップ 0 件
    [sire leading plan]
      scrape 予定 year: 1 年 [2024]
      sire_leading.csv create 予定: 0 件
    scrape_html_leading[sire, 2024]: 取得 15 件, スキップ 0 件
    
    === 収集完了 ===

    最後に ‍=== 収集完了 ===‍ が表示されれば、その期間の学習用rawデータは準備完了です。

    期間が長いぶん、特にhorse・pedのスクレイピングには時間がかかりますが、途中で止まってしまっても、同じコマンドを再実行すれば続きから再開できます。‍

    集まったデータの中身については、後半の章で詳しく解説します。

    1.2. 機械学習モデルの構築

    次に、集めたデータから前処理・特徴量作成・モデルの学習・回収率シミュレーションまでをまとめて行います。

    ターミナル / PowerShell で v3_6_0/src に移動し、

    cd v3_6_0/src

    次のコマンドを実行します。

    uv run python run_dagster.py

    しばらくすると dagster の起動のログが流れ、最後に画面のアドレスが表示されます。

    出力例(抜粋):

    2026-10-07 10:42:53 +0900 - dagster - INFO - Launching Dagster services...
    2026-10-07 10:42:58 +0900 - dagster-webserver - INFO - Serving dagster-webserver on http://127.0.0.1:3000 in process 43599

    ブラウザで http://127.0.0.1:3000 を開きます。止めるときは、Ctrl+C を押します。

    ポート 3000 を他のアプリが使っているときは、自動で別のポートになります。ターミナルの Serving dagster-webserver on … の行に出ているアドレスを開いてください。

    左のメニューの Jobs を開き、一番上の 01_full_pipeline_for_fixed_odds_simulation を選びます。

    画像

    ジョブの画面が開きます。

    画像

    右上の Materialize all…‍ を押すと「Launch runs to materialize 18 assets」という画面が開くので、Partition selection の選択欄(Select a partition or create one)から main を選びます。

    画像

    右下の Launch 1 run を押すと実行が始まります。

    グループをクリックして展開してから、右下の+の虫眼鏡のボタン(もしくは二本指)で拡大すると、アセットごとの状態が表示されます。作り終わったアセットは緑の Materialized に、実行中のアセットは Materializing… に変わっていきます。

    画像

    最後の return_rate_fixed_tansho まで緑になれば完了です。

    画像

    これで、前処理から単勝の回収率シミュレーションまでの一通りの処理が回り終わり、PC上に競馬AIが構築されています。

    どこに何が作られたかは、後半の章で見ていきます。

    2. 何が作られたか

    先ほどの手順の裏では、netkeiba.com から集めた生テーブルを起点に、前処理・特徴量作成・学習・評価の成果物が依存関係に従って順に作られています。

    この章では、各ステップで具体的にどのようなものが作られているのか確認していきますが、その前にまずこの競馬AIがそもそもどういう仕組みで馬券を買うのか、説明しておきます。

    2.1. 競馬AIの仕組み

    AIを使った競馬では、各馬券の的中確率にオッズを掛けた‍「期待値」‍が高い馬券を買う、というのが基本戦略となります。前の章で構築した競馬AIも、この戦略で馬券を買います。

    期待値 = 的中確率(機械学習で予測) × オッズ

    ここで、この「馬券の的中確率」を機械学習モデルで正確に予測することにより、期待値の高い(=市場で過小評価されている)ものを検知することができるわけです。

    画像

    以下は、この戦略で2025年の1年間のレースを発走6分前に購入した場合のシミュレーション結果です。(オッズは発走6分前のものを使用・モデルは2020年〜2024年の5年間のデータで学習)

    画像

    青線が回収率を表していて、例えば「期待値 1.16 を超える単勝馬券を買い続けると、回収率136.2%‍に到達している」ということが読み取れます。

    馬連についても同様に、期待値1.5を超えたあたりから回収率が100%を超え始め、高い期待値のものに絞れば絞るほど、回収率が上がっていくことが分かります。

    画像

    レース当日はこの戦略に基づいて、発走直前に全馬券種の全ての組み合わせの期待値を計算して自動投票を行います。

    2.2. 集めたデータについて

    データの収集コマンドを実行すると、スクリプトは上から順に、次の5つのステップでデータを集めています。それぞれ「netkeiba.comのどのページから・何のテーブルを作るのか」を順に見ていきましょう。

    ① 開催レースの一覧(race_id)
    まず最初に、指定した期間に行われたレースの一覧(レースID)を集めます。出力の 「取得した race_id 数: 240」 が、その期間に存在したレースの総数です。これが、このあとスクレイピングしていく対象の「目次」のような役割になります。

    参考記事:

    ② レース結果(raceページ)
    集めたレースIDをもとに、各raceページから「レース結果(results)」「レース情報(race_info)」「払い戻し(return_tables)」の3つのテーブルを取得します。

    画像
    raceページ(https://db.netkeiba.com/race/202306010101/ )

    先ほどの出力でいうと、以下の部分です。

    race ページからのデータ取得
    [race plan]
      対象期間: 2025-09 〜 2025-09
      対象 race_id (race_id_list から抽出): 240 件
      HTML スクレイピング予定: 240 件
      results.csv create 予定: 240 件
      race_info.csv create 予定: 240 件
      return_tables.csv create 予定: 240 件
    100%|██████████| 240/240 [05:53<00:00,  1.47s/it]
    100%|██████████| 240/240 [00:08<00:00, 28.05it/s]
    100%|██████████| 240/240 [00:05<00:00, 44.26it/s]
    100%|██████████| 240/240 [00:07<00:00, 30.01it/s]
    画像
    「レース結果テーブル」の完成イメージ
    画像
    「レース情報テーブル」の完成イメージ
    画像
    「払い戻しテーブル」の完成イメージ

    参考記事:

    ③ 馬の過去成績(horseページ)
    次に、出走した各馬について、horseページから「馬の過去成績(horse_results)」を取得します。

    画像
    horseページ(https://db.netkeiba.com/horse/2020103575/ )

    先ほどの出力でいうと、以下の部分です。

    horse ページからのデータ取得
    [horse plan]
      HTML 取得予定 horse_id: 2,784 件 (古い 0 + 未取得 2,784)
      horse_results.csv create 予定: 2,784 件
    100%|██████████| 2784/2784 [2:33:21<00:00,  3.30s/it]
    100%|██████████| 2784/2784 [00:59<00:00, 46.85it/s]
    画像
    「馬の過去成績テーブル」の完成イメージ

    参考記事:

    ④ 血統(血統ページ)
    同じ出走馬について、血統ページから「血統テーブル(peds)」を作成します。先ほどの出力でいうと、以下の部分です。

    血統ページからのデータ取得
    [ped plan]
      HTML スクレイピング予定: 2,784 件
      peds.csv create 予定: 2,784 件
    100%|██████████| 2784/2784 [2:41:06<00:00,  3.47s/it]
    100%|██████████| 2784/2784 [01:02<00:00, 44.30it/s]
    画像
    「血統テーブル」の完成イメージ

    参考記事:

    ⑤ リーディング(リーディングページ)
    最後に、リーディングページから騎手(jockey)・調教師(trainer)・種牡馬(sire)の年別成績を作成します。モデルでは前年のデータを使用します。

    画像

    先ほどの出力でいうと、以下の部分です。

    リーディングページからのデータ取得
    [jockey leading plan]
      scrape 予定 year: 1 年 [2024]
      jockey_leading.csv create 予定: 0 件
    scrape_html_leading[jockey, 2024]: 取得 4 件, スキップ 0 件
    [trainer leading plan]
      scrape 予定 year: 1 年 [2024]
      trainer_leading.csv create 予定: 0 件
    scrape_html_leading[trainer, 2024]: 取得 5 件, スキップ 0 件
    [sire leading plan]
      scrape 予定 year: 1 年 [2024]
      sire_leading.csv create 予定: 0 件
    scrape_html_leading[sire, 2024]: 取得 15 件, スキップ 0 件
    画像
    「リーディングテーブル」の完成イメージ

    参考記事:

    ‍■取得状況を確認する(--status)‍
    「いま何がどこまで取れているか」を確認したいときは--statusを付けて実行します。この場合、実際のデータ取得は行わずに取得状況だけを表示して終了します。

    # 取得状況だけを確認する(スクレイピングはしない)
    uv run python common/src/collect_data.py --from-ym 2020-01 --to-ym 2025-12 --status

    出力例:

    === 2020-01 〜 2025-12 のデータ取得状況 ===
    
    [race_id] 開催 race_id 一覧 (race_id_list.csv)
        登録済月数: 72 / 72 (100.00%)
        期間内 race_id: 20,733 件
    
    [race] レースページからのデータ取得状況 (results / race_info / return_tables)
        results.csv: 20,733 / 20,733 (100.00%)
        race_info.csv: 20,733 / 20,733 (100.00%)
        return_tables.csv: 20,733 / 20,733 (100.00%)
    
    [horse] 馬の過去成績 (horse_results.csv)
        最新まで取得済: 35,878 / 35,891 (99.96%)
        古い (要再取得): 2 件
        未取得: 11 件
    
    [ped] 血統 (peds.csv)
        取得済: 35,891 / 35,891 (100.00%)
    
    [leading] リーディング (jockey / trainer / sire)
        jockey_leading.csv: 6 / 6 年
        trainer_leading.csv: 6 / 6 年
        sire_leading.csv: 6 / 6 年

    このデータ収集は race_id(レースID)→ race(レース結果)→ horse(馬の過去成績)/ ped(血統) という順に依存関係があり、上流がまだ取れていない段階では、その先のセクションは「取得完了後に確認可能」と案内されます。

    ‍■初回・追加・中断再開、すべて「同じ1コマンド」でよい
    初めて取得するときも、期間を後から追加するときも、処理が途中で止まって再開するときも、実行するコマンドは常に同じでよいです。

    # 例:あとから2026年1月分も追加したくなったら、--to-ym を変えて同じように実行するだけ
    uv run python common/src/collect_data.py --from-ym 2020-01 --to-ym 2026-01

    すでに取得済みのデータは自動でスキップされ、不足分だけを判定して取得してくれます。

    2.3. 前処理から回収率までのアセット

    次に、「機械学習モデルの構築」ステップでボタンを押して実行した部分について説明していきます。

    ここでは dagster という Python のツールを使っています。
    dagster は、データ処理の流れを「これを作るには、あれが要る」という依存関係つきで管理し、ブラウザの画面から実行と確認することができます。

    左のメニューの Lineage を開くと、処理の流れが工程ごとの箱と矢印のつながりで表示されます。この箱の1つ1つは「アセット(asset)」‍と呼ばれ、処理の結果として作られるデータを表します。

    画像

    特徴量テーブル・学習済みのモデル・回収率シミュレーションの結果など、この競馬AIで作られる物はそれぞれ1つのアセットで、1つのアセットが1つのファイルとして保存されます。

    先ほど 01_full_pipeline_for_fixed_odds_simulation ジョブの実行で作られたのは、以下の3つです。

    • create_features

    • train

    • simulation

    それぞれ、内容を確認してみましょう。

    ‍‍■create_features(前処理・特徴量作成)‍
    create_features では、population を起点に8つのテーブルを前処理し、払い戻し以外の7つを population に結合して特徴量テーブルを作ります。

    画像

    それぞれの中身を、実際のデータで見ていきましょう。
    表では、同じ ID の列を同じ色にしています(race_id は青、horse_id は橙、騎手・調教師・父などの ID は緑)。

    ‍▼population(出走の一覧)‍
    まずは「母集団」を表す「population」アセットです。

    画像

    1行が1頭の出走(あるレースに出た1頭)で、レースの ID・日付・馬の ID の3列だけを持ちます。

    ‍▼results(レース結果)‍

    画像

    そのレースの結果です。1行が1頭の出走で、着順・馬番・単勝オッズ(確定オッズ)・人気・馬体重・騎手の ID など、レースが終わって決まる値を持ちます。

    ‍▼race_info(レース情報)‍

    画像

    レースの条件です。1行が1レースで、芝かダートか・距離・天候・馬場などを数字のコードで持ちます。

    ‍▼horse_results(馬の過去成績)‍

    画像

    馬の過去成績です。1行が馬の1走で、同じ馬の過去のレースが何行も並びます。ここから、直近3・5・10走の着順や賞金の平均(rank_5races など)が計算されて特徴量になります。

    ‍▼peds(血統)‍

    画像

    血統です。1行が1頭で、父(sire_id)と母の父(bms_id)の ID を持ちます。

    ‍▼騎手・調教師・種牡馬のリーディング

    画像

    騎手・調教師・種牡馬の年ごとの成績です。1行が騎手×年などで、勝率・連対率・複勝率・出走数を持ちます。種牡馬は芝とダートで行が分かれます。

    ‍▼return_tables(払い戻し)‍

    画像

    払い戻しです。1行が1レースの券種×的中馬番で、100円あたりの払戻金を持ちます。回収率シミュレーションの時に使います。

    ‍‍■train(学習)‍
    ここで、アセット詳細の画面で中身を確認してみましょう。
    アセット詳細を開くには、グラフ上でグループをクリックして展開し、アセットをクリックして選びます。右側がそのアセットの概要に切り替わるので、View in Asset Catalog を押します。

    画像

    ‍▼学習データ(dataset_tansho_train)‍

    画像

    dataset_tansho_trainは、特徴量テーブルを期間で分けた、学習用のデータです。検証用(dataset_tansho_valid)・テスト用(dataset_tansho_test)と合わせて3つが作られ、Metadata には行数と期間の設定が記録されます。

    画像

    3つの期間は、時系列の順に分けています。モデルが学習するのは学習データだけです。検証データは、学習の途中で精度を見ながら止めどきを決める early stopping と、確率補正モデルの学習に使います。

    テストデータは学習に一切使わない、未来のレースの代わりのデータで、モデルの精度と回収率はこのテストデータで確かめます。

    ‍▼学習の設定(train_config)‍
    学習に使う特徴量の列と、LightGBM のハイパーパラメータです。

    画像

    実験名ごとに保存されるので、あとから別の設定で実験を足すこともできます。

    ‍▼単勝予測モデル(model)‍
    LightGBM で学習した、各馬の勝率を予測するモデルです。

    画像

    ‍▼確率補正モデル(calibration_model)‍
    モデルが出す予測確率を、実際の勝率に近づけるように補正(キャリブレーション)するモデルです。

    画像

    ‍■simulation(評価・回収率シミュレーション)‍

    ‍▼評価テーブル(evaluation_df_fixed)‍
    テストデータの各馬に、予測確率と確定オッズを付けた表です。

    画像

    ‍▼v3_6_0/data/assets/evaluation_df_fixed/main.parquet の中身(抜粋)

    race_id       horse_id    target  target_mod  rank  tansho_odds  popularity  umaban  pred      pred_calibrated
    202506010101  2022102642  0       0           11    231.3        15          1       0.004326  0.002547
    202506010101  2022101022  0       0           6     50.1         7           2       0.023532  0.016147
    202506010101  2022106581  0       0           2     12.0         6           3       0.086071  0.066138
    202506010101  2022100105  0       0           8     8.4          4           4       0.109912  0.086142
    202506010101  2022102964  0       0           10    196.9        13          5       0.003669  0.002128
    202506010101  2022107201  0       0           15    75.8         9           6       0.013303  0.008670
    202506010101  2022101692  0       0           9     11.6         5           7       0.095148  0.073715
    202506010101  2022106350  0       0           7     211.8        14          8       0.003726  0.002164
    202506010101  2022102984  0       0           12    131.9        10          9       0.009860  0.006254
    202506010101  2022103727  0       0           4     2.8          2           10      0.309921  0.260131
    202506010101  2022105247  1       1           1     2.5          1           11      0.307763  0.258230
    202506010101  2022100076  0       0           5     7.3          3           12      0.133421  0.106141
    202506010101  2022107050  0       0           3     156.0        11          13      0.006822  0.004185
    202506010101  2022102350  0       0           14    189.5        12          14      0.004377  0.002579
    202506010101  2022103312  0       0           16    556.3        16          15      0.003462  0.001998
    202506010101  2022101055  0       0           13    73.0         8           16      0.017353  0.011585

    ‍▼回収率シミュレーション結果(return_rate_fixed_tansho)‍
    評価テーブルと払い戻しのテーブルから計算した、回収率シミュレーション結果です。

    画像

    View in Asset Catalog で詳細を見てみます。

    画像

    主な指標の意味は次のとおりです。

    指標            意味
    expect_return   期待値の閾値(この値を超えた馬券を買う)
    total_bets      買った馬券の点数(1点100円)
    hits            払い戻しがあったレース数
    hit_rate        レース単位の的中率(hits ÷ 買ったレース数)
    return_rate     回収率(払い戻しの合計 ÷ 購入点数)
    std             回収率のぶれ幅(標準誤差)
    sharp_ratio     回収率の安定度((return_rate − 1) ÷ std。大きいほど安定)

    以上が、1つのジョブで完成するアセットです。これらの結果は、次の場所にファイルとしても保存されます。

    v3_6_0/data/assets/
    ├── population.parquet              出走の一覧
    ├── results.parquet                 レース結果
    ├── race_info.parquet               レース情報
    ├── horse_results.parquet           馬の過去成績
    ├── peds.parquet                    血統
    ├── jockey_leading.parquet          騎手の年次成績
    ├── trainer_leading.parquet         調教師の年次成績
    ├── sire_leading.parquet            種牡馬の年次成績
    ├── return_tables.parquet           払い戻し
    ├── features.parquet                特徴量テーブル
    ├── dataset_tansho_train.parquet    学習データ
    ├── dataset_tansho_valid.parquet    検証データ
    ├── dataset_tansho_test.parquet     テストデータ
    ├── train_config/
    │   └── main.pkl                    学習の設定
    ├── model/
    │   └── main.pkl                    単勝予測モデル
    ├── calibration_model/
    │   └── main.pkl                    確率補正モデル
    ├── evaluation_df_fixed/
    │   └── main.parquet                評価テーブル(確定オッズ)
    └── return_rate_fixed_tansho/
        └── main.parquet                回収率カーブ(確定オッズ×単勝)

    dagsterの詳しい使い方や各アセットの詳細については、以下の記事に画面つきでまとめているので、併せて読んでいただくと理解しやすいかと思います。

    dagster そのものについては、以下の記事で入門として解説しています。

    前処理・特徴量作成の中身と、モデル学習・精度検証の考え方については、以下の記事でも詳しく図解付きで解説しています。

    3. 直前オッズでの回収率シミュレーション

    本番と同じ条件で回収率を確かめるには、発走前のオッズでのシミュレーションが必要になりますが、Web上に表示されている過去のレース情報には、レース終了後の確定オッズしか存在しません。

    そこでこの競馬AIでは、JRA-VAN の公式ソフトやJRA の公式サイトのスクレイピングで集めた時系列オッズを使って、直前オッズでシミュレーションできるようにしています。

    ‍左のメニューの Jobs を開くと、4つのジョブが並んでいます。

    画像

    一番上の 01_full_pipeline_for_fixed_odds_simulation は、先ほどの手順で実行したジョブです。

    直前オッズを使うのはその下の2つで、
    02_full_pipeline_for_jravan_odds_simulation は JRA-VAN の公式ソフトから取得した時系列オッズでシミュレーションできます。

    03_full_pipeline_for_scraping_odds_simulation は、JRA の公式サイトからスクレイピングして集めた時系列オッズで、単勝・馬連・馬単・三連複・三連単をシミュレーションできます。

    例えば、02_full_pipeline_for_jravan_odds_simulation のジョブを実行すると、以下のような発走6分前オッズを使った単勝・馬連の回収率シミュレーション結果が得られます。

    画像
    発走6分前オッズを使った単勝馬券シミュレーション
    読み方:期待値 1.16 を超える馬券を買い続けると回収率が 136.2% に達する
    画像
    発走6分前オッズを使った馬連馬券シミュレーション

    馬連のような組み合わせの馬券は、内部で全ての組み合わせごとの予測的中確率と期待値を計算しています。

    同様に、03_full_pipeline_for_scraping_odds_simulation のジョブを実行すると、今度は単勝・馬連に加えて三連複・三連単のシミュレーションも実行できます。

    画像
    スクレイピングした発走4分前オッズを使った三連複馬券シミュレーション
    期待値 2.62 を超えるものを買い続けると回収率が 200.6% に達する
    (ただし、閾値を上げるにつれて購入数は少なくなるので、ブレも大きくなる)
    画像
    スクレイピングした発走4分前オッズを使った三連単馬券シミュレーション

    本番の投票も、このシミュレーションと同じ買い方で行います。レース当日はサーバーを起動しておき、発走直前に全馬券種の全ての組み合わせの期待値を計算して自動投票を行います。


    ここからは有料部分となります。
    ここまでの実行に必要な全てのソースコードが添付ファイルで含まれ、ダウンロードしてそのまま使うことができます。

    購入後の個別サポートも行っているので、もし詰まったところがあれば、動かし切るところまで伴走しますのでご連絡ください。

    ソースコードは今後もアップデートが予定されており、それに応じて価格が上がる可能性が高いので、予めご了承ください。

     
     
    競馬予想AIを作ることを通して、機械学習・データサイエンスの勉強になるコンテンツの発信や、筆者が行った実験の共有などを行っていきます。

    あなたへのおすすめ