File size: 5,725 Bytes
a3d10df
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
336608c
 
a3d10df
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
336608c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a3d10df
 
 
 
 
 
 
336608c
 
 
a3d10df
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import os
import joblib
import pandas as pd
from data_loader import DataLoader
from feature_engineer import FeatureEngineer
from rule_based_model import RuleBasedModel

def get_predictions(model_dir='artifacts'):
    loader = DataLoader()
    rankings = loader.get_rankings()
    form = loader.get_team_form()
    teams = loader.get_teams()
    matches = loader.get_matches()
    try:
        manual_features = loader.get_manual_features()
    except Exception as e:
        print(f"WARNING: Could not load manual features: {e}")
        manual_features = None
    odds_summary = loader.get_latest_odds_summary()
    weather_summary = loader.get_latest_weather_summary()
    loader.close()
    
    engineer = FeatureEngineer(rankings, form, teams, manual_features)
    
    # Select upcoming matches
    upcoming = matches[matches['status'].isin(['scheduled', 'active'])].copy()
    if len(upcoming) == 0:
        return {"predictions": [], "skipped": []}
        
    X_pred, _ = engineer.build_dataset(upcoming)
    
    # Load model
    model_path = os.path.join(model_dir, 'rule_based_baseline.pkl')
    if not os.path.exists(model_path):
        raise FileNotFoundError(f"Model not found at {model_path}. Run train.py first.")
        
    clf = joblib.load(model_path)
    
    # Predict probabilities
    probs = clf.predict_proba(X_pred)
    
    X_pred['prob_away_win'] = probs[:, 0]
    X_pred['prob_draw'] = probs[:, 1]
    X_pred['prob_home_win'] = probs[:, 2]
    
    # Merge back to upcoming by match_id
    upcoming = upcoming.merge(X_pred[['match_id', 'prob_away_win', 'prob_draw', 'prob_home_win']], left_on='id', right_on='match_id', how='left')
    
    results = []
    skipped = []
    
    for _, row in upcoming.iterrows():
        if pd.isna(row['prob_home_win']):
            # Determine reason
            reason = "unknown"
            if pd.isna(row['home_team_id']) or pd.isna(row['away_team_id']):
                reason = "missing_team_placeholder"
            else:
                reason = "missing_features"
                
            skipped.append({
                "match_id": row['id'],
                "home_team_id": row['home_team_id'] if not pd.isna(row['home_team_id']) else None,
                "away_team_id": row['away_team_id'] if not pd.isna(row['away_team_id']) else None,
                "reason": reason
            })
            continue
            
        # Check if manual features were applied
        applied = False
        if manual_features is not None and row['id'] in manual_features.index:
            applied = True

        odds_rows = []
        if odds_summary is not None and not odds_summary.empty:
            match_odds = odds_summary[odds_summary['match_id'] == row['id']]
            for _, odds in match_odds.iterrows():
                odds_rows.append({
                    "bookmaker_key": odds.get("bookmaker_key"),
                    "bookmaker_title": odds.get("bookmaker_title"),
                    "market_key": odds.get("market_key"),
                    "market_title": odds.get("market_title"),
                    "home_odds": float(odds["home_odds"]) if not pd.isna(odds.get("home_odds")) else None,
                    "draw_odds": float(odds["draw_odds"]) if not pd.isna(odds.get("draw_odds")) else None,
                    "away_odds": float(odds["away_odds"]) if not pd.isna(odds.get("away_odds")) else None,
                    "last_update": str(odds.get("last_update")) if not pd.isna(odds.get("last_update")) else None,
                })

        weather = None
        if weather_summary is not None and not weather_summary.empty and row['id'] in weather_summary.index:
            w = weather_summary.loc[row['id']]
            weather = {
                "forecast_time": str(w.get("forecast_time")) if not pd.isna(w.get("forecast_time")) else None,
                "temperature_c": float(w["temperature_c"]) if not pd.isna(w.get("temperature_c")) else None,
                "apparent_temperature_c": float(w["apparent_temperature_c"]) if not pd.isna(w.get("apparent_temperature_c")) else None,
                "humidity_pct": float(w["humidity_pct"]) if not pd.isna(w.get("humidity_pct")) else None,
                "precipitation_probability_pct": float(w["precipitation_probability_pct"]) if not pd.isna(w.get("precipitation_probability_pct")) else None,
                "precipitation_mm": float(w["precipitation_mm"]) if not pd.isna(w.get("precipitation_mm")) else None,
                "wind_speed_kmh": float(w["wind_speed_kmh"]) if not pd.isna(w.get("wind_speed_kmh")) else None,
                "wind_gusts_kmh": float(w["wind_gusts_kmh"]) if not pd.isna(w.get("wind_gusts_kmh")) else None,
                "weather_code": int(w["weather_code"]) if not pd.isna(w.get("weather_code")) else None,
            }

        results.append({
            "match_id": row['id'],
            "home_team_id": row['home_team_id'],
            "away_team_id": row['away_team_id'],
            "prob_home_win": float(row['prob_home_win']),
            "prob_draw": float(row['prob_draw']),
            "prob_away_win": float(row['prob_away_win']),
            "manual_features_applied": applied,
            "odds": odds_rows,
            "weather": weather
        })
        
    return {
        "predictions": results,
        "skipped": skipped
    }

def run_predictions():
    data = get_predictions()
    print("\nUpcoming Match Predictions:")
    for p in data['predictions']:
        print(f"Match {p['match_id']} | {p['home_team_id']} vs {p['away_team_id']} "
              f"| 1: {p['prob_home_win']:.2f} X: {p['prob_draw']:.2f} 2: {p['prob_away_win']:.2f}")

if __name__ == "__main__":
    run_predictions()