Files
turf_saas/EVOLUTION_PREDICTIF.md
2026-04-25 17:18:43 +02:00

21 KiB

Évolution du Système Prédictif Turf

Historique des modifications - 25 Mars 2026 (suite)

25 Mars 2026 - Correction du titre du banner

Problème: Le banner de la course affichait uniquement "🏇 MARSEILLE Quinté+" au lieu du nom complet de la course.

Solution:

  • Modification de combined_api.py pour utiliser get_full_race_name() qui retourne le format complet: "R1 BORELY - 13:55 GRAND NATIONAL DU TROT"
  • Mise à jour du dashboard pour afficher le nom complet dans le banner
  • Ajustement CSS pour permettre l'affichage du nom complet sans troncature
  • Ajout du favicon avec le logo H3R7Tech

Résultat: Le banner affiche maintenant "R1 BORELY - 13:55 GRAND NATIONAL DU TROT" avec le type de course "🏇 Quinté+"

Fichiers modifiés:

  • combined_api.py - Utilisation de get_full_race_name() dans l'API
  • dashboard.html - Affichage du nom complet dans le banner

25 Mars 2026 - Résultats groupés par course

Problème: L'onglet Résultats affichait les positions 1-5 pour chaque course sans séparation, ce qui était incohérent.

Solution:

  • Modification de l'API pour inclure race_label (ex: "R1 BORELY") et race_type (ex: "GRAND NATIONAL DU TROT") dans les résultats
  • Mise à jour du dashboard pour grouper les résultats par course et afficher un en-tête pour chaque course

Résultat: Les résultats affichent maintenant chaque course séparément:

  • R1 BORELY - GRAND NATIONAL DU TROT
  • R2 CAEN - PRIX D'ACQUEVILLE

Fichiers modifiés:

  • combined_api.py - Ajout des infos de course dans les résultats
  • dashboard.html - Groupement et affichage par course

Historique des modifications - 25 Mars 2026


1. Analyse de la Base de Données

Tables principales et volumes

Table Lignes Description
historical_data 5 536 Données historiques des courses
pmu_courses 3 146 Courses PMU
pmu_reunions 480 Réunions hippiques
predictions 739 Prédictions effectuées
scoring 123 Scores calculés par cheval
results 68 Résultats des courses
performance 96 Performance prédictions vs réels
recommendations 32 Recommandations de paris
weather 4 Données météo

Métriques de performance (avant ML)

Métrique Valeur
Taux de réussite global 20.83%
Précision favori (rang 1) 42.86%
Précision top 3 50%
Résultats remplis (recos) 0/32

2. Améliorations Effectuées

2.1 Court Terme

Script de mise à jour des résultats

  • Fichier: update_recommendation_results.py
  • Fonction: Compare les recommandations avec les résultats réels
  • Résultat: 20 recommandations mises à jour (6 GAGNE, 14 PERDU)
  • Taux de réussite: 30%

Analyse du rang 0

  • Cause: canalturf_partants (356 prédictions) et canalturf_selections (165) ont rank 0 par défaut
  • Solution: Seuls les ranks 1/2/3 constituent les vraies prédictions

2.2 Moyen Terme

Entraînement XGBoost

  • Fichier: train_xgboost.py
  • Données: 4 902 lignes de historical_data
  • Features: 35 features (cote, forme, performances, etc.)
Modèle CV AUC Amélioration vs random
Top 1 (gagnant) 0.697 +19.7%
Top 3 (placé) 0.715 +21.5%

Top Features (par importance):

  1. cote_directe - La cote est le predictor le plus important
  2. rang_cote - Classement par cote
  3. implied_prob - Probabilité implicite (1/cote)
  4. ratio_cote_field - Ratio cote vs moyenne du field
  5. tx_victoire - Taux de victoire historique
  6. forme_recente - Forme récente du cheval

Fichiers générés:

  • xgboost_models.pkl - Modèles entraînés
  • feature_importance_top1.csv
  • feature_importance_top3.csv

2.3 Intégration Dashboard

Nouvel onglet "Prédictions ML"

  • Fichier: dashboard.html
  • Endpoint: /turf/api/ml_predictions
  • Données affichées:
    • Probabilité Top 1 (%)
    • Probabilité Top 3 (%)
    • Score ML composite
    • Conseil (TOP1 / TOP3 / PASS)

