test(fx): pin loss-sell-no-conversion → divisa 1633/1637 = 0 (#230)#237
Merged
Conversation
A foreign-currency stock sold at a LOSS whose dollars are never converted to EUR generates ZERO divisa gain/loss (Art. 14.2.e: imputed only on the cobro/ pago = the real FCY→EUR conversion). The €-loss lands entirely in the stock line at the sale-date rate (V2422-20). This is issue #230's reporter's principle, and the carry-basis engine already implements it — these e2e tests pin it at the casilla level so it can't silently regress: - loss-sell, NO conversion → 0 FX disposals, 1633=1637=0.00, stock=-160.00 - loss-sell THEN convert the survivors → only the surviving $800 hits 1633/1637 at the carried basis (-320.00); the lost $200 is never taxed. Also re-characterize the CLAUDE.md note: the 'loss-sell residual' is a gap-vs-raw-economic that the engine deliberately does not compute (forcing it would double-count FX against the stock loss) and NEVER reaches a casilla — not an 'unbounded residual' that lands in a declared box. Refs #230
Contributor
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughTwo E2E integration tests are added to ChangesIssue
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Issue #230's reporter (elmasvital) confirmed the governing principle for foreign-currency stock losses: dollars spent inside a losing position that are never converted to EUR generate ZERO divisa gain/loss — under Art. 14.2.e LIRPF the FX result is imputed only at the cobro/pago (the real FCY→EUR conversion). The €-loss lands entirely in the stock line at the sale-date rate (V2422-20). Casillas 1633/1637 must contain only amounts actually transmitted (FCY→EUR) in the year.
The carry-basis engine already implements this exactly (a loss-sell emits no
FxDisposal; only conversions reach 1633/1637). This PR is test + docs only — no engine change — pinning the invariant so it can never silently regress, and correcting a misleading internal doc.Tests added (
tests/integration/fx-carry-basis-e2e.test.ts)Both use tracked funding so the buy genuinely parks a carried basis and the sell genuinely discards the lost principal (exercising the real path, not the uncovered no-op):
Doc fix (
CLAUDE.md)Re-characterized the old "loss-sell carried-principal residual (unbounded ~€250k, NOT a bug)" note. The casilla output is the correct only-real-conversions figure; the so-called "residual" is a gap versus a raw-economic benchmark the engine deliberately does not compute (forcing it would double-count FX against the already-recognized stock loss) and never reaches a declared box. The discard is also clean — it mutates only the per-position parked FIFO, never the spendable pool, so it can't shift the FIFO frontier for a later conversion.
Verification
Full suite 1611 passing (was 1607 + 4 new), typecheck + eslint clean. No source/engine files touched.
Refs #230
Summary by CodeRabbit
Documentation
Tests