Correction du fallback CSV silencieux — Restauration de la fiabilité des données
Billet #139 : Repli CSV silencieux causant des prix portefeuille figés
Type : Débogage / Correction / Intégrité des données
Composants concernés : code_source_simule/pipeline.py, tests/test_pipeline.py, base de données (table historique)
1. Contexte et Symptômes
Les prix du portefeuille dans l'interface sont restés figés à leurs valeurs CSV initiales pendant plus de 5 jours consécutifs (23–27 mars 2026), malgré la disponibilité de données marché en direct. Par exemple, la cad_value de VWAGY est restée à 14.85 CAD sur toutes les dates observées.
2. Processus d'Investigation
Une requête de base de données a confirmé les valeurs figées :
SELECT ticker, date_releve, valeur, cad_value FROM historique
WHERE ticker_id = (SELECT id FROM titres WHERE ticker = 'VWAGY')
ORDER BY date_releve DESC LIMIT 5;
valeur = 10.61 USD et cad_value = 14.85 CAD identiques du 23 au 27 mars.
Corrélation mathématique : Le CSV contient VWAGY Price = 10.61 USD. Avec usd_to_cad_rate = 1.40 dans config.ini, on obtient 10.61 × 1.40 = 14.854 CAD, exactement la valeur figée observée.
Disponibilité API : Un test manuel Marketstack sur la même période a confirmé que les données existaient (ex. close = 10.08 pour le 27 mars 2026). Le problème n'était donc pas l'absence de données API, mais leur non-acheminement en base.
Cause opérationnelle : Le cron tourne à 05:03 UTC (au lieu de 21:05 UTC). À cette heure, les données EOD du jour ne sont généralement pas encore publiées, donc l'API peut répondre {"data": []}. Le pipeline substituait alors silencieusement ces absences par les prix CSV.
3. Causes Racines Identifiées
| # | Cause | Impact | Statut |
|---|---|---|---|
| 1 | Cron décalé de 16 h (05:03 UTC vs 21:05 UTC) |
Données EOD indisponibles au moment du run | Hors scope code — correction VPS requise |
| 2 | Repli CSV silencieux dans enrich_data_with_marketstack() |
Remplace des prix API manquants par CSV sans signalement | Corrigé |
| 3 | Absence d'alerte opérateur | Incident invisible côté exploitation | Corrigé — alerte courriel ajoutée |
4. Solutions Implantées
4.1 - Suppression du repli CSV
Retrait de la logique qui remplaçait silencieusement les prix API manquants par les prix CSV :
# AVANT (bug)
df['market_price'].fillna(df['price'], inplace=True)
# APRÈS (corrigé)
# Pas de repli — les absences API restent NaN
df['market_price'] = df['marketstack_ticker'].map(all_prices)
missing = df[df['market_price'].isna()]['marketstack_ticker'].dropna().tolist()
if missing:
print(f"AVERTISSEMENT: {len(missing)} ticker(s) sans prix API...")
4.2 - Ajout d'une alerte courriel
Implémentation de send_alert_email() pour notifier l'opérateur quand des tickers n'ont pas de prix API. Configuration .env requise :
- SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASSWORD
- ALERT_EMAIL_TO
Si SMTP n'est pas configuré, un avertissement explicite est journalisé.
4.3 - Blocage d'insertion en cas de prix manquant
Mise à jour de insert_data() pour ignorer tout ticker sans prix API valide :
4.4 - Verrouillage par test de non-régression
Ajout du test test_pipeline_does_not_fallback_to_csv_when_api_key_exists (tc-pipe-nocsv01) :
- Given : CSV avec prix + clé API + API vide
- Then : aucune insertion dans historique
- Statut : test passant ✓
5. Nettoyage des Données
Purge de l'historique à partir du 20 janvier 2026 pour éliminer les enregistrements produits sous logique défectueuse :
Résultat : 11 977 lignes supprimées
Justification : ces lignes contiennent des prix CSV injectés à la place de prix marché.
6. Vérification et Résultat
- Tests locaux : 11/11 passent (incluant
tc-pipe-nocsv01). - Cohérence données : disponibilité API confirmée manuellement ; insertion corrigée validée.
- Prévention du repli : comportement verrouillé par test automatique.
7. Synchronisation de la Documentation (EN/FR)
Dans la clôture de ce correctif, la documentation a été relue et synchronisée dans les deux langues :
- Alignement de la logique temporelle avec le comportement réellement exécuté.
- Mise à jour de la description pipeline (absence de repli CSV, contournement des prix API manquants, chemin d'alerte opérateur).
- Mise à jour des recommandations cron (exécution post-clôture).
- Mise à jour de la documentation tests (ajout tc-pipe-nocsv01 + liens vers le rapport d'activité).
8. Dépendances et Prochaines Étapes
Immédiat (action VPS manuelle) :
- Corriger le cron :
03 05 * * 1-5→05 21 * * 1-5 - Configurer les variables SMTP dans
.envpour l'alerte courriel
Suite :
- Revoir la logique d'import (date cible, fréquence) via Speckit
- Définir un seuil de complétude (ex. alerte si <95% des tickers ont un prix API)