@@ -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
3433The engine is [ pint] ( https://pint.readthedocs.io ) , and it runs ** only while the policy
3534environment is built** : it checks dimensions and converts units, and plays no part at
@@ -150,9 +149,11 @@ Unit.HOURS.PER_WEEK
150149```
151150
152151A 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
664665written 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
671673package registers a dated **statutory-currency mapping** — for GETTSIM,
@@ -698,20 +700,25 @@ in its fitted currency, statutory coefficients stay the plain `DIMENSIONLESS` nu
698700the law writes, and the result is exact for arbitrary formula shapes — first calculate
699701in 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
717724Deutsche 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
850857roles:
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
856864The numeric runtime path stays pure arrays, single currency, and JAX-safe.
0 commit comments