学ぶ ・ 予想のしくみ

予想エンジン — 加重平均で点数をつける

レース予想画面の「印」と「買い目」を作っている Kotlin の予想エンジンを、式ひとつひとつまで分解します。実際の出力を手計算で再現し、その上で「勝率」と「期待値」が数学的にどこで破綻しているかも正直に示します。

このページで学ぶこと
  • ペース予想のルールと、6 つの要素の点数のつけ方
  • 加重平均とクリップ (上下限で切る) の意味
  • ドウデュースの総合スコア 99.2 を手計算で再現する
  • 画面の「勝率」が確率になっていない理由と、「期待値」がほぼ全頭同じになる理由
  • 印と買い目の決め方

全体の流れ

出走馬の一覧 ──> ① ペース予想 ──> ② 各馬の 6 要素の点数 ──> ③ 加重平均 (総合スコア)
            ──> ④ 「勝率」「期待値」 ──> ⑤ スコア順に印 ──> ⑥ 印から買い目

コードは 1 ファイル (service/PredictorEngine.kt) にまとまっています。ここで使っている係数 (0.35 など) は 経験則で決めた値 で、データから統計的に推定したものではありません。そのことを前提に読んでください。

① ペース予想 — 逃げ・先行の頭数で決める

n逃n_\text{逃} = 逃げ馬の頭数、n先n_\text{先} = 先行馬の頭数として、上から順に判定します。

条件 (上から順に判定)ペース
n逃≥2n_\text{逃} \ge 2 または (n逃=1n_\text{逃} = 1 かつ n先≥5n_\text{先} \ge 5)ハイペース
n逃=0n_\text{逃} = 0 または (n逃=1n_\text{逃} = 1 かつ n先≤2n_\text{先} \le 2)スローペース
それ以外ミドルペース
return when {
    nigeCount >= 2 || (nigeCount == 1 && senkoCount >= 5) -> "ハイペース"
    nigeCount == 0 || (nigeCount == 1 && senkoCount <= 2) -> "スローペース"
    else -> "ミドルペース"
}

考え方は単純で、「前に行きたい馬が多いと先頭争いが激しくなり、ペースが上がる」というものです。有馬記念 (サンプル) は逃げ 1 頭 (タイトルホルダー)・先行 8 頭なので ハイペース です。

② 6 つの要素を 0〜100 の点数にする

スピード

スピード指数 SI\mathrm{SI} (60〜120 くらい) を 0〜100 に 線形変換 し、10〜98 に収めます。

xspd=clamp⁡ ⁣(SI−6060×100,  10,  98)x_\text{spd} = \operatorname{clamp}\!\left(\frac{\mathrm{SI} - 60}{60} \times 100,\; 10,\; 98\right)

clamp⁡(x,a,b)\operatorname{clamp}(x, a, b) は「xx が aa より小さければ aa、bb より大きければ bb、間ならそのまま」という関数です (クリップとも呼びます)。SI=60\mathrm{SI} = 60 で 0、SI=120\mathrm{SI} = 120 で 100 になる直線を、下を 10・上を 98 で切っています。

展開 (ペースと脚質の相性)

ペース \ 脚質逃げ先行差し追込
ハイ48659288
スロー95886245
ミドル75888670

ハイペースでは前の馬が疲れて後ろの馬が有利、スローでは逆、という競馬の定石を点数にした表です。

血統

基準 75 点に、父の名前で加点します。

父加点
キタサンブラック・ディープインパクト・ハーツクライ+15
エピファネイア・ドゥラメンテ・ロードカナロア+12
ゴールドシップ・オルフェーヴル馬場が良以外 +18、良 +8

騎手

騎手の勝率 ww (0〜1) を 400 倍して 40〜98 に収めます: xjky=clamp⁡(400w,40,98)x_\text{jky} = \operatorname{clamp}(400w, 40, 98)。勝率 0.178 なら 71.2 点、0.245 以上で上限の 98 点です。

馬場

良 85、稍重 82、重・不良は基準 80 に「馬体重 490kg 以上なら +10、未満なら −8」。重い馬場は力の強い大型馬が有利、という経験則です。

