Skip to content

Commit 701cd12

Browse files
MImmesbergerclaude
andcommitted
GEP 10: functions run in the statutory currency; drop the column-boundary wording
Per the review of ttsim #144: a policy function's code does not care which currency it runs in, but its values are always denominated in the statutory currency of the policy date — only parameters and rounding specs pin down concrete currencies. Describe the conversion of input data and results in plain language instead of the "column boundary" metaphor, mention the declaration minted for data supplied at a derived name, and the warning when the statutory currency differs from the default data currency. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent b8fa381 commit 701cd12

1 file changed

Lines changed: 34 additions & 26 deletions

File tree

docs/geps/gep-10.md

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,10 @@ and (optionally) input data. The framework reads those units to do two things:
2525
so mixing incompatible kinds — a monthly amount and a per-square-meter rent, or a
2626
headcount per Bedarfsgemeinschaft with a monthly amount per household — becomes a loud
2727
error when the policy environment is built, not a silent wrong number far downstream.
28-
- **Automatic unit conversion.** It converts user data at the column boundary between
29-
the currency the data is in and the statutory currency the computation runs in — for
30-
example Euros to Deutsche Mark for pre-2002 policy dates. The existing
31-
`_y`/`_q`/`_m`/`_w`/`_d` and aggregation-level (`_hh`, `_bg`, …) suffix conventions
32-
are preserved.
28+
- **Automatic unit conversion.** It converts input data and results between the currency
29+
the data is in and the statutory currency the computation runs in — for example Euros
30+
to Deutsche Mark for pre-2002 policy dates. The existing `_y`/`_q`/`_m`/`_w`/`_d` and
31+
aggregation-level (`_hh`, `_bg`, …) suffix conventions are preserved.
3332

3433
The engine is [pint](https://pint.readthedocs.io), and it runs **only while the policy
3534
environment is built**: it checks dimensions and converts units, and plays no part at
@@ -150,9 +149,11 @@ Unit.HOURS.PER_WEEK
150149
```
151150

152151
A special, but common, case is the currency dimension. GETTSIM supports two currencies:
153-
Euros (EUR) and Deutsche Mark (DM). Policy functions are written to be currency-agnostic
154-
— they run in either currency without change — so only parameters and input data carry a
155-
concrete currency base ({ref}`Currency <gep-10-currency>`).
152+
Euros (EUR) and Deutsche Mark (DM). A policy function's code does not care which
153+
currency it runs in, but its values are always denominated in the statutory currency of
154+
the policy date — set by the parameters feeding it. Function declarations therefore use
155+
the agnostic `CURRENCY`; only parameters and input data carry a concrete currency base
156+
({ref}`Currency <gep-10-currency>`).
156157

157158
(gep-10-levels)=
158159

@@ -663,9 +664,10 @@ base (`DM`, `EUR`) names one specific currency.
663664
**Parameters must be concrete; functions must be agnostic.** A parameter's numbers are
664665
written in a concrete currency — the declaration must name the denomination
665666
(`EUR_PER_YEAR`, not `CURRENCY_PER_YEAR`). Columns and functions may *only* declare the
666-
agnostic `CURRENCY` as base unit. A derived node — a time-conversion variant or an
667-
aggregation of a concrete-currency parameter — inherits the **agnostic** counterpart:
668-
functions compute on whatever currency the computation runs in.
667+
agnostic `CURRENCY` as base unit: they run in the statutory currency of the policy date,
668+
whichever that is, so pinning one down would be wrong for every other policy date. A
669+
derived node — a time-conversion variant or an aggregation of a concrete-currency
670+
parameter — inherits the **agnostic** counterpart for the same reason.
669671

670672
**The computation currency is the statutory currency.** Alongside its currencies, a
671673
package registers a dated **statutory-currency mapping** — for GETTSIM,
@@ -698,20 +700,25 @@ in its fitted currency, statutory coefficients stay the plain `DIMENSIONLESS` nu
698700
the law writes, and the result is exact for arbitrary formula shapes — first calculate
699701
in the parameter currency, then convert the result.
700702

701-
**The data currency and the column boundary.** The `data_currency` argument to `main()`
702-
names the currency the user's data arrives in and results are returned in. It defaults
703-
to the registered base currency (for GETTSIM, `EUR`) and affects only the column
704-
boundary. On the way in, every input column whose *declared* unit carries a currency
705-
component is converted from the data currency to the computation currency; a tagged
706-
column of the {ref}`unit-annotated input tree <gep-10-trees>` may override the data
707-
currency per column, its tag naming the concrete currency it is actually in. On the way
708-
out, every computed column whose resolved unit carries the agnostic `CURRENCY` is
709-
converted back to the data currency. Requested *parameters* — and the policy environment
710-
itself — are exempt on the way out: they are statutory values, returned and labelled in
711-
their statutory currency; echoed input columns are returned as provided. So a
712-
present-day user simulating 1999 policy hands in Euro columns, the system converts them
713-
to Deutsche Mark at the boundary, computes § 32a and friends on statutory DM magnitudes,
714-
and converts the resulting columns back to Euro.
703+
**The data currency.** The `data_currency` argument to `main()` names the currency the
704+
user's data arrives in and results are returned in. It defaults to the registered base
705+
currency (for GETTSIM, `EUR`) and affects only the conversion of input data and results.
706+
On the way in, every input column whose *declared* unit carries a currency component is
707+
converted from the data currency to the computation currency; a tagged column of the
708+
{ref}`unit-annotated input tree <gep-10-trees>` may override the data currency per
709+
column, its tag naming the concrete currency it is actually in. Data supplied at a
710+
derived name (`einkommen_y` for a declared `einkommen_m`, or `einkommen_m_hh`) gets its
711+
declaration minted from the derivation rules, so it converts like any declared column.
712+
On the way out, every computed column whose resolved unit carries the agnostic
713+
`CURRENCY` is converted back to the data currency. Requested *parameters* — and the
714+
policy environment itself — are exempt on the way out: they are statutory values,
715+
returned and labelled in their statutory currency; input columns requested as targets
716+
are returned as provided. So a present-day user simulating 1999 policy hands in Euro
717+
columns, the system converts them to Deutsche Mark, computes § 32a and friends on
718+
statutory DM magnitudes, and converts the resulting columns back to Euro. A run whose
719+
statutory currency differs from the base currency while `data_currency` sits at its
720+
default triggers a warning — the user may not have thought about the denomination of
721+
their data.
715722

716723
**A changeover within one parameter's history.** Many parameters were written in
717724
Deutsche Mark before 2002 and in Euro afterward. Rather than repeating the currency on
@@ -850,7 +857,8 @@ both JAX and the GEP-9 `FloatColumn` vocabulary. Instead, pint is used in two bu
850857
roles:
851858

852859
- to compute conversion **factors** (time factors baked into the compiled workers as
853-
plain numeric constants; the currency factor applied at the column boundary only); and
860+
plain numeric constants; the currency factor applied only to input data and results);
861+
and
854862
- to run the **dry-run** dimensionality check on representative `Quantity`s.
855863

856864
The numeric runtime path stays pure arrays, single currency, and JAX-safe.

0 commit comments

Comments
 (0)