@fin.cx/opendata 4.4.0 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@fin.cx/opendata',
6
- version: '4.4.0',
6
+ version: '4.5.0',
7
7
  description: 'Open business and financial data for TypeScript: register lookups on the German register portal (handelsregister.de) without storage, the statutory public holidays of the German federal states, the base rate of § 247 BGB, the German consumer price index with the arithmetic of index clauses, and stock and crypto prices and fundamentals from several providers.'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxrQkFBa0I7SUFDeEIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLDBXQUEwVztDQUN4WCxDQUFBIn0=
@@ -1,5 +1,5 @@
1
1
  export * from './interfaces.js';
2
2
  export { CpiError, type ICpiErrorDetails, type TCpiErrorCode } from './classes.cpierror.js';
3
3
  export { bundesbankCpiBaseUrl, bundesbankVpiAnnualKey, bundesbankVpiFirstMonth, bundesbankVpiFirstYear, bundesbankVpiMonthlyKey, defaultCpiTimeoutMs, destatisLicence, } from './constants.js';
4
- export { cpiChangePercent, cpiChangePoints, cpiFirstReaching, cpiScaleAmount, cpiThresholds } from './indexmath.js';
4
+ export { cpiChangePercent, cpiChangePoints, cpiFirstReaching, cpiFirstReachingPoints, cpiScaleAmount, cpiThresholds } from './indexmath.js';
5
5
  export { BundesbankCpiClient } from './classes.bundesbankcpiclient.js';
@@ -4,6 +4,6 @@
4
4
  export * from './interfaces.js';
5
5
  export { CpiError } from './classes.cpierror.js';
6
6
  export { bundesbankCpiBaseUrl, bundesbankVpiAnnualKey, bundesbankVpiFirstMonth, bundesbankVpiFirstYear, bundesbankVpiMonthlyKey, defaultCpiTimeoutMs, destatisLicence, } from './constants.js';
7
- export { cpiChangePercent, cpiChangePoints, cpiFirstReaching, cpiScaleAmount, cpiThresholds } from './indexmath.js';
7
+ export { cpiChangePercent, cpiChangePoints, cpiFirstReaching, cpiFirstReachingPoints, cpiScaleAmount, cpiThresholds } from './indexmath.js';
8
8
  export { BundesbankCpiClient } from './classes.bundesbankcpiclient.js';
