Affichage natif par devise et scission des totaux du portefeuille
Billet #337 : Affichage natif par devise et scission des totaux du portefeuille
Type : Implémentation fonctionnelle / Correction de logique métier / Validation production
Composants concernés : code_source_simule/pipeline.py, code_source_simule/flask_app.py, templates/index.html, templates/titre_detail.html, templates/dashboard.html, templates/demo_index.html, tests/test_pipeline.py, tests/test_dashboard.py, tests/test_titre_detail.py, tests/test_demo.py, config.ini, logs/fx_rate_state.json
1. Contexte et symptômes
La présente intervention marque une inversion nette de la logique documentée dans docs/fr/features/chapter2.md, où la conversion de devises était présentée comme une règle systématique fondée sur Marketstack_Currency et le taux usd_to_cad_rate du fichier config.ini. On y renonce aujourd’hui parce que cette approche brouille la source de vérité des seuils 52 semaines et transforme plus de valeurs que la règle métier n’en autorise : la conversion n’est légitime que pour le prix courant, et seulement dans les cas de devise divergente.
Le portefeuille contenait des titres canadiens et américains, mais l’application affichait les montants avec une logique de devise incohérente selon les écrans. Le défaut central était que certaines valeurs étaient converties ou réinterprétées de façon ambigüe, voire erronée, alors que la règle métier attendue était plus stricte :
- le prix courant d’un titre doit rester affiché dans sa devise native lorsque cela est possible ;
- la conversion USD→CAD ne doit intervenir que pour le prix courant concerné dans les cas de devises divergentes ;
- les seuils 52 semaines affichés doivent rester identiques aux chiffres source du CSV, sans conversion artificielle ;
- le tableau de bord doit distinguer les totaux CAD, USD et portefeuille consolidé en CAD.
Cette ambiguïté provoquait des résultats trompeurs : des seuils historiques semblaient être convertis, les totaux du portefeuille étaient mal répartis par devise, et la présentation des titres ne reflétait pas leur devise réelle d’origine.
2. Objectif
Corriger le comportement métier de manière robuste et vérifiable, tout en gardant une logique de production compatible avec un quota API limité :
- afficher chaque titre dans sa devise native sur les pages principales ;
- scinder les totaux du portefeuille en CAD, USD et consolidation CAD ;
- conserver les seuils 52 semaines strictement constants par rapport au fichier source ;
- éviter les appels inutiles au service de taux de change en réutilisant un état local fiable.
3. Solution implémentée
3.1 — Source de vérité unique pour la devise de portefeuille
Le pipeline a été aligné sur une règle cohérente : si le ticker commence par TSE:, la devise de portefeuille est CAD; sinon, elle est USD. Cette logique est désormais utilisée de manière explicite lors de l’import et du rendu applicatif, sans dépendre de la devise brute détectée chez le fournisseur.
3.2 — Conversion ciblée et limitée au prix courant
Le comportement d’import a été ajusté pour convertir uniquement le prix de marché quand la devise source du ticker diffère de la devise du fournisseur et qu’un taux de change est disponible. Les valeurs de seuil 52 semaines restent stockées comme données brutes, sans recalcul ni conversion indirecte.
3.3 — Gestion robuste du taux de change
Le taux USD→CAD est maintenant récupéré selon une logique fail-open :
- on essaie le taux actualisé lorsque pertinent ;
- sinon, on réutilise le dernier taux connu enregistré localement ;
- en dernier recours, on applique la valeur sauvegardée dans
config.ini; - un état opérationnel est persistant dans
logs/fx_rate_state.jsonpour éviter les appels inutiles et rendre le comportement explicite au sein du système.
Cette approche respecte la contrainte de quota API et stabilise le comportement même en production lorsque l’API est indisponible.
3.4 — Tableaux de bord alignés sur la réalité métier
La vue dashboard affiche désormais trois totaux distincts :
- total CAD ;
- total USD ;
- portefeuille consolidé en CAD ;
- taux du jour avec date de récupération.
Les gabarits de consultation (index, titre_detail, dashboard, demo_index) ont été adaptés pour afficher les libellés explicites C$ et $ US selon la devise native du titre.
3.5 — Contrôle de non-régression sur les seuils 52 semaines
Les pages de détails et les vues de démonstration ont été corrigées pour lire les seuils an_haut et an_bas bruts, sans référence aux colonnes de conversion CAD. La même règle a été appliquée au mode démo pour conserver une cohérence totale entre le mode public et le mode réel.
4. Tests et validation
La suite a été revue et renforcée sur les points métier critiques :
- résolution de la devise par préfixe
TSE:; - conversion ciblée uniquement pour les titres en devise divergente ;
- non-conversion des seuils 52 semaines bruts ;
- repli FX avec taux connu puis valeur de secours ;
- journalisation explicite des événements de taux de change ;
- cohérence du mode démo avec le mode réel.
Validation finale exécutée :
- suite complète : 259 tests réussis ;
- avertissements : 3 (warnings de pandas/pyarrow et de parsing de lignes corrompues dans la fixture de test) ;
- couverture du code applicatif (
code_source_simule/*) : 82,37 % ; - artefacts régénérés :
coverage.xml,docs/reports/report.xml,docs/reports/report.jsonl.
5. Validation et résultat
Le correctif a permis de remettre la logique métier en cohérence avec la règle de décision validée par le produit :
- affichage natif par devise restauré ;
- totaux du portefeuille correctement scindés ;
- seuils 52 semaines fidèles à la source ;
- mécanisme de taux de change robuste et compatible avec le quota API.
6. Bilan de Consommation Token**
Au cours de cette session de correction et de validation, 560,23 unités ont été consommés, pour un coût brut de 5,61 $. Ce niveau de consommation reste modéré dans le contexte d’un correctif métier à la fois technique et fonctionnel : il couvre la clarification de la règle de devise, le refactoring du pipeline et du dashboard, la correction du mode démo, ainsi que la validation finale de la suite de tests. En termes de valeur livrée, le gain est net : un correctif fonctionnel fiable, une documentation de décision plus claire et une validation automatisée plus robuste pour la prochaine itération.