""" Confidence-Based Prediction Sections Categorizes predictions by confidence level: - Sure Win: 91%+ confidence (ultra-high probability picks) - Strong Picks: 80-90% confidence (reliable selections) - Value Hunters: 5%+ edge vs bookmaker odds - Upset Watch: Underdog potential picks - Daily Banker: Single safest pick of the day """ from dataclasses import dataclass, asdict from typing import Dict, List, Optional, Tuple from datetime import datetime import json @dataclass class SectionConfig: """Configuration for a confidence section""" name: str description: str icon: str color: str min_confidence: Optional[float] = None max_confidence: Optional[float] = None min_edge: Optional[float] = None max_picks: Optional[int] = None class ConfidenceSectionsManager: """ Categorize predictions into confidence-based sections. Sections: - Sure Win: 91%+ confidence picks (very rare, very reliable) - Strong Picks: 80-90% confidence (solid selections) - Value Hunters: Good edge vs market odds (5%+ value) - Upset Watch: Underdog potential (25%+ probability) - Daily Banker: Single highest confidence pick """ SECTIONS = { 'sure_win': SectionConfig( name='🔒 Sure Win', description='Ultra-high confidence picks (91%+ probability)', icon='🔒', color='#10B981', # Emerald green min_confidence=0.91 ), 'strong_picks': SectionConfig( name='💪 Strong Picks', description='High confidence selections (80-90%)', icon='💪', color='#3B82F6', # Blue min_confidence=0.80, max_confidence=0.90 ), 'value_hunters': SectionConfig( name='💎 Value Hunters', description='Great edge vs bookmaker odds (5%+ value)', icon='💎', color='#8B5CF6', # Purple min_edge=0.05 ), 'upset_watch': SectionConfig( name='⚡ Upset Watch', description='Potential upsets worth watching', icon='⚡', color='#F59E0B', # Amber ), 'daily_banker': SectionConfig( name='🎯 Daily Banker', description='Single safest pick of the day', icon='🎯', color='#EF4444', # Red max_picks=1 ), 'risky_rewards': SectionConfig( name='🎲 Risky Rewards', description='Long shots with high potential returns', icon='🎲', color='#EC4899', # Pink min_confidence=0.30, max_confidence=0.50 ) } def __init__(self): self.prediction_history = [] def categorize(self, predictions: List[Dict]) -> Dict[str, List[Dict]]: """ Sort predictions into confidence-based sections. Args: predictions: List of prediction dicts with 'confidence', 'value_edge', etc. Returns: Dict mapping section name to list of predictions """ sections = {key: [] for key in self.SECTIONS} if not predictions: return sections for pred in predictions: confidence = pred.get('confidence', 0) if isinstance(confidence, str): confidence = float(confidence.replace('%', '')) / 100 elif confidence > 1: confidence = confidence / 100 edge = pred.get('value_edge', 0) or 0 # Determine predicted outcome probabilities home_prob = pred.get('home_win_prob', 0) or 0 draw_prob = pred.get('draw_prob', 0) or 0 away_prob = pred.get('away_win_prob', 0) or 0 # Normalize if needed if home_prob > 1: home_prob /= 100 if draw_prob > 1: draw_prob /= 100 if away_prob > 1: away_prob /= 100 max_prob = max(home_prob, draw_prob, away_prob) # Sure Win: 91%+ confidence if confidence >= 0.91 or max_prob >= 0.91: sections['sure_win'].append(self._enrich_prediction(pred, 'sure_win')) # Strong Picks: 80-90% elif confidence >= 0.80 or max_prob >= 0.80: sections['strong_picks'].append(self._enrich_prediction(pred, 'strong_picks')) # Value Hunters: 5%+ edge if edge >= 0.05: sections['value_hunters'].append(self._enrich_prediction(pred, 'value_hunters')) # Upset Watch: Underdog with reasonable probability is_upset = self._is_upset_potential(pred) if is_upset: sections['upset_watch'].append(self._enrich_prediction(pred, 'upset_watch')) # Risky Rewards: 30-50% confidence but good odds if 0.30 <= confidence <= 0.50: sections['risky_rewards'].append(self._enrich_prediction(pred, 'risky_rewards')) # Daily Banker: Highest confidence pick if predictions: best = max(predictions, key=lambda x: self._get_confidence(x)) sections['daily_banker'] = [self._enrich_prediction(best, 'daily_banker')] # Sort each section by confidence descending for section_name in sections: if section_name != 'daily_banker': sections[section_name].sort( key=lambda x: self._get_confidence(x), reverse=True ) return sections def _get_confidence(self, pred: Dict) -> float: """Extract normalized confidence from prediction""" confidence = pred.get('confidence', 0) if isinstance(confidence, str): confidence = float(confidence.replace('%', '')) / 100 elif confidence > 1: confidence = confidence / 100 return confidence def _is_upset_potential(self, pred: Dict) -> bool: """ Check if this is a potential upset. Criteria: - Lower-ranked team has 25%+ win probability - OR home team expected to lose but has 30%+ probability """ home_prob = pred.get('home_win_prob', 0) or 0 away_prob = pred.get('away_win_prob', 0) or 0 if home_prob > 1: home_prob /= 100 if away_prob > 1: away_prob /= 100 # Check ELO difference if available home_elo = pred.get('home_elo', 1500) away_elo = pred.get('away_elo', 1500) # Underdog is team with lower ELO if home_elo < away_elo and home_prob >= 0.25: return True elif away_elo < home_elo and away_prob >= 0.25: return True # Also check if predicted outcome differs from ELO expectation predicted = pred.get('predicted_outcome', '') if home_elo > away_elo + 50 and predicted == 'Away': return True elif away_elo > home_elo + 50 and predicted == 'Home': return True return False def _enrich_prediction(self, pred: Dict, section: str) -> Dict: """Add section metadata to prediction""" enriched = pred.copy() enriched['section'] = section enriched['section_config'] = asdict(self.SECTIONS[section]) return enriched def get_sure_wins(self, predictions: List[Dict]) -> List[Dict]: """Get only Sure Win picks (91%+ confidence)""" return self.categorize(predictions)['sure_win'] def get_strong_picks(self, predictions: List[Dict]) -> List[Dict]: """Get Strong Picks (80-90% confidence)""" return self.categorize(predictions)['strong_picks'] def get_value_bets(self, predictions: List[Dict]) -> List[Dict]: """Get Value Hunter picks (5%+ edge)""" return self.categorize(predictions)['value_hunters'] def get_daily_banker(self, predictions: List[Dict]) -> Optional[Dict]: """Get the single Daily Banker pick""" bankers = self.categorize(predictions)['daily_banker'] return bankers[0] if bankers else None def get_section_stats(self, predictions: List[Dict]) -> Dict: """Get statistics about each section""" sections = self.categorize(predictions) stats = {} for section_name, preds in sections.items(): if preds: confidences = [self._get_confidence(p) for p in preds] stats[section_name] = { 'count': len(preds), 'avg_confidence': round(sum(confidences) / len(confidences) * 100, 1), 'min_confidence': round(min(confidences) * 100, 1), 'max_confidence': round(max(confidences) * 100, 1), 'config': asdict(self.SECTIONS[section_name]) } else: stats[section_name] = { 'count': 0, 'avg_confidence': 0, 'min_confidence': 0, 'max_confidence': 0, 'config': asdict(self.SECTIONS[section_name]) } return stats def get_all_sections_config(self) -> Dict: """Get configuration for all sections""" return { name: asdict(config) for name, config in self.SECTIONS.items() } # Global instance confidence_manager = ConfidenceSectionsManager() def get_confidence_sections(predictions: List[Dict]) -> Dict[str, List[Dict]]: """Get predictions organized by confidence sections""" return confidence_manager.categorize(predictions) def get_sure_wins(predictions: List[Dict]) -> List[Dict]: """Get 91%+ confidence predictions""" return confidence_manager.get_sure_wins(predictions) def get_daily_banker(predictions: List[Dict]) -> Optional[Dict]: """Get single safest pick""" return confidence_manager.get_daily_banker(predictions)