Intégration vitesse

  • Fichier: combined_api.py
  • Endpoint: /turf/api/vitesse
  • Calcul: Moyenne du temps_obtenu dans historical_data
  • Affichage: Format mm:ss avec nombre de courses

3. Architecture Actuelle

┌─────────────────────────────────────────────────────────┐
│                     PORTAL DUCKDNS                       │
│              https://portal-kolifee.duckdns.org          │
│                    (Auth: h3r7 / ****)                  │
└─────────────────────┬───────────────────────────────────┘
                      │
        ┌─────────────┴─────────────┐
        │                           │
   Port 8765                   Port 9999
        │                           │
┌───────▼────────┐          ┌───────▼────────┐
│ combined_api  │          │ vitesse_api     │
│ - /turf/api   │          │ - /api/vitesse  │
│ - ML预测       │          │ (obsolète)      │
│ - Vitesse     │          └──────────────────┘
│ - Scoring     │
└───────────────┘
        │
        ▼
┌───────────────────────────────────┐
│           turf.db                  │
│  - predictions                    │
│  - historical_data (4 902 lignes) │
│  - scoring                        │
│  - results                        │
│  - recommendations                │
└───────────────────────────────────┘

4. Améliorations à Venir

4.1 Priorité Haute

🔴 Comparaison Prédictions vs Résultats Réels

  • Problème: Seulement 96 prédictions evaluées avec résultats
  • Solution:
    • Automatiser le remplissage des résultats dans performance table
    • Créer script backtest.py qui compare prédictions ML vs réels
    • Calculer ROI par type de pari (simple gagnant, place, couplé)
  • Métriques à suivre:
    • Précision par rang (base 1, chance 2, outsider 3)
    • ROI par type de pari
    • Evolution de la précision dans le temps

