""" Adaptive 500 Match Backtest ============================= Skips NO match unless NO odds exist. Evaluates ALL available markets (MS, OU, BTTS) and picks the BEST value bet. """ import os import sys import json import time import psycopg2 from psycopg2.extras import RealDictCursor AI_DIR = os.path.dirname(os.path.abspath(__file__)) ROOT_DIR = os.path.dirname(AI_DIR) sys.path.insert(0, ROOT_DIR) if "scripts" in os.path.basename(AI_DIR): ROOT_DIR = os.path.dirname(ROOT_DIR) from services.single_match_orchestrator import get_single_match_orchestrator def get_clean_dsn() -> str: return "postgresql://suggestbet:SuGGesT2026SecuRe@localhost:15432/boilerplate_db" def run_adaptive_backtest(): print("🔄 ADAPTIVE 500 MATCH BACKTEST") print("="*60) # 1. Load Top Leagues leagues_path = os.path.join(ROOT_DIR, "top_leagues.json") with open(leagues_path, 'r') as f: top_leagues = json.load(f) league_ids = tuple(str(lid) for lid in top_leagues) dsn = get_clean_dsn() conn = psycopg2.connect(dsn) cur = conn.cursor(cursor_factory=RealDictCursor) # 2. Fetch 500 Finished Matches with Odds cur.execute(""" SELECT m.id, m.match_name, m.home_team_id, m.away_team_id, m.score_home, m.score_away, m.league_id, t1.name as home_team, t2.name as away_team FROM matches m LEFT JOIN teams t1 ON m.home_team_id = t1.id LEFT JOIN teams t2 ON m.away_team_id = t2.id WHERE m.league_id IN %s AND m.status = 'FT' AND m.score_home IS NOT NULL AND EXISTS (SELECT 1 FROM odd_categories oc WHERE oc.match_id = m.id) ORDER BY m.mst_utc DESC LIMIT 500 """, (league_ids,)) rows = cur.fetchall() print(f"📊 Found {len(rows)} matches. Analyzing...\n") if not rows: print("⚠️ No matches found.") return try: orchestrator = get_single_match_orchestrator() except Exception as e: print(f"❌ AI Error: {e}") return # Stats total_evaluated = 0 total_bet = 0 total_won = 0 total_profit = 0.0 skipped_count = 0 for i, row in enumerate(rows): match_id = str(row['id']) home = row['home_team'] or "?" away = row['away_team'] or "?" h_score = row['score_home'] or 0 a_score = row['score_away'] or 0 total_evaluated += 1 # print(f"[{i+1}] {home} vs {away} ... ", end="", flush=True) try: pred = orchestrator.analyze_match(match_id) if not pred: # print("⚠️ No Data") continue # ─── ADAPTIVE PICKING ─── # Check ALL recommendations (Expert or Standard) to find the BEST option candidates = [] # Add main picks if pred.get("expert_recommendation"): rec = pred["expert_recommendation"] if rec.get("main_pick"): candidates.append(rec["main_pick"]) if rec.get("safe_alternative"): candidates.append(rec["safe_alternative"]) if rec.get("value_picks"): candidates.extend(rec["value_picks"]) elif pred.get("main_pick"): candidates.append(pred["main_pick"]) best_bet = None for c in candidates: if not c: continue conf = c.get("confidence", 0) odds = c.get("odds", 0) pick = c.get("pick") # Flexible Criteria: # 1. Confidence > 60% # 2. Odds > 1.10 (Not "free" odds like 1.00) # 3. Edge > -2% (Slightly tolerant) if conf >= 60 and odds > 1.10: implied = 1.0 / odds edge = ((conf/100) - implied) * 100 # Prioritize positive edge, but accept small negative if confidence is high if edge > -2.0: if best_bet is None or (conf > best_bet.get("confidence", 0)): best_bet = c if best_bet: pick = str(best_bet.get("pick")).upper() conf = best_bet.get("confidence") odds = best_bet.get("odds") # Resolution Logic won = False if pick in ["1", "MS 1", "İY 1"] and h_score > a_score: won = True elif pick in ["X", "MS X", "İY X"] and h_score == a_score: won = True elif pick in ["2", "MS 2", "İY 2"] and a_score > h_score: won = True elif pick in ["1X", "X2"]: if "1X" in pick and h_score >= a_score: won = True elif "X2" in pick and a_score >= h_score: won = True elif pick == "12" and h_score != a_score: won = True elif "ÜST" in pick or "OVER" in pick: line = 2.5 if "1.5" in pick: line = 1.5 elif "3.5" in pick: line = 3.5 if (h_score + a_score) > line: won = True elif "ALT" in pick or "UNDER" in pick: line = 2.5 if "1.5" in pick: line = 1.5 elif "3.5" in pick: line = 3.5 if (h_score + a_score) < line: won = True elif "VAR" in pick and h_score > 0 and a_score > 0: won = True elif "YOK" in pick and (h_score == 0 or a_score == 0): won = True total_bet += 1 if won: total_won += 1 profit = odds - 1.0 total_profit += profit # print(f"✅ WON (+{profit:.2f}) | {pick}") else: total_profit -= 1.0 # print(f"❌ LOST ({pick} @ {odds:.2f})") else: skipped_count += 1 # print(f"🚫 SKIP (No Value)") except Exception as e: # print(f"💥 Error: {e}") pass print("\n" + "="*60) print("🔄 ADAPTIVE BACKTEST RESULTS (500 Matches)") print("="*60) print(f"📊 Evaluated: {total_evaluated}") print(f"🎲 Played: {total_bet}") print(f"🚫 Skipped: {skipped_count}") print(f"✅ Won: {total_won}") if total_bet > 0: win_rate = (total_won / total_bet) * 100 roi = (total_profit / total_bet) * 100 print(f"📈 Win Rate: {win_rate:.2f}%") print(f"💰 Total Profit: {total_profit:.2f} Units") print(f"📊 ROI: {roi:.2f}%") if total_profit > 0: print("🟢 KARLI STRATEJİ") else: print("🔴 ZARARDA") else: print("⚠️ Hiç bahis oynanmadı. Veri kalitesi çok düşük.") cur.close() conn.close() if __name__ == "__main__": run_adaptive_backtest()