changes
Deploy Iddaai Backend / build-and-deploy (push) Successful in 42s

This commit is contained in:
2026-05-20 10:10:28 +03:00
parent 1d4aa36602
commit 9481ad7094
9 changed files with 103 additions and 25 deletions
+56 -5
View File
@@ -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]] = []