本站不接受娛樂城的任何形式贊助、分潤或廣告。 我們的收入與你是否下注、是否輸錢完全無關。
查看完整金流揭露 →
機率所
ODDSLAB
資料更新中
演算法公開

方法論

完整公開。你可以拿去驗證,也可以拿去證明我們錯了。

回測做到哪裡 →
俯視一本攤開的筆記本,上面整齊擺著一支短鉛筆和一把木尺
以下內容為技術文件,維持嚴肅精確,不做簡化。

先講最重要的:我們不預測單局結果。 這類遊戲使用 RNG,每一局在統計上獨立於前一局。 「累積了很多局沒開就快出分了」是賭徒謬誤, 任何以此為基礎的「蓄力係數」「爆分預測」在數學上都沒有依據。

我們唯一嘗試回答的問題是:不同機台之間,是否存在可被觀測證實的設定差異?

1. 資料來源與取樣

以下描述的是設計,不是正在執行的系統。 我們目前沒有在跑的生產環境取樣管線,也沒有累積中的真實快照。 這一節寫的是資料到齊之後會怎麼做,先寫下來是為了讓它日後可以被檢驗。

規劃中的作法是以固定間隔輪詢各遊戲的公開大廳資料,記錄每台機的累計下注量與 累計派彩量;預定取樣間隔 180 秒,原始快照全部保存以便回溯重算。

已知限制:我們觀測到的是聚合量而非逐局結果, 因此轉數需由下注量推估,這個推估本身帶有誤差。誤差來源與量級見第 4 節。

2. 區間估計:Wilson score interval

我們給的不是一個點,是一個區間。實際出貨的實作是 Wilson score intervalassets/hitrate.jswilson()),用在免遊觸發率上:

p_hat  = hits / spins
centre = (p_hat + z²/2n) / (1 + z²/n)
half   = z/(1 + z²/n) · √( p_hat(1-p_hat)/n + z²/4n² )
CI_95  = [centre - half, centre + half]      # z = 1.95996

# 再換算成玩家看得懂的單位:平均幾轉觸發一次
oneIn = 1 / p_hat

為什麼是 Wilson。免遊觸發是伯努利事件,而觸發率是小機率(約 0.4%–1%)。 在這個區間,常態近似 p̂ ± z√(p̂(1-p̂)/n) 會給出負數的下界, 覆蓋率也顯著低於名目的 95%。Wilson 是把區間解成二次式得到的,下界恆 ≥ 0、上界恆 ≤ 1, 小樣本下的實際覆蓋率也接近名目值。它是閉式解,不需要重抽樣, 每次頁面載入都能即時重算——對一個要你自己驗證的站來說,這比 bootstrap 實際。

樣本充足度:看區間寬度,不看轉數

判準不是「跑滿幾轉」,而是區間相對於點估計有多寬。 這是大廳、今日、遊戲各頁實際呼叫的 rateTier(), 頁面上「樣本充足/不足」的徽章就是它回傳的:

rel = (oneInHi - oneInLo) / (2 · oneIn)

rel <= 0.25            →  樣本充足(可下結論)
rel <= 0.50            →  樣本不足(顯示,但不做推論)
其餘,或 hits < 5       →  嚴重不足(不予評分)

用相對寬度而不是固定轉數門檻,是因為越稀有的觸發需要越多轉才能達到同樣精度。 在「約 180 轉一次」的觸發率下,±25% 大約需要 2 萬轉;觸發率降到 400 轉一次, 需要的轉數就更多。spinsNeeded(p, rel) 會把這個數算給你。 同一個固定門檻套在所有機台上,對稀有觸發是太鬆,對常見觸發是太嚴。

為什麼 RTP 沒有樣本充足門檻

因為它達不到。單局派彩是重尾分布——絕大多數是 0,偶爾一次大額——變異係數約 6.5, 標準誤下降得非常慢。依我們自己的引擎,要確認 5 個百分點的 RTP 變更,每側約需 60 萬轉, 遠超過絕大多數機台的累積量。所以我們算 RTP 點估計、也顯示它, 但不用 RTP 去下「這台比較好」的結論。 觸發頻率是這個資料集裡唯一能在合理樣本內收斂的量,判準就建立在它上面。

這一節先前寫的是「bootstrap 重抽樣(B=10000, BCa)」與「n ≥ 30,000 轉為充足」。 兩者都不是實際出貨的東西:站上沒有任何 bootstrap 實作,門檻也不是轉數。 已依實際程式碼改寫。

3. 差異檢定與多重比較校正

檢定每台機是否偏離全體分布。因為同時檢定數千台, 必須校正多重比較,否則光靠運氣就會產生大量「顯著」結果。 實作是 extension/lib/stats.jsbenjaminiHochberg()

p_i      = two_sided_test(rate_i, pooled)
p_adj    = benjamini_hochberg(p_all, alpha=0.05)
verdict  = "顯著" if p_adj < 0.05 else "無顯著差異"

這一步是我們與市面上選台站最大的技術差異,而且是純算術: 在 α = 0.05 之下不做校正,光靠隨機就會有大約 5% 的機台被標成「顯著」。 幾千台的大廳,那就是上百台。 你不需要任何真實的設定差異,也永遠能生出一份「今日前五名」—— 那正是那類推薦的來源。

4. 設定變更偵測

