Initial commit: existing turf_saas codebase
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
360
PREDICTION_MODEL_ANALYSIS.md
Normal file
360
PREDICTION_MODEL_ANALYSIS.md
Normal file
@@ -0,0 +1,360 @@
|
||||
# Analyse du Modèle Prédictif Turf - Documentation Technique
|
||||
|
||||
## 1. Vue d'Ensemble du Système
|
||||
|
||||
### 1.1 Architecture Actuelle
|
||||
|
||||
Le système de prédiction turf repose sur plusieurs composants:
|
||||
|
||||
- **Collecte de données**: Scraping PMU (courses, cotes, résultats)
|
||||
- **Calcul de scoring**: Agrégation de multiples features par cheval
|
||||
- **Génération de recommandations**: Types de paris recommandés avec confiance
|
||||
- **Suivi de performance**: Comparaison prédictions vs résultats réels
|
||||
|
||||
### 1.2 Sources de Données
|
||||
|
||||
| Source | Tables | Description |
|
||||
|--------|--------|-------------|
|
||||
| Canalturf | `predictions`, `odds_history` | Cotes et prédictions externes |
|
||||
| PMU | `pmu_courses`, `pmu_reunions` | Courses et réunions officielles |
|
||||
| Interne | `scoring`, `recommendations` | Scores calculés et recommandations |
|
||||
|
||||
---
|
||||
|
||||
## 2. Analyse des Performances Actuelles
|
||||
|
||||
### 2.1 Métriques Globales
|
||||
|
||||
| Métrique | Valeur | Interprétation |
|
||||
|----------|--------|-----------------|
|
||||
| Total prédictions evaluées | 96 | Échantillon encore réduit |
|
||||
| Prédictions réussies (hit) | 20 | - |
|
||||
| **Taux de réussite global** | **20.83%** | En dessous du aléatoire (25% pour top 4) |
|
||||
| 1er prédit = 1er réel | 1 | 42.86% de précision pour le favori |
|
||||
| Chevaux dans le top 3 | 14 | 14.58% dans le top 3 |
|
||||
|
||||
### 2.2 Analyse par Rang Prédit
|
||||
|
||||
| Rang prédit | Total | Hits | Taux de réussite |
|
||||
|-------------|-------|------|-------------------|
|
||||
| 0 (non classé) | 69 | 9 | 13.04% |
|
||||
| 1 (favori) | 7 | 3 | **42.86%** |
|
||||
| 2 | 10 | 3 | 30.00% |
|
||||
| 3 | 10 | 5 | **50.00%** |
|
||||
|
||||
**Observations:**
|
||||
- Le rang 3 a le meilleur taux (50%) - possible sur-optimisation
|
||||
- Les favoris (rang 1) ont 42.86% de réussite
|
||||
- La catégorie "non classé" (rang 0) représente 71.8% des prédictions
|
||||
|
||||
### 2.3 Problemes Identifiés
|
||||
|
||||
1. **Volume insuffisant**: Seulement 96 prédictions evaluées
|
||||
2. **Catégorie 0 trop large**: 69 prédictions non classifiées
|
||||
3. **Pas de suivi des résultats**: Table `recommendations` n'avait pas de résultats (0/32) → **CORRIGÉ**
|
||||
4. **Déséquilibre des données**: Majorité de prédictions en rang 0
|
||||
|
||||
### 2.4 Analyse du Rang 0 (Résolu)
|
||||
|
||||
**Cause racine identifié:**
|
||||
- `canalturf_partants`: 356 prédictions (tous les partants, rank 0 par défaut)
|
||||
- `canalturf_selections`: 165 prédictions (sélections supplémentaires, rank 0)
|
||||
- `canalturf_prono_*`: 198 prédictions avec rank 1/2/3 (vraies prédictions)
|
||||
|
||||
**Solution:** Les prédictions avec rank 0 ne doivent PAS être incluses dans l'évaluation de performance.
|
||||
Seuls les ranks 1 (bases), 2 (chances), 3 (outsiders) constituent les vraie prédictions.
|
||||
|
||||
### 2.5 Résultats des Recommandations (Mise à jour)
|
||||
|
||||
Après mise à jour automatique:
|
||||
| Résultat | Count |
|
||||
|----------|-------|
|
||||
| GAGNE | 6 |
|
||||
| PERDU | 14 |
|
||||
|
||||
**Taux de réussite: 30%**
|
||||
**ROI: -70%** (à affiner avec analyse des cotes)
|
||||
|
||||
### 2.6 Modèle XGBoost - Résultats
|
||||
|
||||
Après entraînement sur 4 902 lignes de données historiques:
|
||||
|
||||
| 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` - Importance des features pour top1
|
||||
- `feature_importance_top3.csv` - Importance des features pour top3
|
||||
|
||||
---
|
||||
|
||||
## 3. Structure des Données
|
||||
|
||||
### 3.1 Tables Principales
|
||||
|
||||
#### `predictions` (739 lignes)
|
||||
```sql
|
||||
-- Prédictions brutes avant scoring
|
||||
date, race_name, race_hippodrome, race_time,
|
||||
horse_number, horse_name, odds, prediction_rank, source
|
||||
```
|
||||
|
||||
#### `scoring` (123 lignes)
|
||||
```sql
|
||||
-- Score composite calculé par cheval
|
||||
score = f(score_cote, score_forme, score_victoire, score_place,
|
||||
score_rk, score_tendance, score_avis)
|
||||
|
||||
-- Features individuelles:
|
||||
score_cote -- Score basé sur la cote
|
||||
score_forme -- Score basé sur la forme récente
|
||||
score_victoire -- Taux de victoire historique
|
||||
score_place -- Taux de placé historique
|
||||
score_rk -- Classement rank
|
||||
score_tendance -- Tendance de la cote
|
||||
score_avis -- Avis de l'entraîneur
|
||||
```
|
||||
|
||||
#### `historical_data` (5 536 lignes)
|
||||
```sql
|
||||
-- Données historiques enrichies
|
||||
date, hippodrome, distance, discipline, allocation
|
||||
horse_name, horse_number, driver, age, sexe
|
||||
musique, nb_courses, nb_victoires, nb_places
|
||||
gains_carriere, gains_annee, reduction_km
|
||||
avis_entraineur, oeilleres, deferre
|
||||
cote_directe, cote_reference, est_favori
|
||||
tx_victoire, tx_place, forme_recente, tendance_forme
|
||||
ordre_arrivee, top1, top3, top5 -- Variables cibles
|
||||
```
|
||||
|
||||
#### `recommendations` (32 lignes)
|
||||
```sql
|
||||
-- Recommandations de paris
|
||||
type_pari: simple_gagnant, simple_place, couple_gagnant, couple_place
|
||||
cheval1, numero1, cheval2, numero2
|
||||
cote, mise, gain_potentiel, confiance, justification
|
||||
```
|
||||
|
||||
### 3.2 Couverture des Données
|
||||
|
||||
| Métrique | Valeur |
|
||||
|----------|--------|
|
||||
| Période couverte | 2025-03-19 à 2026-03-18 |
|
||||
| Nombre de jours de courses | 364 |
|
||||
| Hippodromes différents | 45 |
|
||||
| Disciplines | 5 (PLAT, TROT, MONTE, HAIES, STEEPLE) |
|
||||
|
||||
---
|
||||
|
||||
## 4. Modèle de Scoring Actuel
|
||||
|
||||
### 4.1 Formule de Scoring
|
||||
|
||||
Le score composite est calculé selon:
|
||||
|
||||
```
|
||||
score = score_cote + score_forme + score_victoire + score_place
|
||||
+ score_rk + score_tendance + score_avis
|
||||
```
|
||||
|
||||
**Features utilisées:**
|
||||
- `score_cote`: Pondération inverse de la cote (plus petit = plus haut)
|
||||
- `score_forme`: Basé sur `forme_recente` (0-25 scale)
|
||||
- `score_victoire`: `tx_victoire` du cheval
|
||||
- `score_place`: `tx_place` du cheval
|
||||
- `score_rk`: Classement relatif dans la course
|
||||
- `score_tendance`: Variation de la cote
|
||||
- `score_avis`: Valeur textuelle convertie (POSITIF/NEUTRE/NEGATIF)
|
||||
|
||||
### 4.2 Limites du Modèle Actuel
|
||||
|
||||
1. **Pas depondération apprentissage**: Les poids sont-ils optimaux?
|
||||
2. **Features statiques**: Pas de features dynamiques (météo, forme vs竞争对手)
|
||||
3. **Pas de cross-validation**: Pas de validation robuste
|
||||
4. **Ignorer les correlations**: Interactions entre features non capturées
|
||||
5. **Pas de feature engineering**: Variables dérivées limitées
|
||||
|
||||
---
|
||||
|
||||
## 5. Améliorations Proposées
|
||||
|
||||
### 5.1 Court Terme (Quick Wins)
|
||||
|
||||
#### 5.1.1 Améliorer le Suivi des Résultats
|
||||
```python
|
||||
# Ajouter le remplissage automatique des résultats
|
||||
def update_recommendation_results():
|
||||
"""Récupérer les résultats officiels et mettre à jour recommendations"""
|
||||
# 1. Scraping des résultats PMU
|
||||
# 2. Matching avec recommandations
|
||||
# 3. Mise à jour du champ resultat
|
||||
```
|
||||
|
||||
#### 5.1.2 Réduire la Catégorie "Non Classé"
|
||||
- Analyser pourquoi 71.8% des prédictions ont `predicted_rank = 0`
|
||||
- Implémenter un seuil minimum de confiance
|
||||
|
||||
#### 5.1.3 Ajouter Plus de Prédictions
|
||||
- Automatiser le scraping quotidien
|
||||
- Cible: minimum 500 prédictions avant analyse
|
||||
|
||||
### 5.2 Moyen Terme (Amélioration du Modèle)
|
||||
|
||||
#### 5.2.1 Feature Engineering
|
||||
|
||||
**Nouvelles features à créer:**
|
||||
|
||||
```python
|
||||
# Features basées sur l'historique
|
||||
- forme_vs_favori = forme_recente / forme_favori_moyen
|
||||
- performance_par_distance = tx_victoire_par_distance[dist]
|
||||
- performance_par_discipline = tx_victoire_par_discipline[disc]
|
||||
- performance_par_hippodrome = tx_victoire_par_hippodrome[hippo]
|
||||
- forme_tendance = forme_3_der courses vs forme_10_dernières
|
||||
|
||||
# Features dynamiques
|
||||
- ecart_cote = cote_directe - cote_reference
|
||||
- momentum = indicateur_tendance * volume_paris
|
||||
- valeur = (cote - cote_juste_estimee) / cote_juste_estimee
|
||||
|
||||
# Features d'interaction
|
||||
- forme_x_cote = forme_recente * (1/cote)
|
||||
- age_x_performance = age * tx_victoire
|
||||
```
|
||||
|
||||
#### 5.2.2 Modèle de Machine Learning
|
||||
|
||||
**Approche recommandée: XGBoost avec validation croisée**
|
||||
|
||||
```python
|
||||
# Structure de données pour ML
|
||||
features_ml = [
|
||||
'tx_victoire', 'tx_place', 'forme_recente',
|
||||
'age', 'nb_courses', 'cote_directe',
|
||||
'distance', 'nb_partants', 'est_favori',
|
||||
'reduction_km', 'gains_annee'
|
||||
]
|
||||
|
||||
target_top1 = 'top1' # 1 si cheval gagné
|
||||
target_top3 = 'top3' # 1 si cheval placé top 3
|
||||
|
||||
# Pipeline ML
|
||||
1. Séparation train/test (80/20)
|
||||
2. Cross-validation 5-fold
|
||||
3. Hyperparameter tuning
|
||||
4. Feature importance analysis
|
||||
5. Backtest sur données historiques
|
||||
```
|
||||
|
||||
#### 5.2.3 pondérations Optimales
|
||||
|
||||
**Analyse des poids actuels vs optimaux:**
|
||||
|
||||
| Feature | Poids actuel | Importance suggèree |
|
||||
|---------|-------------|---------------------|
|
||||
| score_cote | 14.7 | Haute (mais non-linéaire) |
|
||||
| score_forme | 25.0 | Très haute |
|
||||
| score_victoire | 15.0 | Haute |
|
||||
| score_place | 15.0 | Moyenne |
|
||||
| score_rk | 7.0 | Basse |
|
||||
| score_tendance | 9.3 | Moyenne |
|
||||
| score_avis | 6.5 | Variable |
|
||||
|
||||
### 5.3 Long Terme (Système Avancé)
|
||||
|
||||
#### 5.3.1 Modèles Multi-Cibles
|
||||
|
||||
| Modèle | Cible | Type de pari |
|
||||
|--------|-------|--------------|
|
||||
| `model_top1` | top1 | Simple Gagnant |
|
||||
| `model_top3` | top3 | Simple Placé |
|
||||
| `model_quinte` | top5 | Couplé/Quinté |
|
||||
|
||||
#### 5.3.2 Système de Cotes Justes
|
||||
|
||||
```python
|
||||
# Estimer la cote "juste" vs cote PMU
|
||||
cote_juste = f(tx_victoire_model, tx_place_model, dispersion)
|
||||
|
||||
# Identifier les "value bets"
|
||||
value = cote_PMU - cote_juste
|
||||
if value > seuil:
|
||||
recommander_pari()
|
||||
```
|
||||
|
||||
#### 5.3.3 Intégration Météo (Non Implémentée)
|
||||
|
||||
La table `weather` existe mais contient seulement 4 lignes.
|
||||
|
||||
**À implémenter:**
|
||||
- Scraping météo quotidien
|
||||
- Impact sur performance (par course)
|
||||
- Ajustement des prédictions selon conditions
|
||||
|
||||
---
|
||||
|
||||
## 6. Plan d'Action
|
||||
|
||||
### Phase 1: Collecte de Données (Semaine 1-2)
|
||||
- [ ] Automatiser le scraping quotidien
|
||||
- [ ] Compléter le remplissage des résultats
|
||||
- [ ] Atteindre 500+ prédictions évaluées
|
||||
|
||||
### Phase 2: Analyse Exploratoire (Semaine 3)
|
||||
- [ ] Analyse univariée des features
|
||||
- [ ] Corrélations entre features
|
||||
- [ ] Identification des patterns
|
||||
|
||||
### Phase 3: Modèle ML (Semaine 4-6)
|
||||
- [ ] Feature engineering
|
||||
- [ ] Entraînement XGBoost
|
||||
- [ ] Validation croisée
|
||||
- [ ] Comparaison avec modèle actuel
|
||||
|
||||
### Phase 4: Production (Semaine 7-8)
|
||||
- [ ] Déploiement nouveau modèle
|
||||
- [ ] Monitoring des performances
|
||||
- [ ] Ajustements itératifs
|
||||
|
||||
---
|
||||
|
||||
## 7. KPIs à Suivre
|
||||
|
||||
| KPI | Cible Court Terme | Cible Long Terme |
|
||||
|-----|-------------------|-------------------|
|
||||
| Taux hit global | 25% | 35% |
|
||||
| Précision favori | 45% | 50% |
|
||||
| Précision top 3 | 40% | 55% |
|
||||
| ROI recommandations | 0% | 10%+ |
|
||||
| Volume predictions | 500+ | 2000+ |
|
||||
|
||||
---
|
||||
|
||||
## 8. Conclusion
|
||||
|
||||
Le système actuel montre des bases solides mais nécessite:
|
||||
1. **Plus de données** pour une analyse statistique robuste
|
||||
2. **Un suivi rigoureux** des résultats pour mesure de performance
|
||||
3. **Une évolution vers le ML** pour optimiser les pondérations
|
||||
|
||||
Les recommandations immédiates:
|
||||
1. Compléter le remplissage des résultats (0/32 actuellement)
|
||||
2. Augmenter le volume de prédictions
|
||||
3. Passer à un modèle XGBoost avec features enrichies
|
||||
|
||||
---
|
||||
|
||||
*Document généré le 2026-03-25*
|
||||
*Source: Analyse de turf.db - turf_scraper*
|
||||
Reference in New Issue
Block a user