""" VQWEN Final Backtest ==================== Tests the Final Model (ELO + Rest + Context). """ import os import sys import json import pickle import pandas as pd import numpy as np import psycopg2 from psycopg2.extras import RealDictCursor AI_DIR = os.path.dirname(os.path.abspath(__file__)) ROOT_DIR = os.path.dirname(AI_DIR) PROJECT_ROOT = os.path.dirname(ROOT_DIR) def get_clean_dsn() -> str: return "postgresql://suggestbet:SuGGesT2026SecuRe@localhost:15432/boilerplate_db" def run_final_backtest(): print("🧠 VQWEN FINAL BACKTEST (ELO + REST)") print("="*60) # Load Models mdir = os.path.join(ROOT_DIR, 'models', 'vqwen') try: with open(os.path.join(mdir, 'vqwen_ms.pkl'), 'rb') as f: model_ms = pickle.load(f) with open(os.path.join(mdir, 'vqwen_ou25.pkl'), 'rb') as f: model_ou = pickle.load(f) with open(os.path.join(mdir, 'vqwen_btts.pkl'), 'rb') as f: model_btts = pickle.load(f) print("✅ VQWEN Final modelleri yüklendi.") except Exception as e: print(f"❌ Model hatası: {e}") return with open(os.path.join(PROJECT_ROOT, "top_leagues.json"), 'r') as f: league_ids = tuple(str(lid) for lid in json.load(f)) dsn = get_clean_dsn() conn = psycopg2.connect(dsn) cur = conn.cursor(cursor_factory=RealDictCursor) cur.execute(""" SELECT m.id, m.home_team_id, m.away_team_id, m.score_home, m.score_away, m.mst_utc, t1.name as home_team, t2.name as away_team, maf.home_elo, maf.away_elo, COALESCE((SELECT AVG(m2.score_home) FROM matches m2 WHERE m2.home_team_id = m.home_team_id AND m2.status = 'FT' AND m2.mst_utc < m.mst_utc), 1.2) as h_home_goals, COALESCE((SELECT AVG(m2.score_away) FROM matches m2 WHERE m2.away_team_id = m.away_team_id AND m2.status = 'FT' AND m2.mst_utc < m.mst_utc), 1.2) as a_away_goals, COALESCE(EXTRACT(EPOCH FROM (to_timestamp(m.mst_utc/1000) - (SELECT MAX(to_timestamp(m2.mst_utc/1000)) FROM matches m2 WHERE m2.home_team_id = m.home_team_id AND m2.status = 'FT' AND m2.mst_utc < m.mst_utc)) / 86400), 7) as h_rest, COALESCE(EXTRACT(EPOCH FROM (to_timestamp(m.mst_utc/1000) - (SELECT MAX(to_timestamp(m2.mst_utc/1000)) FROM matches m2 WHERE m2.away_team_id = m.away_team_id AND m2.status = 'FT' AND m2.mst_utc < m.mst_utc)) / 86400), 7) as a_rest, COALESCE((SELECT COUNT(*) FROM match_player_participation mp WHERE mp.match_id = m.id AND mp.team_id = m.home_team_id AND mp.is_starting = true), 11) as h_xi, COALESCE((SELECT COUNT(*) FROM match_player_participation mp WHERE mp.match_id = m.id AND mp.team_id = m.away_team_id AND mp.is_starting = true), 11) as a_xi, COALESCE((SELECT COUNT(*) FROM match_player_events mpe WHERE mpe.match_id = m.id AND mpe.event_type = 'card'), 4) as cards, (SELECT os.odd_value FROM odd_categories oc JOIN odd_selections os ON os.odd_category_db_id = oc.db_id WHERE oc.match_id = m.id AND oc.name ILIKE 'Maç Sonucu' AND os.name = '1' LIMIT 1) as oh, (SELECT os.odd_value FROM odd_categories oc JOIN odd_selections os ON os.odd_category_db_id = oc.db_id WHERE oc.match_id = m.id AND oc.name ILIKE 'Maç Sonucu' AND os.name = 'X' LIMIT 1) as od, (SELECT os.odd_value FROM odd_categories oc JOIN odd_selections os ON os.odd_category_db_id = oc.db_id WHERE oc.match_id = m.id AND oc.name ILIKE 'Maç Sonucu' AND os.name = '2' LIMIT 1) as oa 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 LEFT JOIN football_ai_features maf ON maf.match_id = m.id WHERE m.league_id IN %s AND m.status = 'FT' AND m.score_home IS NOT NULL ORDER BY m.mst_utc DESC LIMIT 1000 """, (league_ids,)) rows = cur.fetchall() print(f"📊 {len(rows)} maç analiz ediliyor...") results = {'ms': {'bet': 0, 'won': 0, 'profit': 0}, 'ou25': {'bet': 0, 'won': 0, 'profit': 0}, 'btts': {'bet': 0, 'won': 0, 'profit': 0}} for row in rows: oh = float(row['oh'] or 0) od = float(row['od'] or 0) oa = float(row['oa'] or 0) if oh <= 1.0 or od <= 1.0 or oa <= 1.0: continue # Features h_elo = float(row['home_elo'] or 1500) a_elo = float(row['away_elo'] or 1500) h_home_goals = float(row['h_home_goals'] or 1.2) a_away_goals = float(row['a_away_goals'] or 1.2) h_rest = float(row['h_rest'] or 7) a_rest = float(row['a_rest'] or 7) h_xi = float(row['h_xi'] or 11) a_xi = float(row['a_xi'] or 11) cards = float(row['cards'] or 4) def fatigue(rest): if rest < 3: return 0.85 if rest < 5: return 0.95 return 1.0 h_fat = fatigue(h_rest) a_fat = fatigue(a_rest) h_xg = h_home_goals * h_fat a_xg = a_away_goals * a_fat total_xg = h_xg + a_xg margin = (1/oh) + (1/od) + (1/oa) f = pd.DataFrame([{ 'elo_diff': h_elo - a_elo, 'h_xg': h_xg, 'a_xg': a_xg, 'total_xg': total_xg, 'pow_diff': (h_elo/100)*h_fat - (a_elo/100)*a_fat, 'rest_diff': h_rest - a_rest, 'h_fatigue': h_fat, 'a_fatigue': a_fat, 'imp_h': (1/oh)/margin, 'imp_d': (1/od)/margin, 'imp_a': (1/oa)/margin, 'h_xi': h_xi, 'a_xi': a_xi, 'cards': cards }]) # MS ms_probs = model_ms.predict(f)[0] for i, (pick, prob, odd) in enumerate(zip(['1', 'X', '2'], ms_probs, [oh, od, oa])): if odd <= 1.0: continue edge = prob - (1/odd) if edge > 0.05 and prob > 0.45: results['ms']['bet'] += 1 h, a = row['score_home'], row['score_away'] w = (pick=='1' and h>a) or (pick=='X' and h==a) or (pick=='2' and a>h) if w: results['ms']['won'] += 1; results['ms']['profit'] += (odd - 1.0) else: results['ms']['profit'] -= 1.0 break # OU2.5 p_over = float(model_ou.predict(f)[0]) if p_over > 0.55: results['ou25']['bet'] += 1 if (row['score_home'] + row['score_away']) > 2.5: results['ou25']['won'] += 1; results['ou25']['profit'] += 0.85 else: results['ou25']['profit'] -= 1.0 # BTTS p_btts = float(model_btts.predict(f)[0]) if p_btts > 0.55: results['btts']['bet'] += 1 if row['score_home'] > 0 and row['score_away'] > 0: results['btts']['won'] += 1; results['btts']['profit'] += 0.85 else: results['btts']['profit'] -= 1.0 print("\n" + "="*60) print("📊 VQWEN FINAL SONUÇLAR") print("="*60) for mkt in ['ms', 'ou25', 'btts']: r = results[mkt] wr = (r['won'] / r['bet'] * 100) if r['bet'] > 0 else 0 print(f"{mkt.upper():<10} Oyn: {r['bet']:<5} Kaz: {r['won']:<5} WR: {wr:.1f}% Kâr: {r['profit']:+.2f}") total = sum(r['profit'] for r in results.values()) print(f"\n💰 TOPLAM: {total:+.2f} Units") print("🟢 PARA KAZANDIK!" if total > 0 else "🔴 ZARARDA") cur.close() conn.close() if __name__ == "__main__": run_final_backtest()