"""裁判尺度分析器。""" from __future__ import annotations from typing import Dict from .ev_calculator import calculate_expected_value def calculate_cards_ev( referee_stats: dict, match_tension_index: float, bookmaker_card_line: float, bookmaker_odds: float, ) -> dict[str, float | bool | str]: """判斷裁判/對手張力對紅黃牌盤口的偏差與價值。 依據裁判最近場次平均黃牌數與比賽張力(衝突度)估算 本場真實牌數,並與莊家 O/U 盤口比較。 """ if bookmaker_odds <= 1: raise ValueError('bookmaker_odds 必須大於 1') if bookmaker_card_line <= 0: raise ValueError('bookmaker_card_line 必須大於 0') if not 0 <= match_tension_index <= 1: raise ValueError('match_tension_index 必須在 0~1') avg_cards = float(referee_stats.get('avg_yellow_cards', 0.0) or 0.0) penalties_per_game = float(referee_stats.get('penalties_per_game', 0.0) or 0.0) strictness_index = 20.0 + avg_cards * 1.9 + penalties_per_game * 2.5 # 綜合壓力補正,將裁判嚴厲度與球隊/賽事張力轉為預測牌數。 expected_cards = max( 0.5, strictness_index * (0.45 + 0.55 * max(0.0, min(match_tension_index, 1.0))), ) true_prob = min(1.0, max(0.0, expected_cards / (bookmaker_card_line * 1.4))) implied_prob = 1.0 / bookmaker_odds edge = true_prob - implied_prob ev = calculate_expected_value(true_prob, bookmaker_odds, stake=100.0) return { 'strictness_index': round(strictness_index, 3), 'expected_total_cards': round(expected_cards, 3), 'true_prob': round(true_prob, 4), 'implied_prob': round(implied_prob, 4), 'edge_percent': round(edge * 100, 3), 'is_value_bet': ev['is_value_bet'], 'ev_percentage': ev['ev_percentage'], }