這是我們認為唯一有統計基礎、又對玩家真正有意義的訊號。 它回答的是「這台的產出分布在某個時間點發生了結構性改變嗎」, 不是「下一局會不會開」。這是兩個完全不同的問題。 實作是 extension/lib/stats.jsdetectChangepoint()

# 1. 把累計快照轉成每段增量
#    負增量或歸零 = 維護斷點,整段丟棄
# 2. binary segmentation:掃過每個候選切點,算前後兩段的 RTP
# 3. 兩樣本 z 檢定,取 |z| 最大的切點為候選變更點
# 4. 校正「掃描」本身:p_adj = p_raw × 候選切點數(Bonferroni)
# 5. confirmed = p_adj < alpha

minSpinsPerSide = 6000   # 兩側各自的最低轉數,不足則不回傳
alpha           = 0.01

第 1 步不是細節,是這支函式最容易出錯的地方。 伺服器維護或計數器重置會讓累計值產生負增量或歸零。 若不丟棄這種段落,缺口本身就會被讀成「RTP 在這個時點突然改變」, 而且因為缺口通常很大,它幾乎必然成為 |z| 最大的候選切點—— 也就是說,偵測器會穩定地把維護時間報成設定變更。 所以丟棄斷點段落是這支函式做的第一件事。

第 4 步是同類工具通常沒做的。掃 N 個候選切點等於做了 N 次檢定。 不校正的話,只要序列夠長,任何一條純隨機的序列都能「偵測到」變更點。

它很少回傳東西,這是正常的。minSpinsPerSide = 6000 只是「能不能跑」的下限,不是「能不能確認」的門檻——如第 2 節所述, 要確認 5 個百分點的 RTP 變更每側約需 60 萬轉。 所以在絕大多數機台上,這支函式的正確答案就是「沒有偵測到」。 一個天天都在報設定變更的偵測器,報的是雜訊。

5. 已知誤差來源

  • 轉數推估誤差:由下注量反推轉數需假設每局注額,注額變動會造成偏差。目前估計 ±3–7%。
  • 取樣斷點:伺服器維護造成的資料缺口是設定變更偵測最主要的偽陽性來源。目前的處理方式見第 4 節第 1 步,仍非完美——它只丟得掉「留下痕跡」的缺口。
  • 倖存者偏差:被下架或重編號的機台會從資料中消失,可能使整體平均偏高。
  • 非隨機曝光:熱門機台樣本累積快,冷門機台永遠達不到門檻。這是結構性限制,無法完全修正。

6. 回測:我們做到哪裡

前瞻回測——把當時的結論凍結,之後回頭看實際表現——是唯一能證明一套方法有沒有預測力的做法。 我們也認為,公布失準的期間比公布漂亮的期間更有價值。

但我們目前只完成過一次前瞻回測,而且驗的不是我們自己的結論。 我們沒有逐月的命中率紀錄可以公布,這一頁在做出來之前也不會放數字。 等到有,會連同失準的期間一起放在這裡。

已完成的那一次,驗的是競品的公式。我們依對方公開教學頁的說明復現「爆分潛力值」, 放到 500 萬轉、每局觸發機率固定 1/128(約 0.78%)的獨立序列上, 把每一轉按「當下已經幾轉沒開」分組,比對各組未來的實際觸發率。 結果:各組之間沒有差別,與一組完全無關資料的隨機分數也沒有差別,全都等於基準線。 那個分數對未來沒有預測力。完整方法、資料與圖表見 爆分潛力值準嗎?我們復現公式跑了 500 萬轉來驗

要對我們自己的設定變更偵測做同等級的驗證,需要的是同一批機台的長期真實序列, 而不是模擬序列。這件事還沒做完。在做完之前, 任何「我們的偵測有多準」的說法都沒有證據支撐,包括從我們嘴裡說出來的。

而且要先講清楚:就算哪天這裡出現漂亮的命中率,也不代表你玩了會贏。 「這台設定較好」與「你這一趟會賺錢」是兩件事。 前者是統計推論,後者受期望值支配——而期望值是負的。

7. 原始碼

統計的部分沒有藏起來,全部是站上直接載入的檔案,你可以在瀏覽器裡打開來看, 也可以自己重算頁面上的每一個數字。我們希望有人拿它來反駁我們。

  • assets/hitrate.js — 觸發頻率估計。Wilson 區間、 樣本充足度判定(rateTier)、所需樣本量(spinsNeeded)、 兩樣本 z 檢定(compareRates)與對全體比較(vsPool)。 測試在 tools/hitrate_test.html,共 25 項斷言, 其中一項專門檢查沒有匯出任何預測/連莊評分函式。
  • assets/rating.js — 娛樂城與遊戲評分。資料不足回 null 而不是編一個數字;用 Wilson 下界懲罰小樣本; 總評取最弱的關鍵維度而非平均。測試在 tools/rating_test.html, 共 29 項斷言,其中一項專門檢查沒有匯出任何聯盟/分潤相關函式。
  • assets/rivalscore.js — 競品「爆分潛力值」公式的復現, 以及一組與資料無關的隨機分數對照組。這是依對方公開說明重建的近似,不是他們的原始碼, 權重是我們推估的。目前尚無對應的測試檔。
  • extension/lib/stats.js — 設定變更偵測 (detectChangepoint)與 Benjamini–Hochberg 校正,見第 3、4 節。

這一節先前列出 oddslab/estimatoroddslab/changepointoddslab/backtest 三個「MIT 授權 repo」。那三個 repo 不存在,我們也還沒發過授權聲明。 已改列實際出貨的檔案。