AIが作った競馬予想ソフトの中身を全公開

AIツール

先日、noteで「AIを使ってWebサービスを開発する方法」という記事を公開しました。

その中で、開発チュートリアルの具体例として作った競馬予想デスクトップアプリに、興味を持っていただき、

・本当にAIだけで作ったのか。

・仕組みが知りたい。

といった声を頂けたので、今回はソフトの仕組み・設計について解剖していきます。

実際のコード構造に基づいて解説するので、「AIが書いたコードって実際どうなの?」という疑問にも答えられる内容になっているはずです。

このアプリは何ができるのか

このアプリは、レースの出馬表URLを入力するだけで、自動的にデータを収集し、各馬をスコアリングして、期待値の高い馬券を推奨してくれるデスクトップアプリです。

できることを整理すると、こうなります。

  • netkeiba または JRA公式サイトの出馬表URLを貼り付ける
  • 出走馬の情報(馬名、騎手、斤量、オッズなど)を自動で取得する
  • 5つの要素から各馬の「総合スコア」を計算する
  • JRA過去10年の実測統計をもとに、勝率・複勝率を算出する
  • 期待値 = 予測勝率 × オッズ − 1 の計算で、買うべき馬券を選別する
  • 単勝・複勝・3連単・3連複の推奨馬券を、期待値が高い順に表示する

画面は3つのタブで構成されています。

  1. 出馬表・予想タブ:各馬の予想着順と期待値を一覧表示
  2. 推奨馬券タブ:期待値フィルタを通過した馬券を、期待値順にランキング表示
  3. 分析詳細タブ:レースの展望や予測の信頼度をレポート形式で表示

GUIはPyQt6で構築されていて、Windowsでもmacでも動きます。

アプリの全体構成──データの流れ

ソフトは7つのPythonファイルで構成されています。それぞれの役割はこうです。

メイン(約1,200行) アプリの本体。GUI画面の構築、スコアリング計算、期待値計算、推奨馬券の生成まで、すべてここで動いています。

データスクレイパー netkeibaからデータを取得するスクレイパー。出馬表、オッズ、馬の過去成績、騎手成績を収集します。

JRAスクレイパー JRA公式サイトからデータを取得するスクレイパー。Shift_JISエンコーディングへの対応や、URLからレースIDを自動抽出する処理が入っています。

騎手データベース 60名以上の騎手の勝率・連対率・芝ダート適性・グレード(S〜D)をマスターデータとして保持。騎手スコアの計算ロジックもここにあります。

winテーブル 過去の統計に基づく「人気別の勝率・複勝率テーブル」。1番人気の勝率32.3%、2番人気18.8%……といった実測値がハードコードされています。

計算・予測 統計ベースの予測モデル。5つの要素を重み付けして総合スコアを算出し、順位予測・勝率計算・期待値計算を一気通貫で行います。

レースデータベース SQLiteを使ったデータ蓄積モジュール。レース情報、馬情報、騎手成績、過去の結果を保存して、使うほどデータが蓄まる設計になっています。

データの流れを一言で書くと、こうなります。

URL入力 → スクレイパーがデータ収集 → 騎手DBと統計テーブルを参照 → 5要素スコアリング → 実測統計で勝率算出 → 期待値計算 → 推奨馬券を画面表示(+SQLiteに保存)

データ取得の仕組み──2つのスクレイパー

このソフトは、入力されたURLを見て自動的にスクレイパーを切り替えます。

URLにjraが含まれていればJRA公式サイト用、netkeibaが含まれていればnetkeiba用。それ以外のURLはエラーになります。

どちらのスクレイパーも、取得する情報は基本的に同じです。

  • レース情報(レース名、コース、距離、芝/ダート、天候、馬場状態、クラス)
  • 出走馬情報(枠番、馬番、馬名、騎手、斤量、性齢、馬体重、オッズ)
  • オッズデータ(単勝オッズ)

技術的に面白いのは、HTMLの構造が違うサイトに対して、複数のフォールバックパターンを用意している点です。

たとえばJRA公式サイトのスクレイパーでは、出馬表テーブルを探す際に3段階の検索を行います。

  1. まず 出馬表 属性を持つテーブルを探す
  2. 見つからなければ「馬番」というヘッダーを含むテーブルを探す
  3. それでもダメなら、ページ内で最も行数が多いテーブルを使う

HTML構造が変わっても壊れにくい設計です。

もう一つ、サーバーへの負荷軽減のために time.sleep(10) でリクエスト間に10秒の待機を入れています。スクレイピングのマナーとして大事な部分です。

推奨馬券の見極め

予測勝率はどこから来るのか