枠と調教 (直接足す補正)

  • 2000m 以上で 1〜3 枠なら +4、7〜8 枠なら −3 (内枠の方がコーナーで距離を損しにくい)
  • 調教評価 S +10、A+ +7、A +5、B 0、それ以外 −5

③ 加重平均 — 総合スコア

S=clamp⁡ ⁣(0.35 xspd+0.20 xpace+0.15 xped+0.15 xjky+0.10 xcond+b枠+b調教,  15,  99.5)S = \operatorname{clamp}\!\big(0.35\,x_\text{spd} + 0.20\,x_\text{pace} + 0.15\,x_\text{ped} + 0.15\,x_\text{jky} + 0.10\,x_\text{cond} + b_\text{枠} + b_\text{調教},\; 15,\; 99.5\big)

加重平均 とは「大事な要素ほど大きな重みを掛けて合計する」平均です。ここではスピードを最も重視し (35%)、馬場を最も軽く (10%) 見ています。

重みの合計が 1 になっていない

0.35+0.20+0.15+0.15+0.10=0.950.35 + 0.20 + 0.15 + 0.15 + 0.10 = 0.95 です。普通の加重平均は重みの合計を 1 にするので、厳密には「平均」ではなく「加重和」です。5 要素がすべて 100 点でも 95 点にしかならず、残りを枠と調教の補正 (最大 +14) で埋める作りになっています。結果として上限 99.5 に届く馬が複数出ます (有馬記念ではレガレイラ 99.5、ドウデュース 99.2)。

手計算で再現する — ドウデュース

ドウデュースはスピード指数 118.5、差し、父ハーツクライ、騎手勝率 0.178、馬体重 508kg、1 枠、調教 S、馬場は良 (公開時の天気)、ペースはハイです。

要素計算点数× 重み
スピード(118.5−60)/60×100(118.5 - 60)/60 \times 10097.534.125
展開ハイ × 差し9218.4
血統75 + 15 (ハーツクライ)9013.5
騎手400×0.178400 \times 0.17871.210.68
馬場良858.5
枠2500m・1 枠—+4
調教S—+10
合計99.205

アプリは小数第 1 位に丸めて 99.2 と表示します。実際の出力と一致します。

④ 「勝率」と「期待値」— どこで破綻しているか

画面の「勝率」の式

p^=clamp⁡ ⁣(S×2.8オッズ,  2,  68)  [%]\hat p = \operatorname{clamp}\!\left(S \times \frac{2.8}{\text{オッズ}},\; 2,\; 68\right) \;[\%]

1/オッズ1/\text{オッズ} は、後で説明するように「市場が見積もった勝つ確率」のおおよその値です。それにスコアと 2.8 を掛けたものを「勝率」と呼んでいます。

確率の条件を満たしていない

確率なら、全頭の勝率を足すとちょうど 100% になるはずです (誰か 1 頭は必ず勝つので)。ところが有馬記念 (サンプル) の 16 頭を足すと 375.1% になります。さらに、ドウデュースは 99.2×2.8/2.3≈120.8%99.2 \times 2.8 / 2.3 \approx 120.8\% という 100% を超える値になり、上限の 68% で切られています。この値は「確率」ではなく「人気と評価を混ぜた点数」と読むのが正しい解釈です。

本物の確率は モンテカルロ法 の方で、こちらはドウデュース 36.2%、16 頭の合計がちょうど 100% になります。

「期待値」がほぼ全頭 99 になる理由

馬券の 期待値 は「当たる確率 × 配当」です。単勝なら p×オッズp \times \text{オッズ} で、1 を超えれば「長い目で見て得」という意味になります。アプリの妙味指数は

EV=clamp⁡ ⁣(75×p^100×オッズ,  30,  99)\mathrm{EV} = \operatorname{clamp}\!\left(75 \times \frac{\hat p}{100} \times \text{オッズ},\; 30,\; 99\right)

ここに上の p^\hat p を代入すると (上下限で切られない範囲では)

p^100×オッズ=S×2.8100×オッズ×オッズ=0.028 S\frac{\hat p}{100} \times \text{オッズ} = \frac{S \times 2.8}{100 \times \text{オッズ}} \times \text{オッズ} = 0.028\,S

