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
+250
View File
@@ -0,0 +1,250 @@
"""
VQWEN Live Prediction Tracker
=============================
Predicts today's upcoming matches (from live_matches) and tracks results.
"""
import os
import sys
import json
import time
import pickle
import psycopg2
import pandas as pd
import numpy as np
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_live_predictions():
print("🔴 VQWEN LIVE PREDICTION TRACKER")
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 v3 modelleri yüklendi.")
except Exception as e:
print(f"❌ Model hatası: {e}")
return
dsn = get_clean_dsn()
conn = psycopg2.connect(dsn)
cur = conn.cursor(cursor_factory=RealDictCursor)
# 1. Bugünün Maçlarını Çek (NS veya oynanıyor ama henüz bitmemiş olanlar)
# mst_utc bugün olan maçlar
start_of_day = int(time.mktime(time.strptime(time.strftime("%Y-%m-%d"), "%Y-%m-%d")) * 1000)
end_of_day = start_of_day + (24 * 60 * 60 * 1000)
print(f"📅 Bugünün maçları taranıyor...")
# live_matches veya matches tablosundan bugünkü maçları alıyoruz
# Önce odds olanları alalım
cur.execute("""
SELECT m.id, m.home_team_id, m.away_team_id, m.score_home, m.score_away,
m.mst_utc, m.status,
t1.name as home_team, t2.name as away_team,
l.name as league_name,
maf.home_elo, maf.away_elo
FROM live_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 leagues l ON m.league_id = l.id
LEFT JOIN football_ai_features maf ON maf.match_id = m.id
WHERE m.mst_utc >= %s AND m.mst_utc <= %s
ORDER BY m.mst_utc ASC
""", (start_of_day, end_of_day))
rows = cur.fetchall()
print(f"📊 Bugün için {len(rows)} maç bulundu.")
if not rows:
print("⚠️ Bugün için oranı olan maç bulunamadı.")
cur.close()
conn.close()
return
results = []
total_profit = 0.0
total_bet = 0
total_won = 0
for i, row in enumerate(rows):
match_id = str(row['id'])
home = row['home_team'] or "Home"
away = row['away_team'] or "Away"
league = row['league_name'] or "Unknown"
# Maç bitmiş mi kontrol et
is_finished = row['status'] in ['FT', 'AET', 'PEN', 'post', 'postGame'] or (
row['score_home'] is not None and row['score_away'] is not None and
row['status'] not in ['NS', 'pre', 'preGame', 'live', 'liveGame']
)
# Oranları al (odd_categories)
cur.execute("""
SELECT oc.name as category, os.name as selection, os.odd_value
FROM odd_categories oc
JOIN odd_selections os ON os.odd_category_db_id = oc.db_id
WHERE oc.match_id = %s AND oc.name ILIKE ANY (ARRAY['%%Maç Sonucu%%', '%%2,5 Alt/Üst%%', '%%Karşılıklı Gol%%'])
""", (match_id,))
odds_rows = cur.fetchall()
odds_dict = {}
for o in odds_rows:
cat = o['category'].lower()
sel = o['selection'].lower()
val = float(o['odd_value'])
if 'maç sonucu' in cat or 'mac sonucu' in cat:
if sel == '1': odds_dict['ms_h'] = val
elif sel == 'x': odds_dict['ms_d'] = val
elif sel == '2': odds_dict['ms_a'] = val
elif '2,5 alt' in cat or '2.5 alt' in cat:
if 'alt' in sel: odds_dict['ou25_u'] = val
elif 'üst' in sel or 'ust' in sel: odds_dict['ou25_o'] = val
elif 'karşılıklı gol' in cat:
if 'var' in sel: odds_dict['btts_y'] = val
elif 'yok' in sel: odds_dict['btts_n'] = val
# Eğer oranlar yoksa atla
if not all(k in odds_dict for k in ['ms_h', 'ms_d', 'ms_a', 'ou25_o', 'btts_y']):
# print(f"⚠️ {home} vs {away} - Oranlar eksik.")
continue
# Özellikleri Hesapla
# Form, Rest, Contextual Goals veritabanından çekilmeli (canlı maç için)
cur.execute("""
SELECT
COALESCE((SELECT AVG(m2.score_home) FROM matches m2 WHERE m2.home_team_id = %s AND m2.status = 'FT' AND m2.mst_utc < %s), 1.2) as h_home_goals,
COALESCE((SELECT AVG(m2.score_away) FROM matches m2 WHERE m2.away_team_id = %s AND m2.status = 'FT' AND m2.mst_utc < %s), 1.2) as a_away_goals,
COALESCE(EXTRACT(EPOCH FROM (to_timestamp(%s/1000) - (SELECT MAX(to_timestamp(m2.mst_utc/1000)) FROM matches m2 WHERE m2.home_team_id = %s AND m2.status = 'FT' AND m2.mst_utc < %s)) / 86400), 7) as h_rest,
COALESCE(EXTRACT(EPOCH FROM (to_timestamp(%s/1000) - (SELECT MAX(to_timestamp(m2.mst_utc/1000)) FROM matches m2 WHERE m2.away_team_id = %s AND m2.status = 'FT' AND m2.mst_utc < %s)) / 86400), 7) as a_rest,
COALESCE((SELECT COUNT(*) FROM match_player_participation mp WHERE mp.match_id = %s AND mp.team_id = %s AND mp.is_starting = true), 11) as h_xi,
COALESCE((SELECT COUNT(*) FROM match_player_participation mp WHERE mp.match_id = %s AND mp.team_id = %s AND mp.is_starting = true), 11) as a_xi,
COALESCE((SELECT COUNT(*) FILTER (WHERE m2.score_home > m2.score_away)::float / NULLIF(COUNT(*), 0) FROM matches m2 WHERE m2.home_team_id = %s AND m2.away_team_id = m2.away_team_id AND m2.status = 'FT' AND m2.mst_utc < %s), 0.5) as h2h_h_wr,
COALESCE((SELECT SUM(pts) FROM (SELECT CASE WHEN m2.score_home > m2.score_away THEN 3 WHEN m2.score_home = m2.score_away THEN 1 ELSE 0 END as pts FROM matches m2 WHERE m2.home_team_id = %s AND m2.status = 'FT' AND m2.mst_utc < %s ORDER BY m2.mst_utc DESC LIMIT 5) sub), 0) as h_form_pts,
COALESCE((SELECT SUM(pts) FROM (SELECT CASE WHEN m2.score_away > m2.score_home THEN 3 WHEN m2.score_away = m2.score_home THEN 1 ELSE 0 END as pts FROM matches m2 WHERE m2.away_team_id = %s AND m2.status = 'FT' AND m2.mst_utc < %s ORDER BY m2.mst_utc DESC LIMIT 5) sub), 0) as a_form_pts
""", (
row['home_team_id'], row['mst_utc'],
row['away_team_id'], row['mst_utc'],
row['mst_utc'], row['home_team_id'], row['mst_utc'],
row['mst_utc'], row['away_team_id'], row['mst_utc'],
match_id, row['home_team_id'],
match_id, row['away_team_id'],
row['home_team_id'], row['away_team_id'], row['mst_utc'],
row['home_team_id'], row['mst_utc'],
row['away_team_id'], row['mst_utc']
))
stats = cur.fetchone()
h_elo = float(row['home_elo'] or 1500)
a_elo = float(row['away_elo'] or 1500)
h_home_goals = float(stats['h_home_goals'] or 1.2)
a_away_goals = float(stats['a_away_goals'] or 1.2)
h_rest = float(stats['h_rest'] or 7)
a_rest = float(stats['a_rest'] or 7)
h_xi = float(stats['h_xi'] or 11)
a_xi = float(stats['a_xi'] or 11)
h2h_h_wr = float(stats['h2h_h_wr'] or 0.5)
h_pts = float(stats['h_form_pts'] or 0)
a_pts = float(stats['a_form_pts'] or 0)
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
margin = (1/odds_dict['ms_h']) + (1/odds_dict['ms_d']) + (1/odds_dict['ms_a'])
features = pd.DataFrame([{
'elo_diff': h_elo - a_elo,
'h_xg': h_xg, 'a_xg': a_xg,
'total_xg': h_xg + a_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/odds_dict['ms_h'])/margin,
'imp_d': (1/odds_dict['ms_d'])/margin,
'imp_a': (1/odds_dict['ms_a'])/margin,
'h_xi': h_xi, 'a_xi': a_xi,
'h2h_h_wr': h2h_h_wr,
'form_diff': h_pts - a_pts
}])
# --- TAHMİNLER ---
ms_probs = model_ms.predict(features)[0]
p_over = float(model_ou.predict(features)[0])
p_btts = float(model_btts.predict(features)[0])
# --- EN İYİ VALUE PICK ---
picks = []
for pick, prob, odd in zip(['1', 'X', '2'], ms_probs, [odds_dict['ms_h'], odds_dict['ms_d'], odds_dict['ms_a']]):
edge = prob - (1/odd)
if edge > 0.05 and prob > 0.45:
picks.append({"market": "MS", "pick": pick, "prob": prob, "odds": odd})
if p_over > 0.55: picks.append({"market": "OU2.5", "pick": "Over", "prob": p_over, "odds": odds_dict.get('ou25_o', 1.85)})
if p_btts > 0.55: picks.append({"market": "BTTS", "pick": "Var", "prob": p_btts, "odds": odds_dict.get('btts_y', 1.85)})
picks.sort(key=lambda x: (x['prob'] + max(0, x['prob'] - 1/x['odds'])*100), reverse=True)
best_pick = picks[0] if picks else None
# --- SONUÇ KONTROLÜ ---
res_str = "⏳ Oynanıyor/Bekleniyor"
won = None
h_score = row['score_home']
a_score = row['score_away']
if is_finished and h_score is not None and a_score is not None:
res_str = f"🏁 SONUÇ: {h_score}-{a_score}"
if best_pick:
p = best_pick['pick']
if p == '1': won = h_score > a_score
elif p == 'X': won = h_score == a_score
elif p == '2': won = a_score > h_score
elif p == 'Over': won = (h_score + a_score) > 2.5
elif p == 'Var': won = h_score > 0 and a_score > 0
res_str += " | " + ("✅ KAZANDI" if won else "❌ KAYBETTİ")
if won: total_profit += (best_pick['odds'] - 1.0)
else: total_profit -= 1.0
total_bet += 1
if won: total_won += 1
# Çıktı
match_time = time.strftime("%H:%M", time.gmtime(row['mst_utc']/1000))
pick_info = f"{best_pick['market']} - {best_pick['pick']} (%{best_pick['prob']*100:.0f} @ {best_pick['odds']:.2f})" if best_pick else "💤 Önerilen Bahis Yok"
print(f"\n⚽ [{match_time}] {home} vs {away} ({league})")
print(f" 🧠 Tahmin: {pick_info}")
print(f" {res_str}")
print("\n" + "="*60)
print("📊 GÜNLÜK ÖZET")
print("="*60)
if total_bet > 0:
print(f"🎲 Oynanan Bahis: {total_bet}")
print(f"✅ Kazanan: {total_won}")
print(f"💰 Toplam Kâr: {total_profit:.2f} Units")
print(f"📈 ROI: {(total_profit/total_bet)*100:.1f}%")
else:
print("📝 Bugün için Value Bahis bulunamadı veya maçlar bitmedi.")
cur.close()
conn.close()
if __name__ == "__main__":
run_live_predictions()