amarorn / models /corners_predictor.py
beAnalytic's picture
feat: sync main with feature/superbet-live-inplay
16c19b8 verified
Raw
History Blame Contribute Delete
3.02 kB
from __future__ import annotations
from dataclasses import dataclass
from datetime import datetime, timezone
import pandas as pd
from ingest.fixtures.world_cup import load_wc_fixtures
from ingest.sofascore.corners_dataset import corners_training_summary, load_corners_history
from models.poisson_corners import (
CornerModelFactors,
CornersPrediction,
corner_model_factors,
predict_corners,
)
from models.poisson_wc import goal_model_factors
from pipelines.wc_stats import build_match_features
@dataclass
class CornersMatchPrediction:
home_team: str
away_team: str
prediction: CornersPrediction
factors: CornerModelFactors
training_summary: dict
data_source: str
class CornersPredictor:
def __init__(
self,
*,
corners_df: pd.DataFrame | None = None,
fixtures_df: pd.DataFrame | None = None,
) -> None:
self.corners_df = corners_df if corners_df is not None else load_corners_history()
self.fixtures = fixtures_df if fixtures_df is not None else load_wc_fixtures()
def predict(
self,
home_team: str,
away_team: str,
*,
phase: str = "group",
is_neutral: bool = True,
before_date: datetime | None = None,
season: int | None = None,
group_name: str | None = None,
) -> CornersMatchPrediction:
cutoff = before_date or datetime.now(timezone.utc)
features = build_match_features(
self.fixtures,
home_team,
away_team,
before_date=cutoff,
phase=phase,
is_neutral=is_neutral,
season=season,
group_name=group_name,
)
goal_factors = goal_model_factors(
self.fixtures,
home_team,
away_team,
features=features,
before_date=cutoff,
)
goal_lam_home = goal_factors.lambda_home
goal_lam_away = goal_factors.lambda_away
league_goal_avg = goal_factors.league_avg
factors = corner_model_factors(
self.corners_df,
home_team,
away_team,
features=features,
before_date=cutoff,
goal_lam_home=goal_lam_home,
goal_lam_away=goal_lam_away,
league_goal_avg=league_goal_avg,
)
prediction = predict_corners(factors.lambda_home, factors.lambda_away)
data_source = "sofascore_corners"
if factors.training_matches == 0:
data_source = "goal_proxy_default"
elif factors.blend_with_goal_proxy > 0:
data_source = "sofascore_corners+goal_proxy"
return CornersMatchPrediction(
home_team=home_team,
away_team=away_team,
prediction=prediction,
factors=factors,
training_summary=corners_training_summary(
load_corners_history(before_date=cutoff)
),
data_source=data_source,
)