学ぶ ・ 予想のしくみ

能力値と適性 — 戦績を 1 つの数字にする

名鑑の 5,861 頭につける「能力値 (45〜99)」の作り方を説明します。平方根と対数を使う理由、順位 (パーセンタイル) への変換、そして 3D シミュレーションで使う「スピード」への換算まで。

このページで学ぶこと
  • 勝率・GI 勝利数・重賞勝利数・獲得賞金から「素点」を作る式
  • 勝率に平方根、賞金に対数を使う理由 (限界効用の考え方)
  • 素点を順位に変えてから 45〜99 に配る理由と、その計算
  • 「能力値 99 は何頭いるか」を式だけで当てる
  • 得意な馬場・距離の推定と、シミュレーション用のスピードへの換算

素点 — 4 つの実績を足す

名鑑の馬には、Wikipedia の記事から取った「通算成績 (N 戦 M 勝)」「勝ち鞍 (GI・GII・GIII)」「獲得賞金」があります。これらから 素点 RR を作ります。

private fun rawScore(h: HorseEntry): Double {
    val starts = h.starts ?: 0
    val winRate = if (starts > 0) (h.wins ?: 0).toDouble() / starts else 0.25
    val top = h.bigWins.count { it.grade.endsWith("I") && !it.grade.endsWith("II") }
    val graded = h.bigWins.size
    val money = h.earningsManYen?.let { min(log10(1.0 + it) * 3.0, 15.0) } ?: 6.0
    return 18 * sqrt(winRate) + min(top, 9) * 3.0 + min(graded, 15) * 0.6 + money
}
R=18w  +  3min⁡(g1,9)  +  0.6min⁡(g,15)  +  min⁡ ⁣(3log⁡10(1+E), 15)R = 18\sqrt{w} \;+\; 3\min(g_1, 9) \;+\; 0.6\min(g, 15) \;+\; \min\!\big(3\log_{10}(1 + E),\ 15\big)
記号意味不明なとき最大の寄与
ww勝率 = 勝ち数 / 出走数0.2518
g1g_1GI (JpnI) の勝利数027 (9 勝で頭打ち)
gg重賞 (GI〜GIII) の勝利数09 (15 勝で頭打ち)
EE獲得賞金 (万円)項全体を 615

grade.endsWith("I") && !grade.endsWith("II") は「GI または JpnI」だけを数えるための条件です ("GIII" や "GII" も "I" で終わるため、"II" で終わるものを除いています)。

例: オグリキャップ

32 戦 22 勝、データ上の GI 勝ち 3、重賞勝ち 10、獲得賞金 9 億 1251 万円 (91,251 万円)。

1822/32=18×0.8292=14.923×3=90.6×10=63log⁡10(91252)=3×4.960=14.88R=44.81\begin{aligned} 18\sqrt{22/32} &= 18 \times 0.8292 = 14.92 \\ 3 \times 3 &= 9 \\ 0.6 \times 10 &= 6 \\ 3\log_{10}(91252) &= 3 \times 4.960 = 14.88 \\ R &= 44.81 \end{aligned}

なぜ平方根と対数なのか — 限界効用

勝率に平方根

w\sqrt{w} のグラフは、最初は急で、だんだん緩やかになる曲線です (凹関数)。傾き (微分) は

ddw 18w=9w\frac{d}{dw}\,18\sqrt{w} = \frac{9}{\sqrt{w}}

で、ww が小さいほど大きくなります。

勝率の変化素点の増え方
0.1 → 0.218(0.2−0.1)=2.3618(\sqrt{0.2} - \sqrt{0.1}) = 2.36
0.8 → 0.918(0.9−0.8)=0.9718(\sqrt{0.9} - \sqrt{0.8}) = 0.97

「ほとんど勝てない馬」と「たまに勝つ馬」の差は大きいが、「よく勝つ馬」と「とてもよく勝つ馬」の差はそれほどでもない、という感覚を表しています。経済学で「限界効用の逓減」と呼ぶ考え方と同じです。

賞金に対数

賞金は 100 万円の馬から 20 億円の馬まで、桁が 4 つ以上違います。そのまま足すと賞金の大きい馬だけで点数が決まってしまうので、log⁡10\log_{10} (10 を何乗すればその数になるか) で「桁数」に直します。

