""" Advanced Analytics Dashboard Backend Provides: - Detailed accuracy tracking - ROI calculations - League performance analysis - Betting patterns - Trend analysis """ import json from datetime import datetime, timedelta from typing import Dict, List, Optional, Tuple from dataclasses import dataclass, asdict from collections import defaultdict import statistics @dataclass class PredictionRecord: """Single prediction record""" id: str home: str away: str league: str predicted_outcome: str actual_outcome: Optional[str] confidence: float odds: float stake: float status: str # pending, won, lost created_at: str settled_at: Optional[str] = None def profit_loss(self) -> float: if self.status == 'won': return self.stake * (self.odds - 1) elif self.status == 'lost': return -self.stake return 0.0 class AdvancedAnalytics: """Advanced analytics engine""" def __init__(self): self.predictions: List[PredictionRecord] = [] self.daily_stats: Dict[str, Dict] = {} self.league_stats: Dict[str, Dict] = defaultdict(lambda: { 'total': 0, 'correct': 0, 'profit': 0.0 }) def add_prediction(self, record: PredictionRecord): """Add a prediction record""" self.predictions.append(record) self._update_stats(record) def _update_stats(self, record: PredictionRecord): """Update statistics for a prediction""" date_key = record.created_at[:10] if date_key not in self.daily_stats: self.daily_stats[date_key] = { 'total': 0, 'correct': 0, 'profit': 0.0, 'stakes': 0.0, 'high_conf': 0, 'high_conf_correct': 0 } stats = self.daily_stats[date_key] stats['total'] += 1 stats['stakes'] += record.stake if record.confidence >= 0.8: stats['high_conf'] += 1 if record.status == 'won': stats['correct'] += 1 stats['profit'] += record.profit_loss() if record.confidence >= 0.8: stats['high_conf_correct'] += 1 elif record.status == 'lost': stats['profit'] += record.profit_loss() # League stats league_stat = self.league_stats[record.league] league_stat['total'] += 1 if record.status == 'won': league_stat['correct'] += 1 league_stat['profit'] += record.profit_loss() def get_overall_accuracy(self) -> float: """Get overall prediction accuracy""" settled = [p for p in self.predictions if p.status in ['won', 'lost']] if not settled: return 0.0 correct = len([p for p in settled if p.status == 'won']) return correct / len(settled) * 100 def get_roi(self, period_days: int = 30) -> float: """Calculate ROI for a period""" cutoff = datetime.now() - timedelta(days=period_days) cutoff_str = cutoff.strftime('%Y-%m-%d') total_stakes = 0.0 total_profit = 0.0 for record in self.predictions: if record.created_at >= cutoff_str and record.status != 'pending': total_stakes += record.stake total_profit += record.profit_loss() if total_stakes == 0: return 0.0 return (total_profit / total_stakes) * 100 def get_league_performance(self) -> List[Dict]: """Get performance breakdown by league""" result = [] for league, stats in self.league_stats.items(): if stats['total'] > 0: accuracy = (stats['correct'] / stats['total']) * 100 result.append({ 'league': league, 'total': stats['total'], 'correct': stats['correct'], 'accuracy': round(accuracy, 1), 'profit': round(stats['profit'], 2) }) return sorted(result, key=lambda x: x['accuracy'], reverse=True) def get_confidence_analysis(self) -> Dict: """Analyze accuracy by confidence bands""" bands = { '90-100%': {'total': 0, 'correct': 0}, '80-90%': {'total': 0, 'correct': 0}, '70-80%': {'total': 0, 'correct': 0}, '60-70%': {'total': 0, 'correct': 0}, '50-60%': {'total': 0, 'correct': 0}, } for pred in self.predictions: if pred.status == 'pending': continue conf = pred.confidence * 100 if conf >= 90: band = '90-100%' elif conf >= 80: band = '80-90%' elif conf >= 70: band = '70-80%' elif conf >= 60: band = '60-70%' else: band = '50-60%' bands[band]['total'] += 1 if pred.status == 'won': bands[band]['correct'] += 1 result = {} for band, stats in bands.items(): if stats['total'] > 0: result[band] = { 'total': stats['total'], 'correct': stats['correct'], 'accuracy': round(stats['correct'] / stats['total'] * 100, 1) } else: result[band] = {'total': 0, 'correct': 0, 'accuracy': 0} return result def get_outcome_analysis(self) -> Dict: """Analyze accuracy by predicted outcome""" outcomes = defaultdict(lambda: {'total': 0, 'correct': 0}) for pred in self.predictions: if pred.status == 'pending': continue outcomes[pred.predicted_outcome]['total'] += 1 if pred.status == 'won': outcomes[pred.predicted_outcome]['correct'] += 1 result = {} for outcome, stats in outcomes.items(): if stats['total'] > 0: result[outcome] = { 'total': stats['total'], 'correct': stats['correct'], 'accuracy': round(stats['correct'] / stats['total'] * 100, 1) } return result def get_trend_analysis(self, days: int = 30) -> List[Dict]: """Get daily accuracy trend""" cutoff = datetime.now() - timedelta(days=days) cutoff_str = cutoff.strftime('%Y-%m-%d') trend = [] for date, stats in sorted(self.daily_stats.items()): if date >= cutoff_str: if stats['total'] > 0: accuracy = stats['correct'] / stats['total'] * 100 else: accuracy = 0 trend.append({ 'date': date, 'accuracy': round(accuracy, 1), 'total': stats['total'], 'correct': stats['correct'], 'profit': round(stats['profit'], 2) }) return trend def get_streak_info(self) -> Dict: """Get winning/losing streak information""" settled = [p for p in self.predictions if p.status in ['won', 'lost']] settled.sort(key=lambda x: x.created_at) if not settled: return {'current_streak': 0, 'streak_type': 'none', 'best_streak': 0} current_streak = 0 current_type = settled[-1].status best_winning_streak = 0 current_winning = 0 for pred in settled: if pred.status == 'won': current_winning += 1 best_winning_streak = max(best_winning_streak, current_winning) else: current_winning = 0 # Calculate current streak for pred in reversed(settled): if pred.status == current_type: current_streak += 1 else: break return { 'current_streak': current_streak, 'streak_type': 'winning' if current_type == 'won' else 'losing', 'best_winning_streak': best_winning_streak } def get_value_bet_analysis(self) -> Dict: """Analyze value bet performance""" value_bets = [p for p in self.predictions if hasattr(p, 'is_value_bet') and p.is_value_bet] if not value_bets: return {'count': 0, 'accuracy': 0, 'avg_edge': 0, 'roi': 0} settled = [p for p in value_bets if p.status in ['won', 'lost']] if not settled: return {'count': len(value_bets), 'accuracy': 0, 'avg_edge': 0, 'roi': 0} correct = len([p for p in settled if p.status == 'won']) total_stakes = sum(p.stake for p in settled) total_profit = sum(p.profit_loss() for p in settled) return { 'count': len(value_bets), 'settled': len(settled), 'accuracy': round(correct / len(settled) * 100, 1), 'roi': round(total_profit / total_stakes * 100, 1) if total_stakes > 0 else 0 } def get_sure_wins_analysis(self) -> Dict: """Analyze sure wins (91%+ confidence) performance""" sure_wins = [p for p in self.predictions if p.confidence >= 0.91] if not sure_wins: return {'count': 0, 'accuracy': 0, 'profit': 0} settled = [p for p in sure_wins if p.status in ['won', 'lost']] if not settled: return {'count': len(sure_wins), 'accuracy': 0, 'profit': 0} correct = len([p for p in settled if p.status == 'won']) total_profit = sum(p.profit_loss() for p in settled) return { 'count': len(sure_wins), 'settled': len(settled), 'correct': correct, 'accuracy': round(correct / len(settled) * 100, 1), 'profit': round(total_profit, 2) } def get_dashboard_summary(self) -> Dict: """Get complete dashboard summary""" return { 'overall': { 'total_predictions': len(self.predictions), 'accuracy': round(self.get_overall_accuracy(), 1), 'roi_30d': round(self.get_roi(30), 1), 'roi_7d': round(self.get_roi(7), 1), }, 'streak': self.get_streak_info(), 'by_league': self.get_league_performance()[:5], 'by_confidence': self.get_confidence_analysis(), 'by_outcome': self.get_outcome_analysis(), 'trend': self.get_trend_analysis(14), 'sure_wins': self.get_sure_wins_analysis(), 'generated_at': datetime.now().isoformat() } # Global analytics instance analytics = AdvancedAnalytics() def record_prediction( home: str, away: str, league: str, prediction: str, confidence: float, odds: float = 1.0, stake: float = 10.0 ) -> str: """Record a new prediction""" record = PredictionRecord( id=f"pred_{datetime.now().timestamp()}", home=home, away=away, league=league, predicted_outcome=prediction, actual_outcome=None, confidence=confidence, odds=odds, stake=stake, status='pending', created_at=datetime.now().isoformat() ) analytics.add_prediction(record) return record.id def settle_prediction(pred_id: str, actual_outcome: str) -> bool: """Settle a prediction as won or lost""" for pred in analytics.predictions: if pred.id == pred_id: pred.actual_outcome = actual_outcome pred.status = 'won' if pred.predicted_outcome == actual_outcome else 'lost' pred.settled_at = datetime.now().isoformat() analytics._update_stats(pred) return True return False def get_analytics_summary() -> Dict: """Get analytics dashboard summary""" return analytics.get_dashboard_summary() def get_league_accuracy(league: str) -> float: """Get accuracy for a specific league""" stats = analytics.league_stats.get(league) if stats and stats['total'] > 0: return stats['correct'] / stats['total'] * 100 return 0.0