🔴 Ajouter plus de données historiques

  • Problème: 4 902 lignes, seulement 364 jours
  • Solution: Améliorer improve_historical_data.py pour charger plus de dates
  • Objectif: 20 000+ lignes pour meilleur entraînement
  • API à utiliser: PMU API (https://turfinfo.api.pmu.fr)

🔴 Intégration météo

  • Problème: Table weather n'a que 4 lignes
  • Solution: Scraping météo quotidien + impact sur prédictions
  • Impact: Ajustement selon conditions (pluie, vent, température)
  • Sources: weather.com, openweathermap.org

🔴 Système de "Value Bets"

  • Problème: Pas de comparaison cote PMU vs cote "juste"
  • Solution: Estimer cote juste avec le modèle ML, parier si valeur > seuil
  • Formule: value = (cote_PMU - cote_juste) / cote_juste
  • Seuil: Parier si value > 10%

4.2 Priorité Moyenne

🟡 Scraping de Sources Hippiques Externes

  • Problèmes identifiés:
    • Canalturf: prédictions basiques
    • Pas d'avis externes intégrés
  • Sources à scraper:
    • Equidia: Pronostics experts, commentaires
    • Paris-Turf: Analyses courses, tiércé
    • Zeturf: Pronostics communautaire
    • LeTrot: Spécifique trot attelé
  • Données à récupérer:
    • Avis des experts (auteur, confiance, commentaire)
    • Cotes de référence (moyenne de plusieurs sources)
    • Statistiques jockeys/entraineurs

🟡 Backtest complet

  • Problème: Seulement 96 prédictions evaluées
  • Solution: Automatiser le backtest sur toutes les recommandations
  • Objectif: ROI réel du modèle
  • Métriques:
    - ROI = (gains - mises) / mises
    - Yield = gains_esperés / mises
    - Hit Rate = paris_gagnés / total_paris
    - CLV = Cote_Moyenne - Cote_Fermee
    

🟡 Amélioration du scoring

  • Problème: Formule actuelle pondérée manuellement
  • Solution: Utiliser les weights XGBoost pour pondérer le scoring
  • Impact: Précisions bases: 42.86% → 50%+

🟡 Modèles multi-cibles

  • Solution: Entraîner modèles séparés pour:
    • model_quinte - top5 (pour couplés, tiercé, quinté)
    • model_turf - Discipline spécifique (trot vs plat)
    • model_distance - Performance par catégorie de distance
    • model_hippodrome - Performance par hippodrome

🟡 Intégration des performances jockeys/entraineurs

  • Données manquantes:
    • Taux de victoire du jockey
    • Taux de réussite de l'entraineur
    • Combinaison cheval/jockey historique
  • Solution: Ajouter tables jockeys et entraineurs
  • Impact: +5-10% de précision

4.3 Priorité Basse

🟢 Interface admin

  • Solution: Page pour gérer les prédictions, voir stats
  • Fonction:
    • Activer/désactiver scrapers
    • Voir ROI en temps réel
    • Historique des prédictions
    • Configuration des seuils

🟢 Alertes Telegram/Discord

  • Solution: Notification quand prediction forte (prob > 50%)
  • Impact: Réactivité augmentée
  • Format:
    • Cheval recommandé
    • Cote actuelle
    • Probabilité ML
    • Mise suggérée

🟢 Dashboards analytiques

  • Solution: Graphiques d'évolution
  • Métriques:
    • Précision vs temps
    • ROI vs temps
    • Meilleurs/wpires chevaux
    • Meilleurs/wpires jockeys

5. Scraping de Sources Externes

5.1 Sites à Intégrer

Site Données Difficulté Priorité
Equidia Pronostics experts Moyenne Haute
Paris-Turf Analyses courses Moyenne Haute
LeTrot Spécifique trot Facile Moyenne
Zeturf Pronostics communauté Difficile Basse

5.2 Données à Récupérer

# Exemple de structure pour données externes
external_data = {
    "source": "equidia",
    "horse_name": "...",
    "expert_name": "...",
    "expert_confidence": 0-100,
    "comment": "Texte de l'analyse",
    "cote_recommandee": 0.0,
    "date": "YYYY-MM-DD"
}

5.3 Intégration dans le modèle

  1. NLP sur les commentaires:

    • Sentiment: POSITIF / NEUTRE / NEGATIF
    • Mots-clés: формы,腿部, qualité, etc.
    • Score basé sur le texte
  2. Fusion des sources:

    score_final = 
        0.4 * score_ML 
      + 0.3 * score_Canalturf 
      + 0.2 * score_Equidia 
      + 0.1 * score_cote
    

6. Métriques de Performance à Suivre

6.1 Métriques Quotidiennes

Métrique Description Cible
precision_bases % bases correctes > 45%
precision_chances % chances correctes > 30%
precision_outsiders % outsiders corrects > 15%
nb_predictions Nombre de prédictions > 20

6.2 Métriques Hebdomadaires

Métrique Description Cible
roi_simple_gagnant ROI paris gagnant > 5%
roi_simple_place ROI paris placé > 10%
avg_cote Cote moyenne recommandée -
value_bets % de value bets trouvés > 20%

6.3 Métriques Mensuelles

Métrique Description Cible
roi_global ROI global > 10%
evolution Evolution vs mois précédent positive
meilleur_cheval Cheval le plus profitable -
pire_cheval Cheval le moins profitable -

7. Structure de Données Suggérée

7.1 Nouvelle Table: expert_predictions

CREATE TABLE expert_predictions (
    id INTEGER PRIMARY KEY,
    date TEXT NOT NULL,
    source TEXT NOT NULL,  -- 'equidia', 'paris_turf', etc.
    expert_name TEXT,
    horse_name TEXT NOT NULL,
    horse_number INTEGER,
    race_name TEXT,
    confidence INTEGER,  -- 0-100
    sentiment TEXT,  -- 'POSITIF', 'NEUTRE', 'NEGATIF'
    comment TEXT,
    recommended_odds REAL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

7.2 Nouvelle Table: backtest_results

CREATE TABLE backtest_results (
    id INTEGER PRIMARY KEY,
    date TEXT NOT NULL,
    race_name TEXT,
    horse_name TEXT,
    type_pari TEXT,  -- 'simple_gagnant', 'simple_place', 'couple'
    mise REAL,
    Cote REAL,
    Resultat TEXT,  -- 'GAGNE', 'PERDU'
    Gain REAL,
    prob_predite REAL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

7.3 Nouvelle Table: jockeys

CREATE TABLE jockeys (
    id INTEGER PRIMARY KEY,
    name TEXT UNIQUE NOT NULL,
    total_races INTEGER,
    victories INTEGER,
    places INTEGER,
    taux_victoire REAL,
    taux_place REAL,
    last_updated TIMESTAMP
);

8. Plan d'Action Détaillé

Phase 1: Amélioration Données (Semaine 1-2)

  • Augmenter historical_data à 10 000+ lignes
  • Remplir quotidiennement les résultats
  • Créer script backtest automatique
  • Tableau de bord métriques

Phase 2: Intégration Sources (Semaine 3-4)

  • Intégrer Equidia API/scraping
  • Ajouter analyse sentiment des commentaires
  • Fusionner scores multi-sources

Phase 3: Optimisation ML (Semaine 5-6)

  • Réentraîner avec nouvelles features
  • Modèles par discipline
  • Système de value bets

Phase 4: Production (Semaine 7-8)

  • Déploiement nouveau modèle
  • Alertes Telegram
  • Interface admin

4.4 Implémenté

Tables de données analytiques (25 Mars 2026)

Tables créées dans turf.db:

Table Description Colonnes clés
bet_results Historique des paris date, race_name, type_pari, horse_name, cote, mise, resultat, gain
daily_stats Stats quotidiennes date, total_bets, bets_gagne, mise_totale, gain_total, precision_pct, roi_pct
stats_by_type Stats par type de pari date, type_pari, total_bets, gagne, mise, gain, roi
expert_predictions Prédictions externes date, source, expert_name, horse_name, confidence, sentiment, comment

Scripts:

  • populate_analytics.py - Remplit les tables depuis recommendations
  • update_recommendation_results.py - Met à jour les résultats des paris

API endpoints:

  • /api/backtest - Lit depuis bet_results et stats_by_type
  • /api/stats - Lit depuis daily_stats

5. Commandes Utiles

cd /home/h3r7/turf_scraper

# ===== DONNÉES & PRÉDICTIONS =====

# Mettre à jour les résultats des recommandations
python3 update_recommendation_results.py

# Réentraîner le modèle ML
python3 train_xgboost.py

# ===== ANALYTICS =====

# Remplir les tables analytiques (à exécuter après mise à jour résultats)
python3 populate_analytics.py

# ===== API =====

# Redémarrer l'API
pkill -f combined_api
python3 combined_api.py

# Vérifier les logs
tail -f /tmp/combined.log

# ===== BASE DE DONNÉES =====

# Voir les tables analytiques
sqlite3 turf.db "SELECT * FROM daily_stats LIMIT 5;"
sqlite3 turf.db "SELECT * FROM bet_results LIMIT 5;"
sqlite3 turf.db "SELECT * FROM stats_by_type;"

# Statistiques globales
sqlite3 turf.db "SELECT SUM(total_bets) as total, SUM(gain_total) as gains, SUM(mise_totale) as mises FROM daily_stats;"

6. Fichiers Clés

Fichier Description
combined_api.py API principale (port 8765)
dashboard.html Interface frontend avec onglets
train_xgboost.py Entraînement ML XGBoost
update_recommendation_results.py Mise à jour résultats paris
populate_analytics.py Remplit tables analytiques
backtest.py Script de calcul du backtest
fetch_results.py Récupération résultats 1h après course
xgboost_models.pkl Modèles ML entraînés
PREDICTION_MODEL_ANALYSIS.md Analyse détaillée du modèle
EVOLUTION_PREDICTIF.md Ce document

9. Résultats Automatiques

9.1 Source des données

Les résultats sont récupérés depuis l'API PMU (pmu_results.py) et stockés dans:

  • pmu_partants - données des partants avec ordre d'arrivée
  • pmu_courses - informations des courses

9.2 Récupération automatique

Le script fetch_results.py récupère les résultats:

  • Via pmu_results.py qui interroge l'API PMU
  • 自动每小时 ou à 14h (après les courses)
  • Mode scheduler: python fetch_results.py
  • Mode unique: python fetch_results.py --once

9.3 Affichage dashboard

L'API affiche automatiquement les résultats:

# Query: top 5 de chaque course française (course 1)
SELECT pp.nom, pp.ordre_arrivee, pp.cote_direct
FROM pmu_partants pp
JOIN pmu_reunions pr ON ...
WHERE pays_code='FRA' AND num_course=1

13. Stratégie de Paris ZE5 (Focus B4/B3)

13.1 Objectif

Suite à l'analyse des rapports, le pari le plus rentable est le ZE5 avec objectif B4/B3 (trouver 4 ou 5 premiers).

13.2 Stratégies recommandées

Stratégie Description Mise conseillée Risque
ZE5 B4/B3 Bases + Chances + 1 Outsider 3€ Moyen
ZE5 Conservateur Top Favori + 2 Chances 3€ Faible
ZE5 Audacieux Base + 2 Outsiders 1€ Élevé

13.3 Logique

  • B5 (5/5) : ZE5 Ordre/Désordre - Jackpot!
  • B4 (4/5) : Rapport ~20-30€ pour 2€ (fréquent)
  • B3 (3/5) : Rapport ~5-10€ pour 2€ (très fréquent)

13.4 Implémentation API

def generate_ze5_recommendations(conn, today):
    # Récupérer prédictions: Bases + Chances + Outsiders
    # Générer combos optimisés pour B4/B3
    return {
        'ze5_b4b3': {...},
        'ze5_conservateur': {...},
        'ze5_audacieux': {...}
    }

13.5 Résultats du 25 Mars 2026

Pari Mise Résultat Gain
ZE5 B4/B3 3€ B3 (3/5) 12€
ZE5 Conservateur 3€ B3 (3/5) 12€
ZE5 Audacieux 1€ PERDU 0€

ROI: +242.9% 🎯


14. Suivi des Performances

14.1 Données sauvegardées

Les informations suivantes sont enregistrées dans la table recommendations:

Champ Description
date Date de la course
race_name Nom de la course
type_pari Type de pari (simple_gagnant, ze5_b4b3, etc.)
cheval1 Cheval(x) sélectionné(s)
numero1 Numéro du cheval
cote Cote du pari
mise Mise en euros
gain_potentiel Gain potentiel estimé
confiance Niveau de confiance (FORTE, BONNE, etc.)
justification Explication du choix
resultat Résultat (GAGNE, PERDU, B3, B4, B5)

14.2 Script de mise à jour

Le script update_recommendation_results.py:

  • Récupère les résultats depuis pmu_partants
  • Évalue chaque pari (ZE5: compte les matches dans top 5)
  • Met à jour le champ resultat

14.3 Calcul du ROI

SELECT 
    SUM(mise) as total_mise,
    SUM(CASE WHEN resultat='GAGNE' THEN mise * Cote 
             WHEN resultat='B3' THEN mise * 4
             WHEN resultat='B4' THEN mise * 10
             ELSE 0 END) as total_gain
FROM recommendations
WHERE date = '2026-03-25';

15. Règles de Sélection des Courses

15.1 Critères d'inclusion

Critère Description
Pays France uniquement (FR)
Données suffisantes Minimum 10 partants
Type de course Quinté, Trot, Plat, Toutes

15.2 Implémentation API

# Filtre France uniquement
france_condition = """
    EXISTS (
        SELECT 1 FROM pmu_reunions r 
        WHERE r.pays_code='FRA' 
        AND r.date_programme=date
        AND (r.hippodrome_long LIKE '%' || race_hippodrome || '%' 
             OR r.hippodrome_court LIKE '%' || race_hippodrome || '%'
             OR r.hippodrome_code LIKE '%' || race_hippodrome || '%')
    )
"""

# Minimum 10 partants
min_partants_condition = """
    (SELECT COUNT(*) FROM predictions p2 
     WHERE p2.race_name=predictions.race_name 
     AND p2.date=predictions.date 
     AND p2.source='canalturf_partants') >= 10
"""

12. Récupération des Résultats

12.1 Règle

Les résultats sont récupérés 1 heure après l'heure de départ de chaque course.

12.2 Données collectées

Donnée Description
Position Rang du cheval à l'arrivée
Cotes finales Rapports PMU officiels
Gains Gains potentiels par type de pari

12.3 Script fetch_results.py

import schedule
import time
from datetime import datetime, timedelta

def fetch_daily_results():
    """Récupère les résultats du jour à 14h (1h après dernière course)"""
    run_result_fetch()

schedule.every().day.at("14:00").do(fetch_daily_results)

while True:
    schedule.run_pending()
    time.sleep(60)

Document généré le 25 Mars 2026