獲得賞金3log⁡10(1+E)3\log_{10}(1 + E)
100 万円 (E=100E = 100)6.0
1,000 万円9.0
1 億円12.0
10 億円15.0 (上限)

賞金が 10 倍になると +3 点。1+E1 + E としているのは、賞金 0 のとき log⁡0\log 0 (マイナス無限大) にならないようにするためです。人間の感覚が刺激の「比」に反応する、という Weber–Fechner の法則とも似た発想です。

上限 (min) を設ける理由

GI 9 勝、重賞 15 勝、賞金 10 億円で頭打ちにしているのは、極端な 1 頭が他の要素を無視して抜け出すのを防ぐためです。外れ値の影響を抑えるこの操作を、統計では ウィンソライズ (winsorize) と呼びます。

素点 → 順位 → 能力値

素点は 5〜50 くらいの、分布の偏った数です。そのまま見せると「上位の名馬がみな同じような点」になり、差が分かりません。そこで 全頭の中の順位 に変換してから、45〜99 に配ります。

val raw = list.map { rawScore(it.horse) }
val order = raw.indices.sortedBy { raw[it] }
order.forEachIndexed { rank, i ->
    val p = if (list.size == 1) 1.0 else rank.toDouble() / (list.size - 1)
    rating[i] = (45 + 54 * p * p).roundToInt()
}

素点の小さい順に 0, 1, …, N−1N-1 と順位 rr をつけ、

p=rN−1∈[0,1],能力値=round⁡ ⁣(45+54 p2)p = \frac{r}{N - 1} \in [0, 1], \qquad \text{能力値} = \operatorname{round}\!\left(45 + 54\,p^2\right)

pp は「自分より下に何割の馬がいるか」(パーセンタイル) です。最下位で p=0p = 0 → 45、最上位で p=1p = 1 → 99 になります。

なぜ p2p^2 なのか

45+54p45 + 54p (直線) でも 45〜99 になります。2 乗にすると傾きが 108p108p になり、上位ほど 1 段階の差が大きく 表示されます。名鑑を見る人が気にするのは「上位の名馬どうしの差」なので、上の方の解像度を上げているわけです。

能力値 99 は何頭いるか — 式だけで予言する

四捨五入で 99 になるのは 45+54p2≥98.545 + 54p^2 \ge 98.5 のときです。

p2≥53.554  ⟹  p≥0.99536p^2 \ge \frac{53.5}{54} \;\Longrightarrow\; p \ge 0.99536

上位 1−0.99536=0.464%1 - 0.99536 = 0.464\% です。名鑑は N=5861N = 5861 頭なので、r≥0.99536×5860=5832.8r \ge 0.99536 \times 5860 = 5832.8、つまり r=5833r = 5833〜58605860 の 28 頭。実際のデータを数えると 28 頭で、一致します。

同じように中央の馬 (p=0.5p = 0.5) は 45+54×0.25=58.5→5945 + 54 \times 0.25 = 58.5 \to 59 で、実データの中央値も 59 です。

さらに深く能力値の分布

pp は 0〜1 にほぼ一様に散らばるので、「能力値が xx 以下の馬の割合」は

F(x)=P(45+54p2≤x)=P ⁣(p≤x−4554)=x−4554F(x) = P(45 + 54p^2 \le x) = P\!\left(p \le \sqrt{\tfrac{x - 45}{54}}\right) = \sqrt{\frac{x - 45}{54}}

です。たとえば能力値 70 以下は 25/54≈68%\sqrt{25/54} \approx 68\%。半分以上の馬が 60 未満に集まり、上に行くほど少なくなる、「上位が細長い」分布になります。

能力値は「強さ」ではなく「記事に書かれた実績の順位」

Wikipedia に記事がある時点で、その馬はかなり活躍した馬です。能力値 45 は「弱い馬」ではなく「記事のある 5,861 頭の中で実績が最も少ない馬」です。また、海外の馬は賞金が円ではないので賞金点が仮の 6 になり、時代による賞金水準の違いも考慮していません。

得意な馬場と距離の推定

その馬が勝った重賞を、競走一覧のデータ (馬場・距離) と名前で突き合わせます。

  • 勝った重賞に芝が含まれれば「芝」、ダートが含まれれば「ダート」、両方なら「芝・ダート」、記事のある重賞を勝っていなければ「不明」
  • 得意距離 = 勝った重賞の距離の 平均 (オグリキャップは 1,980m)

平均を使うので、マイル (1,600m) と長距離 (2,500m) の両方を勝った馬は 2,000m 前後が「得意」と表示される、という限界があります。

シミュレーション用の「スピード」への換算

3D シミュレーションでは、能力値を モンテカルロ の SI\mathrm{SI} (スピード指数) に換算して Zig に渡します。

function effectiveSpeed(f, distance, surface) {
  if (f.speed) return f.speed;
  let s = 70 + f.rating * 0.5;
  if (f.surface && f.surface !== "不明" && !f.surface.includes(surface)) s -= 4;
  if (f.bestDistance) s -= Math.min(6, Math.abs(distance - f.bestDistance) / 250);
  return s;
}
SI=70+0.5×能力値  −  4⋅[馬場が不得意]  −  min⁡ ⁣(6, ∣D−D∗∣250)\mathrm{SI} = 70 + 0.5 \times \text{能力値} \;-\; 4 \cdot [\text{馬場が不得意}] \;-\; \min\!\left(6,\ \frac{|D - D^*|}{250}\right)
  • 能力値 45〜99 → SI\mathrm{SI} 92.5〜119.5。サンプル出馬表のスピード指数 (101〜118) とだいたい同じ範囲になるように選んだ 1 次式です
  • [ ⋅ ][\,\cdot\,] は「条件が成り立てば 1、そうでなければ 0」(アイバーソンの記法)
  • D∗D^* は得意距離。250m 離れるごとに −1、最大 −6

能力値 10 の差 = SI 5 の差 で、モンテカルロ の揺らぎの標準偏差 0.0635 は SI に直すと約 6.35 なので、「能力値 13 くらいの差が、揺らぎ 1 つ分」という感覚です。

まとめ
  • 素点 = 18w+3min⁡(g1,9)+0.6min⁡(g,15)+min⁡(3log⁡10(1+E),15)18\sqrt{w} + 3\min(g_1,9) + 0.6\min(g,15) + \min(3\log_{10}(1+E), 15)
  • 平方根と対数は「増えるほど 1 単位の価値が下がる」(限界効用の逓減) を表す
  • 素点を順位 pp に直し、45+54p245 + 54p^2 で 45〜99 に配る。上位ほど差が大きく見える
  • 99 になるのは上位 0.464% で、5,861 頭中 28 頭 (実データと一致)
  • 3D では SI=70+0.5×\mathrm{SI} = 70 + 0.5 \times 能力値 − 適性の減点 で Zig に渡す
練習問題素点を計算する

20 戦 8 勝、GI 1 勝、重賞 4 勝、獲得賞金 3 億円の馬の素点を求めてください (log⁡1030001≈4.477\log_{10} 30001 \approx 4.477)。

答えを見る

180.4=11.3818\sqrt{0.4} = 11.38、3×1=33 \times 1 = 3、0.6×4=2.40.6 \times 4 = 2.4、3×4.477=13.433 \times 4.477 = 13.43。合計 R≈30.2R \approx 30.2。

練習問題能力値 80 以上は何%

すべての馬の pp が一様に散らばっているとして、能力値 (四捨五入) が 80 以上になるのは全体の何% ですか。

答えを見る

45+54p2≥79.545 + 54p^2 \ge 79.5 より p≥34.5/54=0.7993p \ge \sqrt{34.5/54} = 0.7993。上位 約 20.1% です。

練習問題距離の減点

得意距離 1,600m、能力値 90 の芝馬が、芝 2,400m を走るときの SI はいくつですか。

答えを見る

70+45=11570 + 45 = 115。距離の減点は min⁡(6,800/250)=3.2\min(6, 800/250) = 3.2。馬場は得意なので減点なし。SI=111.8\mathrm{SI} = 111.8。