136 lines
4.0 KiB
Python
Executable File
136 lines
4.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Turf Performance Tracker
|
|
Calculates REX after results are in
|
|
"""
|
|
import sqlite3
|
|
from datetime import datetime, timedelta
|
|
import requests
|
|
from bs4 import BeautifulSoup
|
|
import re
|
|
|
|
DB_PATH = "/home/h3r7/turf_scraper/turf.db"
|
|
|
|
HEADERS = {
|
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
|
|
}
|
|
|
|
def get_yesterday_results():
|
|
"""Scrape yesterday's results from Zone-Turf"""
|
|
url = "https://www.zone-turf.fr/rapports/"
|
|
try:
|
|
r = requests.get(url, headers=HEADERS, timeout=15)
|
|
soup = BeautifulSoup(r.text, 'html.parser')
|
|
# Extract results - simplified
|
|
return []
|
|
except:
|
|
return []
|
|
|
|
def calculate_performance():
|
|
"""Calculate performance from predictions vs results"""
|
|
conn = sqlite3.connect(DB_PATH)
|
|
c = conn.cursor()
|
|
|
|
# Get predictions without performance
|
|
c.execute('''
|
|
SELECT p.id, p.date, p.race_name, p.horse_name, p.prediction_rank, r.position
|
|
FROM predictions p
|
|
LEFT JOIN results r ON p.date = r.date AND p.horse_name = r.horse_name
|
|
WHERE p.date >= date('now', '-7 days')
|
|
AND p.id NOT IN (SELECT id FROM performance)
|
|
''')
|
|
|
|
pending = c.fetchall()
|
|
|
|
added = 0
|
|
for row in pending:
|
|
pred_id, date, race, horse, pred_rank, actual_pos = row
|
|
|
|
if actual_pos:
|
|
hit = (pred_rank == actual_pos)
|
|
c.execute('''
|
|
INSERT INTO performance (prediction_date, race_date, horse_name, predicted_rank, actual_position, hit)
|
|
VALUES (?, ?, ?, ?, ?, ?)
|
|
''', (date, date, horse, pred_rank, actual_pos, hit))
|
|
added += 1
|
|
|
|
conn.commit()
|
|
|
|
# Get overall stats
|
|
c.execute('''
|
|
SELECT
|
|
COUNT(*) as total,
|
|
SUM(CASE WHEN hit = 1 THEN 1 ELSE 0 END) as hits,
|
|
ROUND(CAST(SUM(CASE WHEN hit = 1 THEN 1 ELSE 0 END) AS FLOAT) / COUNT(*) * 100, 1) as hit_rate
|
|
FROM performance
|
|
''')
|
|
stats = c.fetchone()
|
|
|
|
conn.close()
|
|
|
|
return added, stats
|
|
|
|
def main():
|
|
print("="*50)
|
|
print("TURF PERFORMANCE TRACKER")
|
|
print("="*50)
|
|
|
|
# First, try to get results from Zone-Turf
|
|
print("\n1. Scraping results...")
|
|
results = get_yesterday_results()
|
|
print(f" Found {len(results)} results")
|
|
|
|
# Calculate performance
|
|
print("\n2. Calculating performance...")
|
|
added, stats = calculate_performance()
|
|
|
|
print(f"\n📊 REX:")
|
|
print(f" Total predictions: {stats[0]}")
|
|
print(f" Hits: {stats[1]}")
|
|
print(f" Hit rate: {stats[2]}%")
|
|
|
|
if stats[0] > 0:
|
|
# Calculate ROI (simplified)
|
|
print(f"\n💰 ROI Analysis:")
|
|
|
|
conn = sqlite3.connect(DB_PATH)
|
|
c = conn.cursor()
|
|
|
|
# Get predictions with results
|
|
c.execute('''
|
|
SELECT p.horse_name, p.odds, p.prediction_rank, r.position, r.odds
|
|
FROM predictions p
|
|
JOIN results r ON p.date = r.date AND p.horse_name = r.horse_name
|
|
WHERE p.prediction_rank <= 3
|
|
''')
|
|
|
|
total_stake = 0
|
|
total_return = 0
|
|
|
|
for row in c.fetchall():
|
|
horse, pred_odds, pred_rank, actual_pos, result_odds = row
|
|
stake = 2 # 2 euros per bet
|
|
total_stake += stake
|
|
|
|
# If placed (top 5), win money
|
|
if actual_pos and actual_pos <= 5:
|
|
# Simple placed bet calculation
|
|
if actual_pos == 1:
|
|
total_return += stake * (result_odds - 1)
|
|
else:
|
|
total_return += stake * 0.5 # Placed usually pays ~1.5x
|
|
else:
|
|
total_return -= stake
|
|
|
|
roi = ((total_return / total_stake) * 100) if total_stake > 0 else 0
|
|
print(f" Stake: {total_stake}")
|
|
print(f" Return: {total_return:.2f}")
|
|
print(f" ROI: {roi:.1f}%")
|
|
|
|
conn.close()
|
|
|
|
print("\n" + "="*50)
|
|
|
|
if __name__ == "__main__":
|
|
main()
|