first (part 2: other directories)
Deploy Iddaai Backend / build-and-deploy (push) Failing after 18s

This commit is contained in:
2026-04-16 15:11:25 +03:00
parent 7814e0bc6b
commit 2f0b85a0c7
203 changed files with 59989 additions and 0 deletions
+249
View File
@@ -0,0 +1,249 @@
"""
Value Betting Calculator
Expected Value (EV) ve stake önerileri hesaplar.
"""
from typing import Dict, Optional
from dataclasses import dataclass
@dataclass
class ValueBet:
"""Value bet analiz sonucu"""
bet_type: str # MS_1, AU25_Üst, KG_Var
my_probability: float # Bizim tahminimiz
market_odds: float # Bahis oranı
implied_probability: float # Oranın ima ettiği olasılık
edge: float # Fark (benim tahmin - implied)
expected_value: float # EV = (prob × odds) - 1
is_value: bool # EV > threshold mı?
kelly_fraction: float # Kelly stake oranı
confidence_tier: str # "banker", "strong", "value", "skip"
def to_dict(self) -> Dict:
return {
'bet_type': self.bet_type,
'my_probability': round(self.my_probability, 4),
'market_odds': self.market_odds,
'implied_probability': round(self.implied_probability, 4),
'edge': round(self.edge, 4),
'expected_value': round(self.expected_value, 4),
'is_value': self.is_value,
'kelly_fraction': round(self.kelly_fraction, 4),
'confidence_tier': self.confidence_tier,
}
class ValueCalculator:
"""
Value Betting Calculator
Tahminleri oranlarla karşılaştırarak EV hesaplar.
"""
# Eşikler
MIN_EDGE_FOR_VALUE = 0.05 # Minimum %5 edge
MIN_EDGE_FOR_STRONG = 0.10 # %10+ edge = strong value
MIN_EDGE_FOR_BANKER = 0.15 # %15+ edge = banker
KELLY_FRACTION = 0.25 # 1/4 Kelly (güvenli)
MAX_STAKE_PERCENT = 0.10 # Maksimum bank'ın %10'u
def __init__(self):
pass
def calculate_implied_probability(self, odds: float) -> float:
"""Bahis oranından implied probability hesapla"""
if odds <= 1:
return 1.0
return 1 / odds
def calculate_ev(self, probability: float, odds: float) -> float:
"""
Expected Value hesapla.
EV = (Probability × Odds) - 1
Pozitif EV = uzun vadede kar
Negatif EV = uzun vadede zarar
"""
return (probability * odds) - 1
def calculate_kelly_stake(self, probability: float, odds: float) -> float:
"""
Kelly Criterion stake hesapla.
Kelly = (p × b - q) / b
Burada:
- p = kazanma olasılığı
- q = kaybetme olasılığı (1 - p)
- b = odds - 1 (net kar)
"""
if odds <= 1:
return 0
b = odds - 1
p = probability
q = 1 - p
kelly = (p * b - q) / b
# Negatif veya çok yüksek değerleri sınırla
kelly = max(0, min(kelly, self.MAX_STAKE_PERCENT))
# Fractional Kelly (daha güvenli)
return kelly * self.KELLY_FRACTION
def analyze_bet(self, bet_type: str, my_probability: float,
market_odds: float) -> ValueBet:
"""
Tek bir bahis için value analizi yap.
Args:
bet_type: Bahis türü (MS_1, AU25_Üst, KG_Var vb.)
my_probability: Bizim tahminimiz (0-1 arası)
market_odds: Bahis oranı
Returns:
ValueBet: Analiz sonucu
"""
if market_odds <= 1:
return ValueBet(
bet_type=bet_type,
my_probability=my_probability,
market_odds=market_odds,
implied_probability=1.0,
edge=0,
expected_value=-1,
is_value=False,
kelly_fraction=0,
confidence_tier="skip"
)
implied = self.calculate_implied_probability(market_odds)
edge = my_probability - implied
ev = self.calculate_ev(my_probability, market_odds)
kelly = self.calculate_kelly_stake(my_probability, market_odds)
# Tier belirleme
if edge >= self.MIN_EDGE_FOR_BANKER and my_probability >= 0.70:
tier = "banker"
elif edge >= self.MIN_EDGE_FOR_STRONG:
tier = "strong"
elif edge >= self.MIN_EDGE_FOR_VALUE:
tier = "value"
else:
tier = "skip"
return ValueBet(
bet_type=bet_type,
my_probability=my_probability,
market_odds=market_odds,
implied_probability=implied,
edge=edge,
expected_value=ev,
is_value=edge >= self.MIN_EDGE_FOR_VALUE,
kelly_fraction=kelly,
confidence_tier=tier
)
def analyze_match_predictions(self, predictions: Dict[str, float],
odds: Dict[str, float]) -> Dict[str, ValueBet]:
"""
Maç için tüm tahminleri analiz et.
Args:
predictions: Tahminler {'MS_1': 0.55, 'MS_X': 0.25, ...}
odds: Oranlar {'MS_1': 1.80, 'MS_X': 3.50, ...}
Returns:
Dict[str, ValueBet]: Her bahis için value analizi
"""
results = {}
for bet_type, probability in predictions.items():
if bet_type in odds and odds[bet_type] > 1:
results[bet_type] = self.analyze_bet(
bet_type=bet_type,
my_probability=probability,
market_odds=odds[bet_type]
)
return results
def get_best_value_bets(self, value_bets: Dict[str, ValueBet],
top_n: int = 3) -> list:
"""En iyi value bet'leri döndür"""
valid_bets = [vb for vb in value_bets.values() if vb.is_value]
sorted_bets = sorted(valid_bets, key=lambda x: x.expected_value, reverse=True)
return sorted_bets[:top_n]
def calculate_stake(self, value_bet: ValueBet, bankroll: float,
use_kelly: bool = True) -> float:
"""
Önerilen stake miktarını hesapla.
Args:
value_bet: Value bet analizi
bankroll: Toplam bütçe
use_kelly: Kelly criterion kullan mı?
Returns:
float: Önerilen stake miktarı
"""
if not value_bet.is_value:
return 0
if use_kelly:
return bankroll * value_bet.kelly_fraction
else:
# Tier bazlı sabit stake
tier_stakes = {
"banker": 0.05,
"strong": 0.03,
"value": 0.02,
"skip": 0
}
return bankroll * tier_stakes.get(value_bet.confidence_tier, 0)
# Singleton
_calculator = None
def get_value_calculator() -> ValueCalculator:
global _calculator
if _calculator is None:
_calculator = ValueCalculator()
return _calculator
if __name__ == "__main__":
calc = get_value_calculator()
print("\n🧪 Value Calculator Test")
print("=" * 50)
# Test senaryoları
test_cases = [
{"bet": "MS_1", "prob": 0.70, "odds": 1.60}, # High prob, low odds
{"bet": "MS_1", "prob": 0.55, "odds": 1.90}, # Medium prob, good odds
{"bet": "MS_1", "prob": 0.60, "odds": 2.10}, # VALUE!
{"bet": "AU25_Üst", "prob": 0.65, "odds": 1.85}, # VALUE!
{"bet": "KG_Var", "prob": 0.50, "odds": 1.70}, # No value
]
for tc in test_cases:
result = calc.analyze_bet(tc["bet"], tc["prob"], tc["odds"])
status_emoji = "" if result.is_value else ""
tier_emoji = {"banker": "🎯", "strong": "💪", "value": "", "skip": "⏭️"}
print(f"\n{status_emoji} {tc['bet']}")
print(f" Tahmin: {tc['prob']:.0%} | Oran: {tc['odds']:.2f} | Implied: {result.implied_probability:.0%}")
print(f" Edge: {result.edge:+.1%} | EV: {result.expected_value:+.1%}")
print(f" Tier: {tier_emoji.get(result.confidence_tier, '')} {result.confidence_tier.upper()}")
print(f" Kelly Stake: {result.kelly_fraction:.2%} of bankroll")
if result.is_value:
stake = calc.calculate_stake(result, 1000)
print(f" 💰 Önerilen Stake (1000 TL bank): {stake:.2f} TL")