Files
fahricansecer 2f0b85a0c7
Deploy Iddaai Backend / build-and-deploy (push) Failing after 18s
first (part 2: other directories)
2026-04-16 15:11:25 +03:00

357 lines
13 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Smart Bet Recommender
=====================
Skor tahminine göre akıllı bahis önerileri yapan sistem.
Örnek: Beşiktaş-Galatasaray için model 3-1 tahmin ediyor
→ DÜŞÜK RİSK: 1.5 Üst (yüksek ihtimal tutar)
→ ORTA RİSK: MS 1 + 2.5 Üst (orta ihtimal)
→ YÜKSEK RİSK: 3.5 Üst veya skor 3-1 (düşük ihtimal, yüksek kazanç)
Ayrıca kombinasyonlar:
- MS 1 + 1.5 Üst
- MS 1 + KG Var
- Her iki takım skor > 0.5 (her takım en az 1 gol atar)
"""
from dataclasses import dataclass
from typing import Dict, List, Optional, Tuple
from enum import Enum
class RiskLevel(Enum):
LOW = "LOW" # Yüksek olasılık, düşük oran (güvenli)
MEDIUM = "MEDIUM" # Orta olasılık, orta oran
HIGH = "HIGH" # Düşük olasılık, yüksek kazanç
EXTREME = "EXTREME" # Çok düşük olasılık, çok yüksek kazanç
@dataclass
class BetRecommendation:
"""Tek bir bahis önerisi"""
market: str # Piyasa adı (örn: "MS 1", "2.5 Üst")
pick: str # Seçim (örn: "1", "OVER", "YES")
odds: float # Oran
probability: float # Model olasılığı (0-1)
confidence: float # Güven seviyesi (0-100)
risk_level: RiskLevel
def to_dict(self) -> dict:
return {
"market": self.market,
"pick": self.pick,
"odds": self.odds,
"probability": round(self.probability * 100, 1),
"confidence": round(self.confidence, 1),
"risk_level": self.risk_level.value
}
@dataclass
class MatchPredictionSet:
"""Bir maç için tüm tahmin seti"""
match_name: str
predicted_score: Tuple[int, int] # (home, away)
home_win_prob: float
draw_prob: float
away_win_prob: float
over_15_prob: float
over_25_prob: float
over_35_prob: float
btts_yes_prob: float
# Öneriler
low_risk_bets: List[BetRecommendation]
medium_risk_bets: List[BetRecommendation]
high_risk_bets: List[BetRecommendation]
extreme_risk_bets: List[BetRecommendation]
def to_dict(self) -> dict:
return {
"match_name": self.match_name,
"predicted_score": f"{self.predicted_score[0]}-{self.predicted_score[1]}",
"probs": {
"home_win": round(self.home_win_prob * 100, 1),
"draw": round(self.draw_prob * 100, 1),
"away_win": round(self.away_win_prob * 100, 1),
"over_15": round(self.over_15_prob * 100, 1),
"over_25": round(self.over_25_prob * 100, 1),
"over_35": round(self.over_35_prob * 100, 1),
"btts": round(self.btts_yes_prob * 100, 1)
},
"low_risk": [b.to_dict() for b in self.low_risk_bets],
"medium_risk": [b.to_dict() for b in self.medium_risk_bets],
"high_risk": [b.to_dict() for b in self.high_risk_bets],
"extreme_risk": [b.to_dict() for b in self.extreme_risk_bets]
}
class SmartBetRecommender:
"""
Akıllı Bahis Öneri Sistemi
Skor tahminine göre farklı risk seviyelerinde bahisler önerir.
Mantık:
1. DÜŞÜK RİSK: Yüksek olasılıklı (>70%), düşük oranlı bahisler
- 1.5 Üst
- Double Chance
- Favori takım gol atar
2. ORTA RİSK: Orta olasılıklı (50-70%), orta oranlı bahisler
- MS favori
- 2.5 Üst
- KG Var/Var
3. YÜKSEK RİSK: Düşük olasılıklı (30-50%), yüksek oranlı bahisler
- 3.5 Üst
- Skor tahmini
- Handikap
4. EXTREME RİSK: Çok düşük olasılıklı (<30%), çok yüksek oranlı
- Tam skor
- Uzunluklu kombinasyonlar
"""
# Olasılık eşikleri
PROB_LOW_RISK = 0.70 # > %70 olasılık
PROB_MEDIUM_RISK = 0.50 # %50-70 olasılık
PROB_HIGH_RISK = 0.30 # %30-50 olasılık
# < %30 = EXTREME
def __init__(self):
pass
def _determine_risk(self, probability: float) -> RiskLevel:
"""Olasılığa göre risk seviyesi belirle"""
if probability >= self.PROB_LOW_RISK:
return RiskLevel.LOW
elif probability >= self.PROB_MEDIUM_RISK:
return RiskLevel.MEDIUM
elif probability >= self.PROB_HIGH_RISK:
return RiskLevel.HIGH
else:
return RiskLevel.EXTREME
def _get_favorite(self, home_prob: float, draw_prob: float, away_prob: float) -> Tuple[str, float]:
"""Favori sonucu ve olasılığını döndür"""
if home_prob >= draw_prob and home_prob >= away_prob:
return "1", home_prob
elif away_prob >= home_prob and away_prob >= draw_prob:
return "2", away_prob
else:
return "X", draw_prob
def _calculate_expected_goals(self, predicted_score: Tuple[int, int]) -> float:
"""Tahmin edilen skora göre beklenen gol sayısı"""
return predicted_score[0] + predicted_score[1]
def recommend(
self,
match_name: str,
predicted_score: Tuple[int, int],
probs: Dict[str, float],
odds: Dict[str, float]
) -> MatchPredictionSet:
"""
Maç için tüm bahis önerilerini oluştur.
Args:
match_name: Maç adı
predicted_score: (home_goals, away_goals)
probs: {"home_win": 0.55, "draw": 0.25, "away_win": 0.20,
"over_15": 0.85, "over_25": 0.65, "over_35": 0.35,
"btts_yes": 0.55}
odds: {"1": 1.80, "X": 3.50, "2": 4.20,
"ou15_o": 1.25, "ou15_u": 3.80,
"ou25_o": 1.90, "ou25_u": 1.85,
"ou35_o": 3.20, "ou35_u": 1.30,
"btts_y": 1.75, "btts_n": 2.00}
Returns:
MatchPredictionSet with all recommendations
"""
home_prob = probs.get("home_win", 0.33)
draw_prob = probs.get("draw", 0.33)
away_prob = probs.get("away_win", 0.33)
over_15_prob = probs.get("over_15", 0.70)
over_25_prob = probs.get("over_25", 0.50)
over_35_prob = probs.get("over_35", 0.30)
btts_prob = probs.get("btts_yes", 0.50)
# Beklenen goller
expected_goals = self._calculate_expected_goals(predicted_score)
# Favori
favorite, favorite_prob = self._get_favorite(home_prob, draw_prob, away_prob)
# Önerileri oluştur
low_risk = []
medium_risk = []
high_risk = []
extreme_risk = []
# ========== DÜŞÜK RİSK ÖNERİLERİ ==========
# 1.5 Üst (en güvenli)
if over_15_prob >= self.PROB_LOW_RISK:
low_risk.append(BetRecommendation(
market="1.5 Üst/Alt",
pick="OVER",
odds=odds.get("ou15_o", 1.25),
probability=over_15_prob,
confidence=over_15_prob * 100,
risk_level=RiskLevel.LOW
))
# Double Chance
if home_prob > away_prob:
dc_prob = home_prob + draw_prob
if dc_prob >= self.PROB_LOW_RISK:
low_risk.append(BetRecommendation(
market="Double Chance",
pick="1X",
odds=odds.get("dc_1x", 1.30),
probability=dc_prob,
confidence=dc_prob * 100,
risk_level=RiskLevel.LOW
))
elif away_prob > home_prob:
dc_prob = away_prob + draw_prob
if dc_prob >= self.PROB_LOW_RISK:
low_risk.append(BetRecommendation(
market="Double Chance",
pick="X2",
odds=odds.get("dc_x2", 1.30),
probability=dc_prob,
confidence=dc_prob * 100,
risk_level=RiskLevel.LOW
))
# ========== ORTA RİSK ÖNERİLERİ ==========
# MS Favori
if self.PROB_MEDIUM_RISK <= favorite_prob < self.PROB_LOW_RISK:
medium_risk.append(BetRecommendation(
market="Maç Sonucu",
pick=favorite,
odds=odds.get(favorite, 2.00),
probability=favorite_prob,
confidence=favorite_prob * 100,
risk_level=RiskLevel.MEDIUM
))
# 2.5 Üst
if self.PROB_MEDIUM_RISK <= over_25_prob < self.PROB_LOW_RISK:
medium_risk.append(BetRecommendation(
market="2.5 Üst/Alt",
pick="OVER",
odds=odds.get("ou25_o", 1.90),
probability=over_25_prob,
confidence=over_25_prob * 100,
risk_level=RiskLevel.MEDIUM
))
# KG Var
if self.PROB_MEDIUM_RISK <= btts_prob < self.PROB_LOW_RISK:
medium_risk.append(BetRecommendation(
market="Karşılıklı Gol",
pick="YES",
odds=odds.get("btts_y", 1.75),
probability=btts_prob,
confidence=btts_prob * 100,
risk_level=RiskLevel.MEDIUM
))
# MS + 2.5 Üst kombinasyonu
if favorite_prob >= 0.45 and over_25_prob >= 0.50:
combo_prob = favorite_prob * over_25_prob # Basit çarpım
combo_odds = odds.get(favorite, 2.00) * odds.get("ou25_o", 1.90)
if combo_prob >= 0.30: # En az %30 olasılık
medium_risk.append(BetRecommendation(
market=f"MS {favorite} + 2.5 Üst",
pick=f"{favorite} & OVER",
odds=combo_odds,
probability=combo_prob,
confidence=combo_prob * 100,
risk_level=RiskLevel.MEDIUM
))
# ========== YÜKSEK RİSK ÖNERİLERİ ==========
# 3.5 Üst
if self.PROB_HIGH_RISK <= over_35_prob < self.PROB_MEDIUM_RISK:
high_risk.append(BetRecommendation(
market="3.5 Üst/Alt",
pick="OVER",
odds=odds.get("ou35_o", 3.20),
probability=over_35_prob,
confidence=over_35_prob * 100,
risk_level=RiskLevel.HIGH
))
# Skor tahmini (yüksek skorlu maçlar için)
if expected_goals >= 3.5:
score_str = f"{predicted_score[0]}-{predicted_score[1]}"
# Skor olasılığı tahmini (basit model)
score_prob = 0.15 if expected_goals <= 4 else 0.10
high_risk.append(BetRecommendation(
market="Tam Skor",
pick=score_str,
odds=8.0, # Tahmini oran
probability=score_prob,
confidence=score_prob * 100,
risk_level=RiskLevel.HIGH
))
# MS + 3.5 Üst
if favorite_prob >= 0.40 and over_35_prob >= 0.30:
combo_prob = favorite_prob * over_35_prob
combo_odds = odds.get(favorite, 2.00) * odds.get("ou35_o", 3.20)
high_risk.append(BetRecommendation(
market=f"MS {favorite} + 3.5 Üst",
pick=f"{favorite} & OVER",
odds=combo_odds,
probability=combo_prob,
confidence=combo_prob * 100,
risk_level=RiskLevel.HIGH
))
# ========== EXTREME RİSK ÖNERİLERİ ==========
# Uzun kombinasyonlar
if favorite_prob >= 0.50 and btts_prob >= 0.50 and over_25_prob >= 0.60:
combo_prob = favorite_prob * btts_prob * over_25_prob
combo_odds = odds.get(favorite, 2.00) * odds.get("btts_y", 1.75) * odds.get("ou25_o", 1.90)
if combo_prob >= 0.15: # En az %15 olasılık
extreme_risk.append(BetRecommendation(
market=f"MS {favorite} + KG Var + 2.5 Üst",
pick=f"{favorite} & BTTS & OVER",
odds=combo_odds,
probability=combo_prob,
confidence=combo_prob * 100,
risk_level=RiskLevel.EXTREME
))
return MatchPredictionSet(
match_name=match_name,
predicted_score=predicted_score,
home_win_prob=home_prob,
draw_prob=draw_prob,
away_win_prob=away_prob,
over_15_prob=over_15_prob,
over_25_prob=over_25_prob,
over_35_prob=over_35_prob,
btts_yes_prob=btts_prob,
low_risk_bets=low_risk,
medium_risk_bets=medium_risk,
high_risk_bets=high_risk,
extreme_risk_bets=extreme_risk
)
# Singleton
_recommender = None
def get_smart_bet_recommender() -> SmartBetRecommender:
global _recommender
if _recommender is None:
_recommender = SmartBetRecommender()
return _recommender