9
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9jcGkvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsNEZBQTRGO0FBQzVGLGtHQUFrRztBQUNsRywwRUFBMEU7QUFDMUUsY0FBYyxpQkFBaUIsQ0FBQztBQUNoQyxPQUFPLEVBQUUsUUFBUSxFQUE2QyxNQUFNLHVCQUF1QixDQUFDO0FBQzVGLE9BQU8sRUFDTCxvQkFBb0IsRUFDcEIsc0JBQXNCLEVBQ3RCLHVCQUF1QixFQUN2QixzQkFBc0IsRUFDdEIsdUJBQXVCLEVBQ3ZCLG1CQUFtQixFQUNuQixlQUFlLEdBQ2hCLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEIsT0FBTyxFQUFFLGdCQUFnQixFQUFFLGVBQWUsRUFBRSxnQkFBZ0IsRUFBRSxjQUFjLEVBQUUsYUFBYSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDcEgsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sa0NBQWtDLENBQUMifQ==
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9jcGkvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsNEZBQTRGO0FBQzVGLGtHQUFrRztBQUNsRywwRUFBMEU7QUFDMUUsY0FBYyxpQkFBaUIsQ0FBQztBQUNoQyxPQUFPLEVBQUUsUUFBUSxFQUE2QyxNQUFNLHVCQUF1QixDQUFDO0FBQzVGLE9BQU8sRUFDTCxvQkFBb0IsRUFDcEIsc0JBQXNCLEVBQ3RCLHVCQUF1QixFQUN2QixzQkFBc0IsRUFDdEIsdUJBQXVCLEVBQ3ZCLG1CQUFtQixFQUNuQixlQUFlLEdBQ2hCLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEIsT0FBTyxFQUFFLGdCQUFnQixFQUFFLGVBQWUsRUFBRSxnQkFBZ0IsRUFBRSxzQkFBc0IsRUFBRSxjQUFjLEVBQUUsYUFBYSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDNUksT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sa0NBQWtDLENBQUMifQ==
@@ -25,6 +25,18 @@ export declare const cpiThresholds: (referenceArg: ICpiValue, percentArg: string
25
25
  * given twice is refused.
26
26
  */
27
27
  export declare const cpiFirstReaching: (valuesArg: readonly ICpiValue[], referenceArg: ICpiValue, percentArg: string, optionsArg: ICpiReachOptions) => ICpiValue | undefined;
28
+ /**
29
+ * The first value after the reference period whose change from the reference in index points
30
+ * (`cpiChangePoints`) reaches a points rule's threshold, or `undefined` while none does: a value at or
31
+ * above reference + points (`up`), at or below reference − points (`down`), or whichever comes first
32
+ * (`either`). The points are a decimal written with digits and a point, from 0 upward, with any number
33
+ * of digits (`'5'`, `'2.5'`); nothing is rounded, so a threshold with more digits than the values is
34
+ * compared exactly. Whether the threshold itself counts (`reached`) or only a value beyond it
35
+ * (`exceeded`) is the clause's to say. Points depend on the base, so all values must be published
36
+ * values of the reference value's series and base (`base_mismatch` otherwise); their order does not
37
+ * matter, a period given twice is refused.
38
+ */
39
+ export declare const cpiFirstReachingPoints: (valuesArg: readonly ICpiValue[], referenceArg: ICpiValue, pointsArg: string, optionsArg: ICpiReachOptions) => ICpiValue | undefined;
28
40
  /**
29
41
  * An amount in cents scaled from one index value to another, rounded half away from zero to whole cents:
30
42
  * by the index ratio (amount × new / old, the default, as the Statistisches Bundesamt writes it) or by
@@ -87,18 +87,19 @@ export const cpiThresholds = (referenceArg, percentArg) => {
87
87
  lower: formatUnits(lower, scale),
88
88
  };
89
89
  };
90
- /**
91
- * The first value after the reference period that reaches a threshold of a percent rule
92
- * (`cpiThresholds`), or `undefined` while none does. Whether the threshold itself counts (`reached`) or
93
- * only a value beyond it (`exceeded`), and which direction, is the clause's to say. All values must be
94
- * published values of the reference value's series and base; their order does not matter, a period
95
- * given twice is refused.
96
- */
97
- export const cpiFirstReaching = (valuesArg, referenceArg, percentArg, optionsArg) => {
90
+ /** The reach options as the clause gives them; anything else is refused. */
91
+ const requireReachOptions = (optionsArg) => {
98
92
  if (!['up', 'down', 'either'].includes(optionsArg.direction) || !['reached', 'exceeded'].includes(optionsArg.reach)) {
99
93
  throw new CpiError('invalid_input', 'the direction is up, down or either, and the reach is reached or exceeded.');
100
94
  }
101
- const thresholds = thresholdUnitsOf(referenceArg, percentArg);
95
+ };
96
+ /**
97
+ * The first value after the reference period at or beyond the upper threshold or at or below the lower
98
+ * one, as the options say. The thresholds are units of 10^-scale; the lower one may be zero or less, which
99
+ * no index value reaches. All values must be published values of the reference value's series and base;
100
+ * their order does not matter, a period given twice is refused.
101
+ */
102
+ const firstReachingUnits = (valuesArg, referenceArg, thresholdsArg, optionsArg) => {
102
103
  const periods = new Set();
103
104
  const candidates = [];
104
105
  for (const value of valuesArg) {
@@ -115,10 +116,10 @@ export const cpiFirstReaching = (valuesArg, referenceArg, percentArg, optionsArg
115
116
  candidates.sort((leftArg, rightArg) => leftArg.value.period.localeCompare(rightArg.value.period));
116
117
  const exceeding = optionsArg.reach === 'exceeded';
117
118
  for (const { value, decimal } of candidates) {
118
- const scale = Math.max(decimal.scale, thresholds.scale);
119
+ const scale = Math.max(decimal.scale, thresholdsArg.scale);
119
120
  const units = atScale(decimal, scale);
120
- const upper = atScale({ units: thresholds.upper, scale: thresholds.scale }, scale);
121
- const lower = atScale({ units: thresholds.lower, scale: thresholds.scale }, scale);
121
+ const upper = thresholdsArg.upper * powerOfTen(scale - thresholdsArg.scale);
122
+ const lower = thresholdsArg.lower * powerOfTen(scale - thresholdsArg.scale);
122
123
  const up = exceeding ? units > upper : units >= upper;
123
124
  const down = exceeding ? units < lower : units <= lower;
124
125
  if ((optionsArg.direction !== 'down' && up) || (optionsArg.direction !== 'up' && down)) {
@@ -127,6 +128,40 @@ export const cpiFirstReaching = (valuesArg, referenceArg, percentArg, optionsArg
127
128
  }
128
129
  return undefined;
129
130
  };
131
+ /**
132
+ * The first value after the reference period that reaches a threshold of a percent rule
133
+ * (`cpiThresholds`), or `undefined` while none does. Whether the threshold itself counts (`reached`) or
134
+ * only a value beyond it (`exceeded`), and which direction, is the clause's to say. All values must be
135
+ * published values of the reference value's series and base; their order does not matter, a period
136
+ * given twice is refused.
137
+ */
138
+ export const cpiFirstReaching = (valuesArg, referenceArg, percentArg, optionsArg) => {
139
+ requireReachOptions(optionsArg);
140
+ return firstReachingUnits(valuesArg, referenceArg, thresholdUnitsOf(referenceArg, percentArg), optionsArg);
141
+ };
142
+ /**
143
+ * The first value after the reference period whose change from the reference in index points
144
+ * (`cpiChangePoints`) reaches a points rule's threshold, or `undefined` while none does: a value at or
145
+ * above reference + points (`up`), at or below reference − points (`down`), or whichever comes first
146
+ * (`either`). The points are a decimal written with digits and a point, from 0 upward, with any number
147
+ * of digits (`'5'`, `'2.5'`); nothing is rounded, so a threshold with more digits than the values is
148
+ * compared exactly. Whether the threshold itself counts (`reached`) or only a value beyond it
149
+ * (`exceeded`) is the clause's to say. Points depend on the base, so all values must be published
150
+ * values of the reference value's series and base (`base_mismatch` otherwise); their order does not
151
+ * matter, a period given twice is refused.
152
+ */
153
+ export const cpiFirstReachingPoints = (valuesArg, referenceArg, pointsArg, optionsArg) => {
154
+ requireReachOptions(optionsArg);
155
+ const reference = publishedValueOf(referenceArg);
156
+ const points = parseDecimal(pointsArg);
157
+ if (!points) {
158
+ throw new CpiError('invalid_input', `${JSON.stringify(pointsArg)} is no number of index points from 0 upward, written with digits and a point.`);
159
+ }
160
+ const scale = Math.max(reference.scale, points.scale);
161
+ const referenceUnits = atScale(reference, scale);
162
+ const pointsUnits = atScale(points, scale);
163
+ return firstReachingUnits(valuesArg, referenceArg, { upper: referenceUnits + pointsUnits, lower: referenceUnits - pointsUnits, scale }, optionsArg);
164
+ };
130
165
  /**
131
166
  * An amount in cents scaled from one index value to another, rounded half away from zero to whole cents:
132
167
  * by the index ratio (amount × new / old, the default, as the Statistisches Bundesamt writes it) or by
@@ -160,4 +195,4 @@ export const cpiScaleAmount = (amountCentsArg, oldArg, newArg, optionsArg = {})
160
195
  }
161
196
  return result;
162
197
  };
163
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXhtYXRoLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvY3BpL2luZGV4bWF0aC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDakQsT0FBTyxFQUFFLE9BQU8sRUFBRSxhQUFhLEVBQUUsV0FBVyxFQUFFLFlBQVksRUFBRSxVQUFVLEVBQXVCLE1BQU0sY0FBYyxDQUFDO0FBR2xILGtHQUFrRztBQUNsRyx1R0FBdUc7QUFDdkcseUdBQXlHO0FBQ3pHLHlGQUF5RjtBQUV6RixNQUFNLEtBQUssR0FBRywwQkFBMEIsQ0FBQztBQUN6QyxNQUFNLElBQUksR0FBRyxVQUFVLENBQUM7QUFFeEIsNEZBQTRGO0FBQzVGLE1BQU0sQ0FBQyxNQUFNLFdBQVcsR0FBRyxDQUFDLFNBQWtCLEVBQTZCLEVBQUU7SUFDM0UsSUFBSSxPQUFPLFNBQVMsS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUNsQyxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBQ0QsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQ3pGLENBQUMsQ0FBQztBQUVGLCtHQUErRztBQUMvRyxNQUFNLGdCQUFnQixHQUFHLENBQUMsUUFBbUIsRUFBa0IsRUFBRTtJQUMvRCxJQUFJLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQ2xDLE1BQU0sSUFBSSxRQUFRLENBQUMsZUFBZSxFQUFFLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLHdDQUF3QyxDQUFDLENBQUM7SUFDbEgsQ0FBQztJQUNELE1BQU0sT0FBTyxHQUFH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
198
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXhtYXRoLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvY3BpL2luZGV4bWF0aC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDakQsT0FBTyxFQUFFLE9BQU8sRUFBRSxhQUFhLEVBQUUsV0FBVyxFQUFFLFlBQVksRUFBRSxVQUFVLEVBQXVCLE1BQU0sY0FBYyxDQUFDO0FBR2xILGtHQUFrRztBQUNsRyx1R0FBdUc7QUFDdkcseUdBQXlHO0FBQ3pHLHlGQUF5RjtBQUV6RixNQUFNLEtBQUssR0FBRywwQkFBMEIsQ0FBQztBQUN6QyxNQUFNLElBQUksR0FBRyxVQUFVLENBQUM7QUFFeEIsNEZBQTRGO0FBQzVGLE1BQU0sQ0FBQyxNQUFNLFdBQVcsR0FBRyxDQUFDLFNBQWtCLEVBQTZCLEVBQUU7SUFDM0UsSUFBSSxPQUFPLFNBQVMsS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUNsQyxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBQ0QsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQ3pGLENBQUMsQ0FBQztBQUVGLCtHQUErRztBQUMvRyxNQUFNLGdCQUFnQixHQUFHLENBQUMsUUFBbUIsRUFBa0IsRUFBRTtJQUMvRCxJQUFJLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQ2xDLE1BQU0sSUFBSSxRQUFRLENBQUMsZUFBZSxFQUFFLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLHdDQUF3QyxDQUFDLENBQUM7SUFDbEgsQ0FBQztJQUNELE1BQU0sT0FBTyxHQUFH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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fin.cx/opendata",
3
- "version": "4.4.0",
3
+ "version": "4.5.0",
4
4
  "private": false,
5
5
  "description": "Open business and financial data for TypeScript: register lookups on the German register portal (handelsregister.de) without storage, the statutory public holidays of the German federal states, the base rate of § 247 BGB, the German consumer price index with the arithmetic of index clauses, and stock and crypto prices and fundamentals from several providers.",
6
6
  "main": "dist_ts/index.js",
package/readme.md CHANGED
@@ -116,6 +116,8 @@ Everything here comes from `@fin.cx/opendata/cpi`. That entry point imports noth
116
116
  The change in percent as the Statistisches Bundesamt computes it, ((new / old) × 100) − 100, rounded to one decimal; and the change in index points.
117
117
  - `cpiThresholds(reference, percent)`, `cpiFirstReaching(values, reference, percent, { direction, reach })`
118
118
  The thresholds of a percent rule (reference × (1 ± percent / 100), rounded to the reference's digits), and the first month after the reference month that reaches one. Whether the threshold itself counts (`reached`) or only a value beyond it (`exceeded`) is the clause's to say.
119
+ - `cpiFirstReachingPoints(values, reference, points, { direction, reach })`
120
+ The same for a points rule: the first month after the reference month whose change in index points reaches the threshold, at or above reference + points (`up`), at or below reference − points (`down`), or whichever comes first (`either`). The points are a decimal from 0 upward (`'5'`, `'2.5'`); the comparison is exact and nothing is rounded.
119
121
  - `cpiScaleAmount(amountCents, old, new, { basis? })`
120
122
  An amount in cents scaled from one index value to another: by the index ratio (amount × new / old, the default) or, with `basis: 'rounded_percent'`, by the change in percent rounded to one decimal.
121
123
  - `CpiError` with the codes `invalid_input`, `before_first_period`, `not_published`, `base_mismatch`, `series_withdrawn`, `busy`, `unavailable`, `unreachable`, `timeout`, `aborted` and `unexpected_answer`
@@ -123,7 +125,7 @@ Everything here comes from `@fin.cx/opendata/cpi`. That entry point imports noth
123
125
  The client takes a `fetch` (for example `createPublicOnlyFetch` of `@push.rocks/smartrequest`), a `baseUrl` for a test server, a `timeoutMs` (30 seconds by default; its timer ends with the request), a `userAgent` and a caller's `signal`. Nothing is retried.
124
126
 
125
127
  ```typescript
126
- import { BundesbankCpiClient, CpiError, cpiChangePercent, cpiFirstReaching, cpiScaleAmount } from '@fin.cx/opendata/cpi';
128
+ import { BundesbankCpiClient, CpiError, cpiChangePercent, cpiFirstReaching, cpiFirstReachingPoints, cpiScaleAmount } from '@fin.cx/opendata/cpi';
127
129
 
128
130
  const client = new BundesbankCpiClient();
129
131
  const series = await client.getMonthly({ from: '2020-01' });
@@ -140,6 +142,7 @@ cpiFirstReaching(series.values, series.values.find((value) => value.period === '
140
142
  direction: 'up',
141
143
  reach: 'reached',
142
144
  }); // the value of 2021-12 (104.7)
145
+ cpiFirstReachingPoints(series.values, october2022, '5', { direction: 'up', reach: 'reached' }); // the value of 2024-03 (118.6); 5 % first in 2024-04
143
146
 
144
147
  try {
145
148
  await client.getMonth('2026-09');
@@ -160,7 +163,7 @@ The Statistisches Bundesamt moves the index to a new base year about every five
160
163
 
161
164
  - every value carries its base, and the calculations refuse values of different bases, indices or frequencies with `base_mismatch`; nothing is converted;
162
165
  - for a percent rule the Statistisches Bundesamt calculates with the values of the current base for both months, even where the contract names an earlier base, so read both again on the current base;
163
- - points depend on the base. `cpiChangePoints()` gives them within one base only; a points rule on an earlier base is the contract's matter;
166
+ - points depend on the base. `cpiChangePoints()` and `cpiFirstReachingPoints()` give them within one base only; a points rule on an earlier base is the contract's matter;
164
167
  - the client leaves the base open in its request, and the Bundesbank answers with the series of the current base. The key of the former base 2015=100 answers 404 today; an answer of 404 ends in `series_withdrawn`, and an answer that holds two bases in `unexpected_answer`.
165
168
 
166
169
  #### Attribution
@@ -581,7 +584,7 @@ Four holidays apply only in part of a state:
581
584
  ### Consumer price index (`@fin.cx/opendata/cpi`)
582
585
 
583
586
  - `BundesbankCpiClient` with `getMonthly({ from, to? })`, `getAnnual({ from, to? })` and `getMonth(month)`
584
- - `cpiChangePercent(old, new)`, `cpiChangePoints(old, new)`, `cpiThresholds(reference, percent)`, `cpiFirstReaching(values, reference, percent, options)`, `cpiScaleAmount(amountCents, old, new, options?)`
587
+ - `cpiChangePercent(old, new)`, `cpiChangePoints(old, new)`, `cpiThresholds(reference, percent)`, `cpiFirstReaching(values, reference, percent, options)`, `cpiFirstReachingPoints(values, reference, points, options)`, `cpiScaleAmount(amountCents, old, new, options?)`
585
588
  - `bundesbankCpiBaseUrl`, `bundesbankVpiMonthlyKey`, `bundesbankVpiAnnualKey`, `bundesbankVpiFirstMonth`, `bundesbankVpiFirstYear`, `destatisLicence`, `defaultCpiTimeoutMs`
586
589
  - `CpiError` with the codes `invalid_input`, `before_first_period`, `not_published`, `base_mismatch`, `series_withdrawn`, `busy`, `unavailable`, `unreachable`, `timeout`, `aborted` and `unexpected_answer`
587
590
 
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@fin.cx/opendata',
6
- version: '4.4.0',
6
+ version: '4.5.0',
7
7
  description: 'Open business and financial data for TypeScript: register lookups on the German register portal (handelsregister.de) without storage, the statutory public holidays of the German federal states, the base rate of § 247 BGB, the German consumer price index with the arithmetic of index clauses, and stock and crypto prices and fundamentals from several providers.'
8
8
  }
package/ts/cpi/index.ts CHANGED
@@ -12,5 +12,5 @@ export {
12
12
  defaultCpiTimeoutMs,
13
13
  destatisLicence,
14
14
  } from './constants.js';
15
- export { cpiChangePercent, cpiChangePoints, cpiFirstReaching, cpiScaleAmount, cpiThresholds } from './indexmath.js';
15
+ export { cpiChangePercent, cpiChangePoints, cpiFirstReaching, cpiFirstReachingPoints, cpiScaleAmount, cpiThresholds } from './indexmath.js';
16
16
  export { BundesbankCpiClient } from './classes.bundesbankcpiclient.js';
@@ -102,23 +102,25 @@ export const cpiThresholds = (referenceArg: ICpiValue, percentArg: string): ICpi
102
102
  };
103
103
  };
104
104
 
105
+ /** The reach options as the clause gives them; anything else is refused. */
106
+ const requireReachOptions = (optionsArg: ICpiReachOptions): void => {
107
+ if (!['up', 'down', 'either'].includes(optionsArg.direction) || !['reached', 'exceeded'].includes(optionsArg.reach)) {
108
+ throw new CpiError('invalid_input', 'the direction is up, down or either, and the reach is reached or exceeded.');
109
+ }
110
+ };
111
+
105
112
  /**
106
- * The first value after the reference period that reaches a threshold of a percent rule
107
- * (`cpiThresholds`), or `undefined` while none does. Whether the threshold itself counts (`reached`) or
108
- * only a value beyond it (`exceeded`), and which direction, is the clause's to say. All values must be
109
- * published values of the reference value's series and base; their order does not matter, a period
110
- * given twice is refused.
113
+ * The first value after the reference period at or beyond the upper threshold or at or below the lower
114
+ * one, as the options say. The thresholds are units of 10^-scale; the lower one may be zero or less, which
115
+ * no index value reaches. All values must be published values of the reference value's series and base;
116
+ * their order does not matter, a period given twice is refused.
111
117
  */
112
- export const cpiFirstReaching = (
118
+ const firstReachingUnits = (
113
119
  valuesArg: readonly ICpiValue[],
114
120
  referenceArg: ICpiValue,
115
- percentArg: string,
121
+ thresholdsArg: { upper: bigint; lower: bigint; scale: number },
116
122
  optionsArg: ICpiReachOptions,
117
123
  ): ICpiValue | undefined => {
118
- if (!['up', 'down', 'either'].includes(optionsArg.direction) || !['reached', 'exceeded'].includes(optionsArg.reach)) {
119
- throw new CpiError('invalid_input', 'the direction is up, down or either, and the reach is reached or exceeded.');
120
- }
121
- const thresholds = thresholdUnitsOf(referenceArg, percentArg);
122
124
  const periods = new Set<string>();
123
125
  const candidates: { value: ICpiValue; decimal: IScaledDecimal }[] = [];
124
126
  for (const value of valuesArg) {
@@ -135,10 +137,10 @@ export const cpiFirstReaching = (
135
137
  candidates.sort((leftArg, rightArg) => leftArg.value.period.localeCompare(rightArg.value.period));
136
138
  const exceeding = optionsArg.reach === 'exceeded';
137
139
  for (const { value, decimal } of candidates) {
138
- const scale = Math.max(decimal.scale, thresholds.scale);
140
+ const scale = Math.max(decimal.scale, thresholdsArg.scale);
139
141
  const units = atScale(decimal, scale);
140
- const upper = atScale({ units: thresholds.upper, scale: thresholds.scale }, scale);
141
- const lower = atScale({ units: thresholds.lower, scale: thresholds.scale }, scale);
142
+ const upper = thresholdsArg.upper * powerOfTen(scale - thresholdsArg.scale);
143
+ const lower = thresholdsArg.lower * powerOfTen(scale - thresholdsArg.scale);
142
144
  const up = exceeding ? units > upper : units >= upper;
143
145
  const down = exceeding ? units < lower : units <= lower;
144
146
  if ((optionsArg.direction !== 'down' && up) || (optionsArg.direction !== 'up' && down)) {
@@ -148,6 +150,52 @@ export const cpiFirstReaching = (
148
150
  return undefined;
149
151
  };
150
152
 
153
+ /**
154
+ * The first value after the reference period that reaches a threshold of a percent rule
155
+ * (`cpiThresholds`), or `undefined` while none does. Whether the threshold itself counts (`reached`) or
156
+ * only a value beyond it (`exceeded`), and which direction, is the clause's to say. All values must be
157
+ * published values of the reference value's series and base; their order does not matter, a period
158
+ * given twice is refused.
159
+ */
160
+ export const cpiFirstReaching = (
161
+ valuesArg: readonly ICpiValue[],
162
+ referenceArg: ICpiValue,
163
+ percentArg: string,
164
+ optionsArg: ICpiReachOptions,
165
+ ): ICpiValue | undefined => {
166
+ requireReachOptions(optionsArg);
167
+ return firstReachingUnits(valuesArg, referenceArg, thresholdUnitsOf(referenceArg, percentArg), optionsArg);
168
+ };
169
+
170
+ /**
171
+ * The first value after the reference period whose change from the reference in index points
172
+ * (`cpiChangePoints`) reaches a points rule's threshold, or `undefined` while none does: a value at or
173
+ * above reference + points (`up`), at or below reference − points (`down`), or whichever comes first
174
+ * (`either`). The points are a decimal written with digits and a point, from 0 upward, with any number
175
+ * of digits (`'5'`, `'2.5'`); nothing is rounded, so a threshold with more digits than the values is
176
+ * compared exactly. Whether the threshold itself counts (`reached`) or only a value beyond it
177
+ * (`exceeded`) is the clause's to say. Points depend on the base, so all values must be published
178
+ * values of the reference value's series and base (`base_mismatch` otherwise); their order does not
179
+ * matter, a period given twice is refused.
180
+ */
181
+ export const cpiFirstReachingPoints = (
182
+ valuesArg: readonly ICpiValue[],
183
+ referenceArg: ICpiValue,
184
+ pointsArg: string,
185
+ optionsArg: ICpiReachOptions,
186
+ ): ICpiValue | undefined => {
187
+ requireReachOptions(optionsArg);
188
+ const reference = publishedValueOf(referenceArg);
189
+ const points = parseDecimal(pointsArg);
190
+ if (!points) {
191
+ throw new CpiError('invalid_input', `${JSON.stringify(pointsArg)} is no number of index points from 0 upward, written with digits and a point.`);
192
+ }
193
+ const scale = Math.max(reference.scale, points.scale);
194
+ const referenceUnits = atScale(reference, scale);
195
+ const pointsUnits = atScale(points, scale);
196
+ return firstReachingUnits(valuesArg, referenceArg, { upper: referenceUnits + pointsUnits, lower: referenceUnits - pointsUnits, scale }, optionsArg);
197
+ };
198
+
151
199
  /**
152
200
  * An amount in cents scaled from one index value to another, rounded half away from zero to whole cents:
153
201
  * by the index ratio (amount × new / old, the default, as the Statistisches Bundesamt writes it) or by