Skip to content

pint units (GEP 10): convert currencies at the column boundary only (never scale parameters)#144

Draft
MImmesberger wants to merge 1 commit into
gep10-infra-1-dimensional-corefrom
gep10-boundary-currency-conversion
Draft

pint units (GEP 10): convert currencies at the column boundary only (never scale parameters)#144
MImmesberger wants to merge 1 commit into
gep10-infra-1-dimensional-corefrom
gep10-boundary-currency-conversion

Conversation

@MImmesberger

Copy link
Copy Markdown
Member

Stacked on #138; #141 will be re-stacked on top of this branch once the rework lands, picking up the mettsim fallout there.

Problem

Build-time parameter scaling breaks run-currency covariance for any formula that is not homogeneous of degree 1 in its money inputs. The concrete case is gettsim's Wohngeld Basisformel, 1.15 · (M − (a + b·M + c·Y) · Y) — quadratic in the money inputs M and Y. Rescaling M and Y by λ (a currency change) rescales the output by λ only if b and c rescale by 1/λ. Making that work under parameter scaling forces per-coefficient units (a dimensionless, b and c in month/EUR) — confusing, and not how the law states these numbers (plain values whose currency convention is implicit in the statute).

Design

Parameters are never scaled. They keep their statutory values in their statutory currency.

  • Computation runs in the policy date's statutory currency (for gettsim: DM through 2001, EUR from 2002), declared by the downstream package as a dated mapping.
  • Conversion happens only at the column boundary: user-provided input columns convert into the computation currency on the way in; requested targets with a currency component in their resolved unit convert to the user-facing currency on the way out.
  • A build-time guard requires every parameter's concrete currency to match the statutory currency at its date — which doubles as the check that a DM value surviving past 2001 got its explicit (legally rounded) Euro-Einführungsgesetz restatement instead of a mechanical ÷1.95583.

This is the definitionally correct semantics — "first calculate in the parameter currency, then convert the result" — so it is exact for arbitrary formula shapes, and statutory formulas keep their published plain-number coefficients as DIMENSIONLESS.

Consequences

  • The parameter-conversion machinery is deleted (leaf scaling, per-order axes conversion of converter outputs, RoundingSpec conversion — a DM-era rounding spec rounds in DM natively). The axes declarations keep their checking role.
  • The currency argument to main() changes meaning: from the currency everything is computed in, to the currency the user's data arrives in and results are returned in.
  • New: target-side boundary conversion; resolved units are known for every column, so this is a factor multiply on currency-carrying targets.
  • The mettsim worked example is reshaped: the two-currency setup becomes a clean dated changeover (the DM→EUR analog) instead of parameter scaling across currencies.
  • The GEP's currency sections are rewritten accordingly (gettsim #1193).

Independent second item riding this branch: the HOURS denominator in the unit grammar (Mindestlohn is EUR per working hour).

Full handoff with touch surface and open sub-questions lives outside the repo (dev-gettsim workspace).

🤖 Generated with Claude Code

Parameters will never be scaled; computation runs in the policy date's
statutory currency and conversion moves entirely to the column boundary
(inputs in, requested targets out). Design and rationale in the PR body;
implementation follows on this branch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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