オッズが打ち消し合って消えてしまいます。EV=75×0.028 S=2.1 S\mathrm{EV} = 75 \times 0.028\,S = 2.1\,S なので、総合スコアが 99/2.1≈47.199/2.1 \approx 47.1 以上の馬はすべて上限の 99 になります。「勝率」をオッズから作っておいて、その勝率にオッズを掛けているので、循環してしまっているのです。

教訓: 確率と配当は別の情報源から

期待値でお得な馬券 (「妙味」) を見つけるには、勝つ確率を、オッズとは独立した方法で見積もる 必要があります。モンテカルロの勝率 pip_i を使えば pi×オッズip_i \times \text{オッズ}_i は意味のある期待値になります。具体的な直し方は 本物の予想へ で扱います。

⑤ 印 — スコア順に並べる

総合スコアの高い順に並べ、1 位 ◎、2 位 ◯、3 位 ▲、4・5 位 △ をつけます。☆ (穴) は、6 位以下で「妙味 75 以上かつオッズ 8 倍以上」の最初の馬、いなければ 6 位の馬です。上で見たように妙味はほぼ 99 なので、実質的には「6 位以下で、最初に出てくるオッズ 8 倍以上の馬」です。

⑥ 買い目と配分

券種組み合わせ想定オッズ配分
単勝◎◎ の単勝オッズ35%
馬連◎ − ◯max⁡ ⁣(4, o◎ o◯2.2)\max\!\left(4,\ \dfrac{o_◎\, o_◯}{2.2}\right)30%
3 連複◎ = ◯ = ▲ (+☆)24.5 (固定)25%
ワイド◎ − ☆max⁡(6.5, 1.8 o☆)\max(6.5,\ 1.8\, o_☆)10%

想定オッズの式は「2 頭の単勝オッズの積を割り引く」という大まかな近似です。2 頭の着順の確率から正しく計算する方法 (Harville の公式) は 本物の予想へ で紹介します。配分の 35/30/25/10 も固定値で、ケリー基準 のような理論に基づくものではありません。

まとめ
  • ペースは逃げ・先行の頭数で、6 要素の点数は表と 1 次式で決まる
  • 総合スコアは重み合計 0.95 の加重和 + 補正を 15〜99.5 で切ったもの
  • 画面の「勝率」は合計 375% になる「点数」で、確率ではない
  • 「勝率」をオッズから作っているので、期待値を計算するとオッズが消え、ほぼ全頭 99 になる
  • 本物の確率はモンテカルロ側にある。改善の方向は「確率をオッズと独立に作る」
練習問題レガレイラの 99.5 を再現する

レガレイラはスピード指数 116、差し、父スワーヴリチャード (加点なし)、騎手勝率 0.285、3 枠、調教 S、距離 2500m、馬場は良、ハイペースです。総合スコアを計算してください。

答えを見る

スピード (116−60)/60×100=93.33(116-60)/60 \times 100 = 93.33、展開 92、血統 75、騎手 min⁡(400×0.285,98)=98\min(400 \times 0.285, 98) = 98、馬場 85、枠 +4、調教 +10。 0.35×93.33+0.2×92+0.15×75+0.15×98+0.1×85+4+10=32.67+18.4+11.25+14.7+8.5+14=99.520.35 \times 93.33 + 0.2 \times 92 + 0.15 \times 75 + 0.15 \times 98 + 0.1 \times 85 + 4 + 10 = 32.67 + 18.4 + 11.25 + 14.7 + 8.5 + 14 = 99.52。上限 99.5 で切られて 99.5 (実際の出力と一致)。

練習問題期待値の循環を確かめる

総合スコア 40 の馬の妙味指数はいくつになりますか (勝率が上下限で切られないと仮定)。また、妙味指数が 99 未満になるのは総合スコアがいくつ未満のときですか。

答えを見る

2.1×40=842.1 \times 40 = 84。2.1 S<992.1\,S < 99 より S<47.14S < 47.14。オッズの値は結果に一切関係しません。