"""EV(期望值)運算模組。 本模組提供最基本、可復用的賠率價值判斷邏輯:給定真實勝率與小數賠率,計算期望值與是否為優勢投注。 """ from __future__ import annotations from typing import Any def calculate_expected_value( true_win_prob: float, decimal_odds: float, stake: float = 100.0, suggested_kelly_fraction: float | None = None, ) -> dict[str, Any]: """計算期望值(EV)並回傳報價建議。 Parameters ---------- true_win_prob: 模型估計的真實勝率,必須在 0 到 1 之間。 decimal_odds: 小數制賠率,必須大於 1(否則不具可投注意義)。 stake: 本次下注本金;同時也是 EV 百分比的基準。 suggested_kelly_fraction: 由外部凱利公式模組預留的建議資金比例;若未提供則回傳 None。 Returns ------- dict { 'ev_value': 實際 EV 金額, 'ev_percentage': EV / stake * 100, 'is_value_bet': 當 EV% 大於 3% 時為 True, 'suggested_kelly_fraction': 傳入值或 None } """ if not 0.0 <= true_win_prob <= 1.0: raise ValueError('true_win_prob 必須介於 0 到 1 之間') if decimal_odds <= 1: raise ValueError('decimal_odds 必須大於 1') if stake <= 0: raise ValueError('stake 必須大於 0') win_prob = float(true_win_prob) odds = float(decimal_odds) stake_amount = float(stake) profit_when_win = odds - 1.0 lose_prob = 1.0 - win_prob ev = win_prob * profit_when_win * stake_amount - lose_prob * stake_amount ev_percentage = ev / stake_amount * 100 return { 'ev_value': round(ev, 6), 'ev_percentage': round(ev_percentage, 4), 'is_value_bet': ev_percentage > 3.0, 'suggested_kelly_fraction': suggested_kelly_fraction, }