Skip to content

fix(lightyear): parse FX conversions as CASH trades for FX FIFO engine#161

Merged
GeiserX merged 2 commits into
mainfrom
fix/lightyear-fx-conversions
May 11, 2026
Merged

fix(lightyear): parse FX conversions as CASH trades for FX FIFO engine#161
GeiserX merged 2 commits into
mainfrom
fix/lightyear-fx-conversions

Conversation

@GeiserX
Copy link
Copy Markdown
Owner

@GeiserX GeiserX commented May 11, 2026

Summary

  • FX Conversion rows were incorrectly skipped, causing detectAutoConvert() to assume the account uses auto-convert (no manual CASH trades → broker does it)
  • This meant FX gains/losses on manual EUR↔FCY conversions were never computed per Art. 37.1.l LIRPF (DGT V2324-10)
  • Now emits assetCategory=CASH trades for non-EUR conversion legs, enabling the FX FIFO engine to track lots and compute taxable FX gains
  • EUR legs are skipped (the FX engine only needs the FCY side)

Test plan

  • Non-EUR conversion leg emitted as CASH BUY trade (USD +64.50)
  • EUR leg of conversion pair skipped
  • Negative gross (FCY→EUR) emits SELL CASH
  • Presence of CASH trades enables FX FIFO detection (autoConvert=false)
  • All 1019 existing tests pass

Summary by CodeRabbit

  • New Features

    • FX conversions now tracked as taxable trade events for accurate tax and P&L calculations.
    • Fractional currency codes (GBX, ZAC, ILA) automatically normalized to base currencies with proper amount scaling.
  • Bug Fixes

    • Improved handling of non-EUR currency conversions in import processing.

Review Change Stack

GeiserX added 2 commits May 11, 2026 12:58
…(÷100)

Trading 212 reports prices in GBX (pence) for UK stocks. The ECB only
publishes GBP rates, so the parser must normalize GBX→GBP and divide
amounts by 100. Also handles ZAc→ZAR and ILA→ILS.

Closes #86
Conversions were incorrectly skipped, causing detectAutoConvert() to
assume auto-convert (no CASH trades = broker does it automatically).
This meant FX gains/losses on manual EUR↔FCY conversions were never
computed per Art. 37.1.l LIRPF (DGT V2324-10).

Now emits assetCategory=CASH trades for non-EUR conversion legs,
enabling the FX FIFO engine to track lots and compute taxable FX gains.
@GeiserX GeiserX merged commit 6cf1506 into main May 11, 2026
2 of 3 checks passed
@GeiserX GeiserX deleted the fix/lightyear-fx-conversions branch May 11, 2026 20:48
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 11, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7d9dcfdc-b0ae-4be6-8116-f02e0b513bba

📥 Commits

Reviewing files that changed from the base of the PR and between 25a8241 and 80cd600.

📒 Files selected for processing (4)
  • src/parsers/lightyear.ts
  • src/parsers/trading212.ts
  • tests/parsers/lightyear.test.ts
  • tests/parsers/trading212.test.ts

📝 Walkthrough

Walkthrough

Two independent parser improvements: Lightyear now emits CASH FX trades for non-EUR conversions instead of skipping them, with FIFO fields populated for downstream processing. Trading 212 normalizes fractional currencies (GBX, ZAC, ILA) to base ISO codes by scaling all monetary amounts by ÷100.

Changes

Lightyear FX Conversion Handling

Layer / File(s) Summary
Skip Set Removal
src/parsers/lightyear.ts
conversion removed from non-taxable skip set, enabling conversion rows to be processed as taxable transactions.
Conversion Logic
src/parsers/lightyear.ts
Adds explicit handling for conversion rows that emits CASH-category FX trade records for non-EUR legs, mapping grossAmount sign to BUY/SELL semantics with FIFO fields populated.
Test Updates & Coverage
tests/parsers/lightyear.test.ts
Inline test updated to expect CASH BUY trade for USD conversion leg; new "FX conversions" section verifies non-EUR CASH emission, EUR leg skipping, FCY→EUR SELL trades, and FX FIFO detection; overall trade count increased from 5 to 6.

Trading 212 Fractional Currency Normalization

Layer / File(s) Summary
Normalization Helper
src/parsers/trading212.ts
Introduces FRACTIONAL_CURRENCIES set (GBX, ZAC, ILA) and normalizeCurrency() function that returns base ISO currency and Decimal divisor for amount scaling.
Currency Resolution
src/parsers/trading212.ts
CSV column initialization resolves both instrument price currency and cash "Total" currency via normalization, storing priceDivisor and cashDivisor instead of raw codes.
Cash Transaction Scaling
src/parsers/trading212.ts
Withholding Tax, Dividends, and Interest-on-cash amounts now scaled by dividing absolute CSV total by cashDivisor before emission.
Trade Monetary Scaling
src/parsers/trading212.ts
Trade price and total amounts normalized by dividing priceStr by priceDivisor and totalStr by cashDivisor, affecting downstream money, cost, and proceeds calculations.
Fractional Currency Tests
tests/parsers/trading212.test.ts
New test suite verifies GBX→GBP normalization (÷100) for buy/sell trades, dividends, and withholding tax; includes guard test for unchanged GBP inputs.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • GeiserX/DeclaRenta#146: Modifies Trading 212 parser; this PR's fractional currency scaling is a direct enhancement to that parser.
  • GeiserX/DeclaRenta#117: Modifies Lightyear conversion handling; this PR changes how conversions are processed into CASH FX trades.
  • GeiserX/DeclaRenta#124: This PR's CASH FX trade emissions for conversions directly interact with FXCONV detection and auto-convert account suppression in that PR.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/lightyear-fx-conversions

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 11, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.65%. Comparing base (8f6bef2) to head (80cd600).
⚠️ Report is 9 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #161      +/-   ##
==========================================
+ Coverage   97.63%   97.65%   +0.01%     
==========================================
  Files          38       38              
  Lines        7622     7669      +47     
  Branches     1549     1563      +14     
==========================================
+ Hits         7442     7489      +47     
  Misses        179      179              
  Partials        1        1              
Files with missing lines Coverage Δ
src/parsers/lightyear.ts 99.06% <100.00%> (+0.16%) ⬆️
src/parsers/trading212.ts 97.71% <100.00%> (+0.16%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant