iT邦幫忙

0

用 pandas 檢查運動賠率是否「準」:從公開 CSV 做出校準表

  • 分享至 

  • xImage
  •  

賠率看起來像機率,但不是。十進位賠率 2.00 隱含 50%,可是一個市場裡所有結果的隱含機率加起來會超過 100%,多出來的部分就是莊家的抽水(margin)。要判斷賠率是不是好的預測,得先把抽水去掉,再拿去掉之後的機率和實際結果比。這篇用一個公開資料集(CC BY 4.0)示範整個流程,大約 20 行 pandas。

資料

資料集來自研究 Well Calibrated, Unevenly Priced:2024 年 11 月到 2026 年 7 月之間已結算的 18,238 個兩結果市場,每個市場兩邊各一列,共 36,476 筆。欄位只有五個:

欄位 意思
event_month 比賽月份
sport 運動項目
market_family 市場類型(勝負、讓分、大小分、球員)
market_implied_probability 去掉抽水後的隱含機率(比例法)
outcome 1 = 發生,0 = 沒發生

抽水的大小依市場類型不同。每日莊家抽水指數 量到的 2026 年 7–9 月平均值:兩結果勝負 4.85%、讓分 5.33%、大小分 5.97%、三結果(1X2)7.55%、球員市場 7.68%。量測方法見 方法說明。

步驟一:讀檔並分箱

import pandas as pd

df = pd.read_csv("betbetter_market_calibration.csv")
bins = [0, .1, .2, .3, .4, .5, .6, .7, .8, .9, 1.0]
df["band"] = pd.cut(df["market_implied_probability"], bins, right=False)

步驟二:每箱比較「平均隱含機率」和「實際發生率」

table = (df.groupby("band", observed=True)
           .agg(n=("outcome", "size"),
                implied=("market_implied_probability", "mean"),
                actual=("outcome", "mean")))
table["gap_pts"] = (table["actual"] - table["implied"]) * 100
print(table.round(3))

研究報告裡兩個端點箱的結果,可以拿來核對你跑出的數字:

箱 n 平均隱含 實際 差(百分點)
10–20% 2,144 17.5% 18.8% +1.4
80–90% 2,157 82.5% 80.9% −1.6

每一箱的差都在 2 個百分點以內:去掉抽水的賠率是相當好的預測。但差不是零,而且方向一致——低於 50% 的結果發生得比價格說的多一點,熱門發生得少一點。這就是文獻裡的「熱門—冷門偏誤」(Griffith 1949 起),在 2026 年的線上市場仍看得到。

步驟三:Brier 分數與信賴區間

import numpy as np
p, y = df["market_implied_probability"].values, df["outcome"].values
brier = np.mean((p - y) ** 2)

rng = np.random.default_rng(0)
boot = [np.mean((p[i] - y[i]) ** 2)
        for i in (rng.integers(0, len(p), len(p)) for _ in range(1000))]
print(round(brier, 4), np.percentile(boot, [2.5, 97.5]).round(4))

把同一段程式套到你自己的模型機率上,就能和市場比 Brier 分數。要拿到已經去掉抽水的模型機率,可以用 免 key 的免費 API,有 Python、R 等 13 種語言的用戶端。

常見的錯

  1. 沒先去抽水就比較。 隱含機率總和 105% 的市場,每一箱都會看起來「實際低於預期」。
  2. 箱太細。 一箱不到幾百筆時,差幾個百分點只是雜訊;每箱旁邊永遠印出 n。
  3. 只用比例法。 抽水不是平均分攤的;換成 Shin 或 power 方法再跑一次,看尾端的差會不會縮小。

本文為教學用途的統計說明,作者 Bet Better Pty Ltd(墨爾本)。不是投注建議。未滿 18 歲請勿投注。


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言