ここがこのソフトの独自性のある部分です。

予測勝率は「自分で計算した確率」ではなく、JRA過去10年の実測データをそのまま使っています。

具体的には、人気順位と勝率の対応テーブルをアプリ内に持っています。

予想順位勝率複勝率(3着以内)
1位32.3%62.8%
2位18.8%51.2%
3位13.2%42.8%
4位9.3%36.1%
5位6.8%30.5%
6位4.8%25.8%
10位1.6%13.4%
15位0.4%5.9%

「アプリが1位と予想した馬の勝率は32.3%」「3位予想なら13.2%」という具合に、予想着順に対応する実測勝率を当てはめて期待値を計算しています。

券種ごとのフィルタ基準

4つの券種で、それぞれ異なるフィルタ基準を設けています。

券種フィルタ基準理由
単勝期待値 > 0プラスの馬券だけを推奨
複勝期待値 > -0.1手数料が安いので少し緩め
3連単期待値 > 0.2ハイリスクなので基準を厳しく
3連複期待値 > 0.13連単よりは緩め

複勝だけ「マイナスでもOK」にしているのは、複勝はJRAの控除率が低い(約20%)ため、わずかにマイナスでも他の券種より回収率が高くなる傾向があるからです。

3連単・3連複については、的中確率を3連単確率テーブルや条件付き確率モデルから算出しています。たとえば3連複の的中確率は、3連単の6通り分(3! = 6)として概算しています。

推奨度の星評価

期待値の大きさに応じて、ユーザーが直感的に判断できる星評価も付いています。

期待値星評価
1.0 超★★★★★
0.6 超★★★★☆
0.3 超★★★☆☆
0.1 超★★☆☆☆
それ以下★☆☆☆☆

データベース設計

このソフトには、SQLiteデータベースによるデータ蓄積機能が組み込まれています。

6つのテーブルで構成されています。

  • レース情報(コース、距離、馬場状態など)
  • 馬のマスター情報
  • レース結果(着順、オッズ、タイムなど)
  • 騎手の成績統計
  • 調教師の成績統計
  • 馬ごとの過去成績キャッシュ

使うたびにデータが蓄積され、将来的には 機械学習用の訓練データを一発取得できる設計になっています。類似条件のレース結果を引っ張ることもできます。

今はルールベースの予測ですが、データが蓄まれば機械学習モデルに切り替える土台がすでに用意されているということです。

正直に書く「限界と課題」

せっかくなので、このアプリの弱点も正直に書きます。

オッズ依存度が高い。 スコアリングの60%をオッズが占めているので、基本的には人気馬が上位に来やすい。大穴を狙う使い方には向いていません。

3連単・3連複のオッズが推定値。 単勝オッズはスクレイピングで取得していますが、3連単・3連複のオッズはbase_odds = 50.0 + idx * 30.0 のような推定値を使っています。実際のオッズとズレがあるため、マルチ系券種の期待値は参考値の域を出ません。

的中実績はまだ検証中。 アプリとして形にはなっていますが、実際のレースで長期的に回収率がプラスになるかは、まだ十分に検証できていません。ここは今後データを蓄積しながら改善していく部分です。

AIモデルは未完成。 現時点では機械学習は使っておらず、ルールベースの重み付けスコアリングです。LightGBMなどの機械学習モデルを組み込む準備(specファイルにlightgbmが記載されている)はあるものの、まだ実装されていません。

ただ、重要なのは「完璧かどうか」ではなく、AIだけでここまでの構造を持つソフトが作れたという事実だと思っています。

7つのPythonファイル、合計3,000行以上のコード。スクレイパー2つ、騎手データベース、統計テーブル、SQLiteデータベース、GUI。これを自分は1行もコードを手書きせずに作りました。

まとめ

この記事では、AIで作った競馬予想ソフトの仕組みを見せました。

  • データ取得:2つのスクレイパーで自動収集
  • スコアリング:オッズ・騎手・馬体重・性齢・斤量の5要素
  • 勝率算出:JRA過去10年の実測統計テーブル
  • 期待値計算:予測勝率 × オッズ − 1 で馬券の価値を判定
  • データ蓄積:SQLiteで将来の機械学習に備える設計

「中身を見て、自分でも何か作ってみたい」と思った方もいるかもしれません。

このソフトは、Claude AI(設計レビュー担当)と Antigravity(実装担当)のAI二人体制で、コードを1行も手書きせずに作りました。設計書をAIに書かせて、別のAIにレビューさせて、修正して、開発に進む。

プログラミングの知識がなくても、「正しいツールの使い方」を知っていれば、ここまでのものが作れます。

コメント

タイトルとURLをコピーしました