Native currency display and split portfolio totals
Ticket #337: Native currency display and split portfolio totals
Type: Functional implementation / Business logic correction / Production validation
Affected Component: 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. Context and Symptoms
This intervention marks a clear reversal of the logic documented in docs/fr/features/chapter2.md, where currency conversion was presented as a systematic rule based on Marketstack_Currency and the usd_to_cad_rate rate from config.ini. That approach is being abandoned today because it blurs the source of truth for the 52-week thresholds and converts more values than the business rule allows: conversion is legitimate only for the current price, and only in cases of divergent currency.
The portfolio contained Canadian and U.S. securities, but the application displayed amounts using inconsistent currency logic across screens. The central defect was that some values were converted or reinterpreted ambiguously, or even incorrectly, although the expected business rule was stricter:
- a security's current price must remain displayed in its native currency whenever possible;
- USD-to-CAD conversion must apply only to the relevant current price in cases of divergent currencies;
- displayed 52-week thresholds must remain identical to the CSV source figures, without artificial conversion;
- the dashboard must distinguish CAD totals, USD totals, and the consolidated portfolio total in CAD.
This ambiguity produced misleading results: historical thresholds appeared to be converted, portfolio totals were incorrectly distributed by currency, and the presentation of securities did not reflect their actual original currency.
2. Objective
Correct the business behavior in a robust and verifiable way while retaining production logic compatible with a limited API quota:
- display each security in its native currency on the main pages;
- split portfolio totals into CAD, USD, and CAD consolidation;
- keep the 52-week thresholds strictly unchanged from the source file;
- avoid unnecessary calls to the exchange-rate service by reusing a reliable local state.
3. Implemented Solution
3.1 - Single source of truth for portfolio currency
The pipeline was aligned with a consistent rule: if the ticker starts with TSE:, the portfolio currency is CAD; otherwise, it is USD. This logic is now used explicitly during import and application rendering, without relying on the raw currency detected from the provider.
3.2 - Targeted conversion limited to the current price
Import behavior was adjusted to convert only the market price when the ticker's source currency differs from the provider currency and an exchange rate is available. The 52-week threshold values remain stored as raw data, without recalculation or indirect conversion.
3.3 - Robust exchange-rate management
The USD-to-CAD rate is now retrieved according to fail-open logic:
- try the updated rate when relevant;
- otherwise, reuse the last known rate recorded locally;
- as a last resort, apply the value stored in
config.ini; - persist operational state in
logs/fx_rate_state.jsonto avoid unnecessary calls and make the system behavior explicit.
This approach respects the API quota constraint and stabilizes behavior in production even when the API is unavailable.
3.4 - Dashboards aligned with business reality
The dashboard now displays three separate totals:
- CAD total;
- USD total;
- consolidated portfolio in CAD;
- current rate with retrieval date.
The viewing templates (index, titre_detail, dashboard, and demo_index) were adapted to display explicit labels such as C$ and US$ according to each security's native currency.
3.5 - Non-regression control for 52-week thresholds
The detail pages and demo views were corrected to read the raw an_haut and an_bas thresholds, without referring to the CAD conversion columns. The same rule was applied to demo mode to maintain complete consistency between public and real modes.
4. Tests and Validation
The test suite was reviewed and strengthened around the critical business points:
- currency resolution by the
TSE:prefix; - targeted conversion only for securities with divergent currency;
- no conversion of raw 52-week thresholds;
- FX fallback using the known rate and then the safety value;
- explicit logging of exchange-rate events;
- consistency between demo mode and real mode.
Final validation performed:
- complete suite: 259 tests passed;
- warnings: 3 (pandas/pyarrow warnings and warnings from parsing corrupted lines in the test fixture);
- application code coverage (
code_source_simule/*): 82.37%; - regenerated artifacts:
coverage.xml,docs/reports/report.xml,docs/reports/report.jsonl.
5. Validation and Result
The fix restored business logic consistency with the product decision rule that had been validated:
- native currency display restored;
- portfolio totals correctly split;
- 52-week thresholds faithful to the source;
- exchange-rate mechanism robust and compatible with the API quota.
6. Token Consumption Summary**
During this correction and validation session, 560.23 units were consumed, for a gross cost of $5.61. This level of consumption remains moderate in the context of a business correction that was both technical and functional: it covered clarification of the currency rule, pipeline and dashboard refactoring, correction of demo mode, and final validation of the test suite. In terms of delivered value, the outcome is clear: a reliable functional fix, clearer decision documentation, and a more robust automated validation baseline for the next iteration.