Initial commit: existing turf_saas codebase

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
ML Engineer
2026-04-25 17:18:43 +02:00
commit ed07c8a3d1
137 changed files with 36398 additions and 0 deletions

View 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*