mirror of
https://github.com/we-promise/sure.git
synced 2026-05-28 15:04:57 +00:00
* fix(holdings): carry provider cost_basis forward to calculated rows Providers like IBKR Flex emit holdings on report_date and only include trades within the query window. The reverse calculator + gapfill therefore produces rows past report_date with nil cost_basis, even though the provider supplied a basis on the snapshot. That nil basis silently blanks `Trend`, the Reports "Total Return" card, the Top Holdings return column, and Gains by Tax Treatment, because every one of them gates on `holding.avg_cost`. When a calculated row would otherwise have no usable cost_basis, backfill it with the most recent provider-supplied cost_basis for the same (security, currency) on or before the holding date. Existing calculated/manual values are preserved (they outrank a provider carry-forward), and existing provider carry-forwards are refreshed when a newer snapshot supersedes them. * - Fix currency mismatch: provider snapshots were keyed by (security_id, currency) but calculated rows use account currency while IBKR provider rows use the security's native currency (e.g., USD vs EUR). Now keyed by security_id only; carry_forward_provider_cost_basis converts via Money#exchange_to at the snapshot date (same convention as ReverseCalculator for trade prices), with a ConversionError fallback. - Trim long inline comment to three lines - Fix safe-nav inconsistency: existing.cost_basis.positive? -> existing&.cost_basis&.positive? - Add test: refreshes stale carry-forward when a newer provider snapshot arrives - Add test: carry-forward is a no-op for forward-strategy accounts with no provider holdings * fix(holdings): prevent overwriting zero-valued manual cost basis Ensure that manual cost basis entries with a value of zero (e.g., for free shares) are not overwritten by provider carry-forward values during materialization. Additionally, updated the logic to allow zero-valued manual or calculated cost bases to be preserved, and added tests to verify currency conversion and error handling during cost basis carry-forward. * refactor(holdings): allow zero-valued cost basis in provider snapshots Remove the filter that restricted provider cost basis snapshots to values greater than zero. This ensures that manual cost basis entries with a value of zero (e.g., for free shares) are correctly captured and available for carry-forward logic. * perf(holdings): optimize provider cost basis snapshot lookup Filter provider cost basis snapshots by the security IDs present in the current holdings set to reduce the amount of data loaded into memory. * refactor(holdings): move PortfolioCache FX fix to dedicated branch Remove date-accurate exchange rate fix from this branch — it has been split into fix/portfolio-cache-historical-fx-rate to keep concerns separate. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * revert(portfolio_cache): restore date-accurate FX in get_price36676784removed date: date from exchange_to intending to move it to fix/portfolio-cache-historical-fx-rate, but that branch was a duplicate ofdb1051d2which was already in main. The revert therefore regressed portfolio_cache.rb below main's state. Restore the historical exchange rate lookup so this branch no longer removes a fix already present in main. * fix(portfolio_cache): restore date-accurate FX and its test36676784removed date: date from exchange_to and deleted the historical FX test, intending to carry them in fix/portfolio-cache-historical-fx-rate. That branch was a duplicate ofdb1051d2already in main, so the removal regressed portfolio_cache.rb below main's state. Restore both. --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>