""" VQWEN Full Backtest =================== Tests all 3 VQWEN models (MS, OU25, BTTS) on 1000 historical matches. """ 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_vqwen_backtest(): print("🧠 VQWEN FULL BACKTEST") 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 MS, OU25, BTTS 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, t1.name as home_team, t2.name as away_team, (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, COALESCE((SELECT AVG(CASE WHEN m2.home_team_id = m.home_team_id AND m2.score_home > m2.score_away THEN 3 WHEN m2.home_team_id = m.home_team_id AND m2.score_home = m2.score_away THEN 1 ELSE 0 END) FROM matches m2 WHERE m2.home_team_id = m.home_team_id AND m2.status = 'FT' AND m2.mst_utc < m.mst_utc LIMIT 5), 0) as h_form, COALESCE((SELECT AVG(CASE WHEN m2.away_team_id = m.away_team_id AND m2.score_away > m2.score_home THEN 3 WHEN m2.away_team_id = m.away_team_id AND m2.score_away = m2.score_home THEN 1 ELSE 0 END) FROM matches m2 WHERE m2.away_team_id = m.away_team_id AND m2.status = 'FT' AND m2.mst_utc < m.mst_utc LIMIT 5), 0) as a_form, COALESCE((SELECT AVG(m2.score_home) FROM matches m2 WHERE m2.home_team_id = m.home_team_id AND m2.status = 'FT' LIMIT 10), 1.2) as h_sc, COALESCE((SELECT AVG(m2.score_away) FROM matches m2 WHERE m2.away_team_id = m.home_team_id AND m2.status = 'FT' LIMIT 10), 1.2) as h_co, COALESCE((SELECT AVG(m2.score_away) FROM matches m2 WHERE m2.away_team_id = m.away_team_id AND m2.status = 'FT' LIMIT 10), 1.2) as a_sc, COALESCE((SELECT AVG(m2.score_home) FROM matches m2 WHERE m2.home_team_id = m.away_team_id AND m2.status = 'FT' LIMIT 10), 1.2) as a_co 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 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, od, oa = float(row['oh'] or 0), float(row['od'] or 0), float(row['oa'] or 0) if oh <= 1.0 or od <= 1.0 or oa <= 1.0: continue h_xg = (float(row['h_sc'] or 1.2) + float(row['a_co'] or 1.2)) / 2 a_xg = (float(row['a_sc'] or 1.2) + float(row['h_co'] or 1.2)) / 2 h_p = (float(row['h_form'] or 0)*10) + (float(row['h_sc'] or 1.2)*5) - (float(row['h_co'] or 1.2)*5) a_p = (float(row['a_form'] or 0)*10) + (float(row['a_sc'] or 1.2)*5) - (float(row['a_co'] or 1.2)*5) margin = (1/oh) + (1/od) + (1/oa) # MS Prediction f_ms = pd.DataFrame([{'h_form': float(row['h_form']), 'a_form': float(row['a_form']), 'h_xg': h_xg, 'a_xg': a_xg, 'pow_diff': h_p - a_p, 'imp_h': (1/oh)/margin, 'imp_d': (1/od)/margin, 'imp_a': (1/oa)/margin, 'h_sot': 4.0, 'a_sot': 3.0}]) ms_probs = model_ms.predict(f_ms)[0] # MS Value Bet 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.50: # Value ve Güven 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 Prediction f_ou = pd.DataFrame([{'h_xg': h_xg, 'a_xg': a_xg, 'total_xg': h_xg+a_xg, 'h_sot': 4.0, 'a_sot': 3.0}]) p_over = model_ou.predict(f_ou)[0] # OU2.5 Value Bet if p_over > 0.55 and oh > 1.0: # Sadece örnek olarak over > %55 ise results['ou25']['bet'] += 1 if (row['score_home'] + row['score_away']) > 2.5: results['ou25']['won'] += 1; results['ou25']['profit'] += 0.85 # Ortalama oran else: results['ou25']['profit'] -= 1.0 # BTTS Prediction f_btts = pd.DataFrame([{'h_xg': h_xg, 'a_xg': a_xg, 'h_sc': float(row['h_sc']), 'a_sc': float(row['a_sc'])}]) p_btts = model_btts.predict(f_btts)[0] # BTTS Value Bet 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 PAZAR BAZLI 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} Oynanan: {r['bet']:<5} Kazanılan: {r['won']:<5} WR: {wr:.1f}% Kâr: {r['profit']:+.2f} Units") total_profit = sum(r['profit'] for r in results.values()) print(f"\n💰 TOPLAM KÂR: {total_profit:+.2f} Units") if total_profit > 0: print("🟢 PARA KAZANDIK!") else: print("🔴 ZARARDA") cur.close() conn.close() if __name__ == "__main__": run_vqwen_backtest()