This commit is contained in:
@@ -60,6 +60,51 @@ from models.calibration import get_calibrator
|
||||
|
||||
|
||||
class CouponMixin:
|
||||
def _prefilter_match_ids(self, match_ids: List[str], limit: int = 15) -> List[str]:
|
||||
"""
|
||||
40+ maç gelirse hepsini analiz etmek çok yavaş.
|
||||
DB'den hızlıca en kaliteli limit adet maçı seç:
|
||||
- Odds verisi olan maçlar önce
|
||||
- football_ai_features'da gerçek ELO'su olan maçlar
|
||||
- Yüksek lig güvenilirliği
|
||||
"""
|
||||
if len(match_ids) <= limit:
|
||||
return match_ids
|
||||
|
||||
try:
|
||||
with psycopg2.connect(self.dsn) as conn:
|
||||
with conn.cursor(cursor_factory=RealDictCursor) as cur:
|
||||
cur.execute("""
|
||||
SELECT
|
||||
m.id,
|
||||
COUNT(oc.db_id) AS odds_count,
|
||||
COALESCE(f.home_elo, 1500) AS home_elo,
|
||||
lr.reliability_score
|
||||
FROM matches m
|
||||
LEFT JOIN odd_categories oc ON oc.match_id = m.id
|
||||
LEFT JOIN football_ai_features f ON f.match_id = m.id
|
||||
LEFT JOIN team_elo_ratings ter_h ON ter_h.team_id = m.home_team_id
|
||||
LEFT JOIN (
|
||||
SELECT league_id, AVG(home_elo) AS reliability_score
|
||||
FROM football_ai_features
|
||||
GROUP BY league_id
|
||||
) lr ON lr.league_id = m.league_id
|
||||
WHERE m.id = ANY(%s)
|
||||
GROUP BY m.id, f.home_elo, lr.reliability_score
|
||||
ORDER BY
|
||||
COUNT(oc.db_id) DESC,
|
||||
COALESCE(f.home_elo, 1500) DESC
|
||||
LIMIT %s
|
||||
""", (match_ids, limit))
|
||||
rows = cur.fetchall()
|
||||
filtered = [r["id"] for r in rows]
|
||||
# Eğer DB'den yeterli gelmediyse kalanları ekle
|
||||
remaining = [m for m in match_ids if m not in filtered]
|
||||
return filtered + remaining[:max(0, limit - len(filtered))]
|
||||
except Exception as e:
|
||||
print(f"⚠️ Prefilter failed, using original list: {e}")
|
||||
return match_ids[:limit]
|
||||
|
||||
def build_coupon(
|
||||
self,
|
||||
match_ids: List[str],
|
||||
@@ -70,15 +115,21 @@ class CouponMixin:
|
||||
strategy_name = (strategy or "BALANCED").upper()
|
||||
|
||||
strategy_config = {
|
||||
"SAFE": {"max_matches": 4, "min_conf": 66.0},
|
||||
"BALANCED": {"max_matches": 5, "min_conf": 58.0},
|
||||
"AGGRESSIVE": {"max_matches": 8, "min_conf": 52.0},
|
||||
"VALUE": {"max_matches": 8, "min_conf": 48.0},
|
||||
"MIRACLE": {"max_matches": 10, "min_conf": 44.0},
|
||||
"SAFE": {"max_matches": 4, "min_conf": 66.0, "prefilter": 12},
|
||||
"BALANCED": {"max_matches": 5, "min_conf": 58.0, "prefilter": 15},
|
||||
"AGGRESSIVE": {"max_matches": 8, "min_conf": 52.0, "prefilter": 20},
|
||||
"VALUE": {"max_matches": 8, "min_conf": 48.0, "prefilter": 20},
|
||||
"MIRACLE": {"max_matches": 10, "min_conf": 44.0, "prefilter": 25},
|
||||
}
|
||||
cfg = strategy_config.get(strategy_name, strategy_config["BALANCED"])
|
||||
max_allowed = max_matches if max_matches is not None else cfg["max_matches"]
|
||||
min_conf = min_confidence if min_confidence is not None else cfg["min_conf"]
|
||||
prefilter_limit = cfg["prefilter"]
|
||||
|
||||
# Çok fazla maç gelirse önce hızlı prefilter uygula
|
||||
if len(match_ids) > prefilter_limit:
|
||||
print(f"🔍 Prefiltering {len(match_ids)} → {prefilter_limit} matches for {strategy_name} coupon")
|
||||
match_ids = self._prefilter_match_ids(match_ids, prefilter_limit)
|
||||
|
||||
candidates: List[Dict[str, Any]] = []
|
||||
rejected: List[Dict[str, Any]] = []
|
||||
|
||||
Reference in New Issue
Block a user