@actuarial-ts/core 0.5.0 → 0.6.1
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.
- package/README.md +65 -226
- package/dist/capping.d.ts.map +1 -1
- package/dist/capping.js +39 -6
- package/dist/capping.js.map +1 -1
- package/dist/casualtyDiagnostics.d.ts +19 -49
- package/dist/casualtyDiagnostics.d.ts.map +1 -1
- package/dist/casualtyDiagnostics.js +84 -116
- package/dist/casualtyDiagnostics.js.map +1 -1
- package/dist/diagnosticAggregation.d.ts +32 -0
- package/dist/diagnosticAggregation.d.ts.map +1 -0
- package/dist/diagnosticAggregation.js +73 -0
- package/dist/diagnosticAggregation.js.map +1 -0
- package/dist/diagnosticDefinitions.d.ts +289 -0
- package/dist/diagnosticDefinitions.d.ts.map +1 -0
- package/dist/diagnosticDefinitions.js +1688 -0
- package/dist/diagnosticDefinitions.js.map +1 -0
- package/dist/diagnosticDerivations.d.ts +35 -0
- package/dist/diagnosticDerivations.d.ts.map +1 -0
- package/dist/diagnosticDerivations.js +224 -0
- package/dist/diagnosticDerivations.js.map +1 -0
- package/dist/diagnosticExposure.d.ts +51 -0
- package/dist/diagnosticExposure.d.ts.map +1 -0
- package/dist/diagnosticExposure.js +273 -0
- package/dist/diagnosticExposure.js.map +1 -0
- package/dist/diagnosticExpressions.d.ts +56 -0
- package/dist/diagnosticExpressions.d.ts.map +1 -0
- package/dist/diagnosticExpressions.js +124 -0
- package/dist/diagnosticExpressions.js.map +1 -0
- package/dist/diagnosticFormulas.d.ts +198 -0
- package/dist/diagnosticFormulas.d.ts.map +1 -0
- package/dist/diagnosticFormulas.js +219 -0
- package/dist/diagnosticFormulas.js.map +1 -0
- package/dist/diagnosticIdentity.d.ts +251 -0
- package/dist/diagnosticIdentity.d.ts.map +1 -0
- package/dist/diagnosticIdentity.js +721 -0
- package/dist/diagnosticIdentity.js.map +1 -0
- package/dist/diagnosticOrdering.d.ts +8 -0
- package/dist/diagnosticOrdering.d.ts.map +1 -0
- package/dist/diagnosticOrdering.js +73 -0
- package/dist/diagnosticOrdering.js.map +1 -0
- package/dist/diagnosticPeriodAxis.d.ts +9 -0
- package/dist/diagnosticPeriodAxis.d.ts.map +1 -0
- package/dist/diagnosticPeriodAxis.js +69 -0
- package/dist/diagnosticPeriodAxis.js.map +1 -0
- package/dist/diagnosticPeriods.d.ts +15 -0
- package/dist/diagnosticPeriods.d.ts.map +1 -0
- package/dist/diagnosticPeriods.js +50 -0
- package/dist/diagnosticPeriods.js.map +1 -0
- package/dist/diagnosticPreparation.d.ts +131 -0
- package/dist/diagnosticPreparation.d.ts.map +1 -0
- package/dist/diagnosticPreparation.js +1539 -0
- package/dist/diagnosticPreparation.js.map +1 -0
- package/dist/diagnosticReview.d.ts +66 -0
- package/dist/diagnosticReview.d.ts.map +1 -0
- package/dist/diagnosticReview.js +490 -0
- package/dist/diagnosticReview.js.map +1 -0
- package/dist/diagnosticRules.d.ts +32 -0
- package/dist/diagnosticRules.d.ts.map +1 -0
- package/dist/diagnosticRules.js +32 -0
- package/dist/diagnosticRules.js.map +1 -0
- package/dist/diagnosticRunner.d.ts +86 -0
- package/dist/diagnosticRunner.d.ts.map +1 -0
- package/dist/diagnosticRunner.js +703 -0
- package/dist/diagnosticRunner.js.map +1 -0
- package/dist/diagnosticRuntime.d.ts +26 -0
- package/dist/diagnosticRuntime.d.ts.map +1 -0
- package/dist/diagnosticRuntime.js +243 -0
- package/dist/diagnosticRuntime.js.map +1 -0
- package/dist/diagnosticSourceOrdering.d.ts +6 -0
- package/dist/diagnosticSourceOrdering.d.ts.map +1 -0
- package/dist/diagnosticSourceOrdering.js +38 -0
- package/dist/diagnosticSourceOrdering.js.map +1 -0
- package/dist/index.d.ts +28 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -1
- package/dist/index.js.map +1 -1
- package/dist/mack.d.ts +4 -0
- package/dist/mack.d.ts.map +1 -1
- package/dist/mack.js +32 -4
- package/dist/mack.js.map +1 -1
- package/dist/triangle.d.ts.map +1 -1
- package/dist/triangle.js +59 -9
- package/dist/triangle.js.map +1 -1
- package/dist/types.d.ts +21 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +128 -0
- package/dist/types.js.map +1 -1
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/package.json +4 -3
- package/src/capping.ts +109 -18
- package/src/casualtyDiagnostics.ts +79 -189
- package/src/diagnosticAggregation.ts +128 -0
- package/src/diagnosticDefinitions.ts +3624 -0
- package/src/diagnosticDerivations.ts +321 -0
- package/src/diagnosticExposure.ts +482 -0
- package/src/diagnosticExpressions.ts +255 -0
- package/src/diagnosticFormulas.ts +350 -0
- package/src/diagnosticIdentity.ts +1267 -0
- package/src/diagnosticOrdering.ts +106 -0
- package/src/diagnosticPeriodAxis.ts +92 -0
- package/src/diagnosticPeriods.ts +102 -0
- package/src/diagnosticPreparation.ts +2475 -0
- package/src/diagnosticReview.ts +897 -0
- package/src/diagnosticRules.ts +69 -0
- package/src/diagnosticRunner.ts +1114 -0
- package/src/diagnosticRuntime.ts +264 -0
- package/src/diagnosticSourceOrdering.ts +50 -0
- package/src/index.ts +184 -1
- package/src/mack.ts +72 -9
- package/src/triangle.ts +103 -13
- package/src/types.ts +196 -0
- package/src/version.ts +2 -0
- package/dist/metricDiagnostics.d.ts +0 -212
- package/dist/metricDiagnostics.d.ts.map +0 -1
- package/dist/metricDiagnostics.js +0 -627
- package/dist/metricDiagnostics.js.map +0 -1
- package/src/metricDiagnostics.ts +0 -876
package/src/triangle.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
TriangleKind,
|
|
6
6
|
} from "./types.js";
|
|
7
7
|
import { ReservingError } from "./types.js";
|
|
8
|
+
import { isDiagnosticToken, isRealIsoDate } from "./diagnosticRuntime.js";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Builds development triangles from claim-level evaluation snapshots.
|
|
@@ -27,16 +28,12 @@ interface ParsedDate {
|
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
function parseISO(date: string): ParsedDate {
|
|
30
|
-
|
|
31
|
-
if (!match) {
|
|
31
|
+
if (!isRealIsoDate(date))
|
|
32
32
|
throw new ReservingError("BAD_DATE", `Invalid ISO date: "${date}"`);
|
|
33
|
-
}
|
|
33
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(date)!;
|
|
34
34
|
const y = Number(match[1]);
|
|
35
35
|
const m = Number(match[2]);
|
|
36
36
|
const d = Number(match[3]);
|
|
37
|
-
if (m < 1 || m > 12 || d < 1 || d > 31) {
|
|
38
|
-
throw new ReservingError("BAD_DATE", `Invalid ISO date: "${date}"`);
|
|
39
|
-
}
|
|
40
37
|
return { y, m, d };
|
|
41
38
|
}
|
|
42
39
|
|
|
@@ -90,6 +87,7 @@ export interface TriangleSet {
|
|
|
90
87
|
|
|
91
88
|
interface ClaimTimeline {
|
|
92
89
|
originIdx: number;
|
|
90
|
+
accidentISO: string;
|
|
93
91
|
reportISO: string;
|
|
94
92
|
/** Snapshots sorted ascending by evaluation date. */
|
|
95
93
|
snapshots: ClaimSnapshot[];
|
|
@@ -101,9 +99,17 @@ export function buildTriangles(
|
|
|
101
99
|
): TriangleSet {
|
|
102
100
|
const { cadence, asOfDate } = options;
|
|
103
101
|
if (claims.length === 0) {
|
|
104
|
-
throw new ReservingError(
|
|
102
|
+
throw new ReservingError(
|
|
103
|
+
"NO_CLAIMS",
|
|
104
|
+
"Cannot build triangles from an empty loss run",
|
|
105
|
+
);
|
|
105
106
|
}
|
|
106
107
|
const asOf = parseISO(asOfDate);
|
|
108
|
+
if (cadence !== "annual" && cadence !== "quarterly")
|
|
109
|
+
throw new ReservingError(
|
|
110
|
+
"BAD_ORIGIN",
|
|
111
|
+
"Cadence must be annual or quarterly",
|
|
112
|
+
);
|
|
107
113
|
const asOfMonth = monthIndex(asOf);
|
|
108
114
|
const asOfIsMonthEnd = asOf.d === daysInMonth(asOf.y, asOf.m);
|
|
109
115
|
// The latest complete evaluation month.
|
|
@@ -115,15 +121,53 @@ export function buildTriangles(
|
|
|
115
121
|
let minPeriod = Infinity;
|
|
116
122
|
let maxPeriod = -Infinity;
|
|
117
123
|
for (const snap of claims) {
|
|
124
|
+
if (!isDiagnosticToken(snap.claimId))
|
|
125
|
+
throw new ReservingError(
|
|
126
|
+
"BAD_ORIGIN",
|
|
127
|
+
"Claim id must be a nonempty token",
|
|
128
|
+
);
|
|
118
129
|
const accident = parseISO(snap.accidentDate);
|
|
130
|
+
parseISO(snap.reportDate);
|
|
131
|
+
parseISO(snap.evaluationDate);
|
|
132
|
+
if (
|
|
133
|
+
snap.reportDate < snap.accidentDate ||
|
|
134
|
+
snap.evaluationDate < snap.reportDate
|
|
135
|
+
)
|
|
136
|
+
throw new ReservingError(
|
|
137
|
+
"BAD_DATE",
|
|
138
|
+
`Claim ${snap.claimId} dates must satisfy accident <= report <= evaluation`,
|
|
139
|
+
);
|
|
140
|
+
if (!Number.isFinite(snap.paidToDate) || !Number.isFinite(snap.caseReserve))
|
|
141
|
+
throw new ReservingError(
|
|
142
|
+
"BAD_LOSSES",
|
|
143
|
+
`Claim ${snap.claimId} contains a non-finite amount`,
|
|
144
|
+
);
|
|
145
|
+
if (snap.status !== "open" && snap.status !== "closed")
|
|
146
|
+
throw new ReservingError(
|
|
147
|
+
"BAD_LOSSES",
|
|
148
|
+
`Claim ${snap.claimId} has an invalid status`,
|
|
149
|
+
);
|
|
119
150
|
if (snap.evaluationDate > asOfDate) continue; // beyond the analysis date
|
|
120
151
|
const period = periodIndexOf(accident, cadence);
|
|
121
152
|
minPeriod = Math.min(minPeriod, period);
|
|
122
153
|
maxPeriod = Math.max(maxPeriod, period);
|
|
123
154
|
let timeline = byClaim.get(snap.claimId);
|
|
124
155
|
if (!timeline) {
|
|
125
|
-
timeline = {
|
|
156
|
+
timeline = {
|
|
157
|
+
originIdx: period,
|
|
158
|
+
accidentISO: snap.accidentDate,
|
|
159
|
+
reportISO: snap.reportDate,
|
|
160
|
+
snapshots: [],
|
|
161
|
+
};
|
|
126
162
|
byClaim.set(snap.claimId, timeline);
|
|
163
|
+
} else if (
|
|
164
|
+
timeline.accidentISO !== snap.accidentDate ||
|
|
165
|
+
timeline.reportISO !== snap.reportDate
|
|
166
|
+
) {
|
|
167
|
+
throw new ReservingError(
|
|
168
|
+
"BAD_ORIGIN",
|
|
169
|
+
`Claim ${snap.claimId} has conflicting accident or report dates across snapshots`,
|
|
170
|
+
);
|
|
127
171
|
}
|
|
128
172
|
timeline.snapshots.push(snap);
|
|
129
173
|
}
|
|
@@ -135,13 +179,18 @@ export function buildTriangles(
|
|
|
135
179
|
}
|
|
136
180
|
for (const timeline of byClaim.values()) {
|
|
137
181
|
timeline.snapshots.sort((a, b) =>
|
|
138
|
-
a.evaluationDate < b.evaluationDate
|
|
182
|
+
a.evaluationDate < b.evaluationDate
|
|
183
|
+
? -1
|
|
184
|
+
: a.evaluationDate > b.evaluationDate
|
|
185
|
+
? 1
|
|
186
|
+
: 0,
|
|
139
187
|
);
|
|
140
188
|
}
|
|
141
189
|
|
|
142
190
|
const nOrigins = maxPeriod - minPeriod + 1;
|
|
143
191
|
const origins: string[] = [];
|
|
144
|
-
for (let p = minPeriod; p <= maxPeriod; p++)
|
|
192
|
+
for (let p = minPeriod; p <= maxPeriod; p++)
|
|
193
|
+
origins.push(periodLabel(p, cadence));
|
|
145
194
|
|
|
146
195
|
// Ages available to the oldest origin period determine the column count.
|
|
147
196
|
const oldestStart = periodStartMonth(minPeriod, cadence);
|
|
@@ -198,7 +247,8 @@ export function buildTriangles(
|
|
|
198
247
|
else break;
|
|
199
248
|
}
|
|
200
249
|
const paid = state?.paidToDate ?? 0;
|
|
201
|
-
const caseReserve =
|
|
250
|
+
const caseReserve =
|
|
251
|
+
state?.status === "open" ? (state?.caseReserve ?? 0) : 0;
|
|
202
252
|
const isClosed = state?.status === "closed";
|
|
203
253
|
add(set.reportedCount, i, j, 1);
|
|
204
254
|
add(set.paid, i, j, paid);
|
|
@@ -223,13 +273,53 @@ export function triangleFromGrid(
|
|
|
223
273
|
ages: number[],
|
|
224
274
|
values: (number | null)[][],
|
|
225
275
|
): Triangle {
|
|
276
|
+
const kinds: readonly TriangleKind[] = [
|
|
277
|
+
"paid",
|
|
278
|
+
"incurred",
|
|
279
|
+
"caseReserve",
|
|
280
|
+
"reportedCount",
|
|
281
|
+
"openCount",
|
|
282
|
+
"closedCount",
|
|
283
|
+
"closedWithPayCount",
|
|
284
|
+
];
|
|
285
|
+
if (!kinds.includes(kind))
|
|
286
|
+
throw new ReservingError("SHAPE", "Unknown triangle kind");
|
|
287
|
+
if (
|
|
288
|
+
origins.some((origin) => !isDiagnosticToken(origin)) ||
|
|
289
|
+
new Set(origins).size !== origins.length
|
|
290
|
+
) {
|
|
291
|
+
throw new ReservingError("SHAPE", "Origins must be unique nonempty tokens");
|
|
292
|
+
}
|
|
293
|
+
if (
|
|
294
|
+
ages.some((age) => !Number.isSafeInteger(age) || age <= 0) ||
|
|
295
|
+
ages.some((age, index) => index > 0 && age <= ages[index - 1]!)
|
|
296
|
+
) {
|
|
297
|
+
throw new ReservingError(
|
|
298
|
+
"SHAPE",
|
|
299
|
+
"Development ages must be finite positive safe integers in strictly ascending order",
|
|
300
|
+
);
|
|
301
|
+
}
|
|
226
302
|
if (values.length !== origins.length) {
|
|
227
303
|
throw new ReservingError("SHAPE", "Row count does not match origin count");
|
|
228
304
|
}
|
|
229
305
|
for (const row of values) {
|
|
230
306
|
if (row.length !== ages.length) {
|
|
231
|
-
throw new ReservingError(
|
|
307
|
+
throw new ReservingError(
|
|
308
|
+
"SHAPE",
|
|
309
|
+
"Column count does not match age count",
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
if (row.some((value) => value !== null && !Number.isFinite(value))) {
|
|
313
|
+
throw new ReservingError(
|
|
314
|
+
"SHAPE",
|
|
315
|
+
"Observed triangle cells must be finite numbers",
|
|
316
|
+
);
|
|
232
317
|
}
|
|
233
318
|
}
|
|
234
|
-
return {
|
|
319
|
+
return {
|
|
320
|
+
kind,
|
|
321
|
+
origins: [...origins],
|
|
322
|
+
ages: [...ages],
|
|
323
|
+
values: values.map((r) => [...r]),
|
|
324
|
+
};
|
|
235
325
|
}
|
package/src/types.ts
CHANGED
|
@@ -190,6 +190,10 @@ export interface MackResult {
|
|
|
190
190
|
tailFactor?: number;
|
|
191
191
|
/** Extrapolated sigma^2 for the tail step; present only when a tail was applied. */
|
|
192
192
|
sigmaSquaredTail?: number;
|
|
193
|
+
/** Explicit tail-factor estimation error when supplied under Mack (1999). */
|
|
194
|
+
tailStandardError?: number;
|
|
195
|
+
/** Explicit tail random-error scale when supplied under Mack (1999). */
|
|
196
|
+
tailSigma?: number;
|
|
193
197
|
rows: MackRow[];
|
|
194
198
|
totals: {
|
|
195
199
|
latest: number;
|
|
@@ -295,6 +299,198 @@ export interface DiagnosticFinding {
|
|
|
295
299
|
message: string;
|
|
296
300
|
}
|
|
297
301
|
|
|
302
|
+
export type DiagnosticValidationErrorCode =
|
|
303
|
+
| "INVALID_DIAGNOSTIC_DEFINITION"
|
|
304
|
+
| "INVALID_DIAGNOSTIC_INPUT"
|
|
305
|
+
| "INVALID_DIAGNOSTIC_CONFIGURATION"
|
|
306
|
+
| "INVALID_DIAGNOSTIC_VIEW";
|
|
307
|
+
|
|
308
|
+
export type DiagnosticValidationIssueCode =
|
|
309
|
+
| "missing-required"
|
|
310
|
+
| "invalid-type"
|
|
311
|
+
| "unknown-key"
|
|
312
|
+
| "invalid-string"
|
|
313
|
+
| "invalid-number"
|
|
314
|
+
| "invalid-json-value"
|
|
315
|
+
| "duplicate-id"
|
|
316
|
+
| "unknown-reference"
|
|
317
|
+
| "incompatible-semantics"
|
|
318
|
+
| "invalid-period"
|
|
319
|
+
| "invalid-input-relationship"
|
|
320
|
+
| "invalid-configuration"
|
|
321
|
+
| "expression-limit"
|
|
322
|
+
| "cycle";
|
|
323
|
+
|
|
324
|
+
export type DiagnosticValidationDomain =
|
|
325
|
+
| "definition"
|
|
326
|
+
| "input"
|
|
327
|
+
| "configuration"
|
|
328
|
+
| "view";
|
|
329
|
+
|
|
330
|
+
export interface DiagnosticValidationIssue {
|
|
331
|
+
readonly domain: DiagnosticValidationDomain;
|
|
332
|
+
readonly code: DiagnosticValidationIssueCode;
|
|
333
|
+
/** Canonical singular JSONPath, rooted at `$`. */
|
|
334
|
+
readonly path: string;
|
|
335
|
+
readonly message: string;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const DIAGNOSTIC_DOMAIN_ORDER: readonly DiagnosticValidationDomain[] = [
|
|
339
|
+
"definition",
|
|
340
|
+
"input",
|
|
341
|
+
"configuration",
|
|
342
|
+
"view",
|
|
343
|
+
];
|
|
344
|
+
|
|
345
|
+
const DIAGNOSTIC_ISSUE_ORDER: readonly DiagnosticValidationIssueCode[] = [
|
|
346
|
+
"missing-required",
|
|
347
|
+
"invalid-type",
|
|
348
|
+
"unknown-key",
|
|
349
|
+
"invalid-string",
|
|
350
|
+
"invalid-number",
|
|
351
|
+
"invalid-json-value",
|
|
352
|
+
"duplicate-id",
|
|
353
|
+
"unknown-reference",
|
|
354
|
+
"incompatible-semantics",
|
|
355
|
+
"invalid-period",
|
|
356
|
+
"invalid-input-relationship",
|
|
357
|
+
"invalid-configuration",
|
|
358
|
+
"expression-limit",
|
|
359
|
+
"cycle",
|
|
360
|
+
];
|
|
361
|
+
|
|
362
|
+
function compareCodeUnits(left: string, right: string): number {
|
|
363
|
+
return left === right ? 0 : left < right ? -1 : 1;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
type DiagnosticPathSegment =
|
|
367
|
+
| { readonly kind: "property"; readonly value: string }
|
|
368
|
+
| { readonly kind: "index"; readonly value: number };
|
|
369
|
+
|
|
370
|
+
function diagnosticPathSegments(
|
|
371
|
+
path: string,
|
|
372
|
+
): readonly DiagnosticPathSegment[] {
|
|
373
|
+
const segments: DiagnosticPathSegment[] = [];
|
|
374
|
+
let cursor = 1;
|
|
375
|
+
while (cursor < path.length) {
|
|
376
|
+
if (path[cursor] === ".") {
|
|
377
|
+
const start = ++cursor;
|
|
378
|
+
while (
|
|
379
|
+
cursor < path.length &&
|
|
380
|
+
path[cursor] !== "." &&
|
|
381
|
+
path[cursor] !== "["
|
|
382
|
+
)
|
|
383
|
+
cursor++;
|
|
384
|
+
segments.push({ kind: "property", value: path.slice(start, cursor) });
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
if (path[cursor] === "[") {
|
|
388
|
+
const close = path.indexOf("]", cursor);
|
|
389
|
+
if (close < 0) return [{ kind: "property", value: path }];
|
|
390
|
+
const token = path.slice(cursor + 1, close);
|
|
391
|
+
if (/^\d+$/.test(token))
|
|
392
|
+
segments.push({ kind: "index", value: Number(token) });
|
|
393
|
+
else {
|
|
394
|
+
try {
|
|
395
|
+
segments.push({
|
|
396
|
+
kind: "property",
|
|
397
|
+
value: JSON.parse(token) as string,
|
|
398
|
+
});
|
|
399
|
+
} catch {
|
|
400
|
+
return [{ kind: "property", value: path }];
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
cursor = close + 1;
|
|
404
|
+
continue;
|
|
405
|
+
}
|
|
406
|
+
return [{ kind: "property", value: path }];
|
|
407
|
+
}
|
|
408
|
+
return segments;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
function compareDiagnosticPaths(left: string, right: string): number {
|
|
412
|
+
if (left === right) return 0;
|
|
413
|
+
const a = diagnosticPathSegments(left);
|
|
414
|
+
const b = diagnosticPathSegments(right);
|
|
415
|
+
const length = Math.min(a.length, b.length);
|
|
416
|
+
for (let index = 0; index < length; index++) {
|
|
417
|
+
const x = a[index]!;
|
|
418
|
+
const y = b[index]!;
|
|
419
|
+
if (x.kind !== y.kind) return x.kind === "property" ? -1 : 1;
|
|
420
|
+
const compared =
|
|
421
|
+
x.kind === "index"
|
|
422
|
+
? x.value -
|
|
423
|
+
(y as Extract<DiagnosticPathSegment, { kind: "index" }>).value
|
|
424
|
+
: compareCodeUnits(
|
|
425
|
+
x.value,
|
|
426
|
+
(y as Extract<DiagnosticPathSegment, { kind: "property" }>).value,
|
|
427
|
+
);
|
|
428
|
+
if (compared !== 0) return compared;
|
|
429
|
+
}
|
|
430
|
+
return a.length - b.length;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
function normalizeDiagnosticIssues(
|
|
434
|
+
issues: readonly DiagnosticValidationIssue[],
|
|
435
|
+
): readonly DiagnosticValidationIssue[] {
|
|
436
|
+
if (issues.length === 0) {
|
|
437
|
+
throw new Error("DiagnosticValidationError requires at least one issue");
|
|
438
|
+
}
|
|
439
|
+
const unique = new Map<
|
|
440
|
+
string,
|
|
441
|
+
Map<string, Map<string, Map<string, DiagnosticValidationIssue>>>
|
|
442
|
+
>();
|
|
443
|
+
for (const issue of issues) {
|
|
444
|
+
const normalized = Object.freeze({ ...issue });
|
|
445
|
+
const byCode = unique.get(issue.domain) ?? new Map();
|
|
446
|
+
unique.set(issue.domain, byCode);
|
|
447
|
+
const byPath = byCode.get(issue.code) ?? new Map();
|
|
448
|
+
byCode.set(issue.code, byPath);
|
|
449
|
+
const byMessage = byPath.get(issue.path) ?? new Map();
|
|
450
|
+
byPath.set(issue.path, byMessage);
|
|
451
|
+
if (!byMessage.has(issue.message)) byMessage.set(issue.message, normalized);
|
|
452
|
+
}
|
|
453
|
+
const flattened = [...unique.values()].flatMap((byCode) =>
|
|
454
|
+
[...byCode.values()].flatMap((byPath) =>
|
|
455
|
+
[...byPath.values()].flatMap((byMessage) => [...byMessage.values()]),
|
|
456
|
+
),
|
|
457
|
+
);
|
|
458
|
+
return Object.freeze(
|
|
459
|
+
flattened.sort(
|
|
460
|
+
(left, right) =>
|
|
461
|
+
DIAGNOSTIC_DOMAIN_ORDER.indexOf(left.domain) -
|
|
462
|
+
DIAGNOSTIC_DOMAIN_ORDER.indexOf(right.domain) ||
|
|
463
|
+
DIAGNOSTIC_ISSUE_ORDER.indexOf(left.code) -
|
|
464
|
+
DIAGNOSTIC_ISSUE_ORDER.indexOf(right.code) ||
|
|
465
|
+
compareDiagnosticPaths(left.path, right.path) ||
|
|
466
|
+
compareCodeUnits(left.code, right.code) ||
|
|
467
|
+
compareCodeUnits(left.message, right.message),
|
|
468
|
+
),
|
|
469
|
+
);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
/** Public, deterministic validation failure for every generalized diagnostic boundary. */
|
|
473
|
+
export class DiagnosticValidationError extends Error {
|
|
474
|
+
readonly code: DiagnosticValidationErrorCode;
|
|
475
|
+
readonly path: string;
|
|
476
|
+
readonly issues: readonly DiagnosticValidationIssue[];
|
|
477
|
+
|
|
478
|
+
constructor(issues: readonly DiagnosticValidationIssue[]) {
|
|
479
|
+
const normalized = normalizeDiagnosticIssues(issues);
|
|
480
|
+
super(normalized[0]!.message);
|
|
481
|
+
this.name = "DiagnosticValidationError";
|
|
482
|
+
this.issues = normalized;
|
|
483
|
+
this.path = normalized[0]!.path;
|
|
484
|
+
this.code = {
|
|
485
|
+
definition: "INVALID_DIAGNOSTIC_DEFINITION",
|
|
486
|
+
input: "INVALID_DIAGNOSTIC_INPUT",
|
|
487
|
+
configuration: "INVALID_DIAGNOSTIC_CONFIGURATION",
|
|
488
|
+
view: "INVALID_DIAGNOSTIC_VIEW",
|
|
489
|
+
}[normalized[0]!.domain] as DiagnosticValidationErrorCode;
|
|
490
|
+
Object.freeze(this);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
298
494
|
/**
|
|
299
495
|
* Every machine-readable code a ReservingError can carry. This registry is
|
|
300
496
|
* public contract: consumers may switch exhaustively on ReservingErrorCode,
|
package/src/version.ts
ADDED
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
import { type DiagnosticFinding } from "./types.js";
|
|
2
|
-
export type SparseValuePolicy = "preserve-null" | "zero-fill";
|
|
3
|
-
export type DiagnosticMeasureMap = Readonly<Record<string, number | null | undefined>>;
|
|
4
|
-
export type MeasureExpression = {
|
|
5
|
-
op: "measure";
|
|
6
|
-
measure: string;
|
|
7
|
-
} | {
|
|
8
|
-
op: "add";
|
|
9
|
-
terms: readonly MeasureExpression[];
|
|
10
|
-
} | {
|
|
11
|
-
op: "subtract";
|
|
12
|
-
left: MeasureExpression;
|
|
13
|
-
right: MeasureExpression;
|
|
14
|
-
};
|
|
15
|
-
export interface DiagnosticWarning {
|
|
16
|
-
code: "MISSING_COMPONENT" | "NON_FINITE_COMPONENT" | "NON_FINITE_NUMERATOR" | "NON_FINITE_RESULT" | "INVALID_DENOMINATOR" | "INCOMPLETE_EXPOSURE" | "CONFLICTING_EXPOSURE" | "DUPLICATE_EXPOSURE_KEY" | "PAID_EXCEEDS_INCURRED" | (string & {});
|
|
17
|
-
message: string;
|
|
18
|
-
component?: string;
|
|
19
|
-
exposureKey?: string;
|
|
20
|
-
}
|
|
21
|
-
/** Adapts structured metric warnings to the existing core diagnostic finding vocabulary. */
|
|
22
|
-
export declare function diagnosticWarningToFinding(warning: DiagnosticWarning): DiagnosticFinding;
|
|
23
|
-
export interface MetricWarningRule {
|
|
24
|
-
code: "PAID_EXCEEDS_INCURRED";
|
|
25
|
-
when: "numerator-greater-than-denominator";
|
|
26
|
-
message: string;
|
|
27
|
-
tolerance?: number;
|
|
28
|
-
}
|
|
29
|
-
export interface MetricDefinition {
|
|
30
|
-
id: string;
|
|
31
|
-
version: string;
|
|
32
|
-
displayName: string;
|
|
33
|
-
description: string;
|
|
34
|
-
unit: "count-per-million" | "ratio" | "currency-per-exposure" | "currency-per-claim" | (string & {});
|
|
35
|
-
scale: number;
|
|
36
|
-
numerator: MeasureExpression;
|
|
37
|
-
denominator: MeasureExpression;
|
|
38
|
-
numeratorLabel: string;
|
|
39
|
-
denominatorLabel: string;
|
|
40
|
-
basis: string;
|
|
41
|
-
requiredComponents: readonly string[];
|
|
42
|
-
warningRules?: readonly MetricWarningRule[];
|
|
43
|
-
/** Optional pure caller rule for domain warnings beyond the built-in comparisons. */
|
|
44
|
-
evaluateWarnings?: (context: MetricWarningContext) => readonly DiagnosticWarning[];
|
|
45
|
-
}
|
|
46
|
-
export interface MetricWarningContext {
|
|
47
|
-
definition: MetricDefinition;
|
|
48
|
-
components: Readonly<Record<string, number | null>>;
|
|
49
|
-
rawNumerator: number | null;
|
|
50
|
-
rawDenominator: number | null;
|
|
51
|
-
value: number | null;
|
|
52
|
-
}
|
|
53
|
-
export interface MetricEvaluation {
|
|
54
|
-
metricId: string;
|
|
55
|
-
metricVersion: string;
|
|
56
|
-
value: number | null;
|
|
57
|
-
rawNumerator: number | null;
|
|
58
|
-
rawDenominator: number | null;
|
|
59
|
-
numeratorLabel: string;
|
|
60
|
-
denominatorLabel: string;
|
|
61
|
-
unit: MetricDefinition["unit"];
|
|
62
|
-
scale: number;
|
|
63
|
-
basis: string;
|
|
64
|
-
rawComponents: Record<string, number | null>;
|
|
65
|
-
warnings: DiagnosticWarning[];
|
|
66
|
-
}
|
|
67
|
-
export interface MeasureAggregateCell {
|
|
68
|
-
sum: number;
|
|
69
|
-
observed: number;
|
|
70
|
-
missing: number;
|
|
71
|
-
nonFinite: number;
|
|
72
|
-
}
|
|
73
|
-
/** Mergeable sufficient statistics: grouping in stages gives the same result. */
|
|
74
|
-
export interface MeasureAggregate {
|
|
75
|
-
components: Record<string, MeasureAggregateCell>;
|
|
76
|
-
}
|
|
77
|
-
export declare function aggregateMeasures(rows: readonly DiagnosticMeasureMap[]): MeasureAggregate;
|
|
78
|
-
export declare function mergeMeasureAggregates(aggregates: readonly MeasureAggregate[]): MeasureAggregate;
|
|
79
|
-
export interface FinalizedMeasures {
|
|
80
|
-
measures: Record<string, number | null>;
|
|
81
|
-
warnings: DiagnosticWarning[];
|
|
82
|
-
}
|
|
83
|
-
export declare function finalizeMeasureAggregate(aggregate: MeasureAggregate, sparsePolicy?: SparseValuePolicy): FinalizedMeasures;
|
|
84
|
-
export declare function measureExpressionComponents(expression: MeasureExpression): string[];
|
|
85
|
-
export declare function evaluateMetric(definition: MetricDefinition, components: DiagnosticMeasureMap, inheritedWarnings?: readonly DiagnosticWarning[]): MetricEvaluation;
|
|
86
|
-
export type LayerExpression = {
|
|
87
|
-
op: "measure";
|
|
88
|
-
measure: string;
|
|
89
|
-
} | {
|
|
90
|
-
op: "add";
|
|
91
|
-
terms: readonly LayerExpression[];
|
|
92
|
-
} | {
|
|
93
|
-
op: "claim-cap";
|
|
94
|
-
measure: string;
|
|
95
|
-
limit: number;
|
|
96
|
-
};
|
|
97
|
-
export interface AmountLayerDefinition {
|
|
98
|
-
id: string;
|
|
99
|
-
displayName: string;
|
|
100
|
-
paidMeasure: string;
|
|
101
|
-
incurredMeasure: string;
|
|
102
|
-
paid: LayerExpression;
|
|
103
|
-
incurred: LayerExpression;
|
|
104
|
-
/** Documents whether inputs are already limited or this layer caps claim rows. */
|
|
105
|
-
basis: "pre-capped-additive" | "claim-level-cap" | "unlimited-additive";
|
|
106
|
-
}
|
|
107
|
-
export interface DiagnosticClaimRow<T = unknown> {
|
|
108
|
-
dimensions: T;
|
|
109
|
-
measures: DiagnosticMeasureMap;
|
|
110
|
-
}
|
|
111
|
-
/** Applies claim caps before aggregation; this function intentionally accepts claim rows, not aggregates. */
|
|
112
|
-
export declare function deriveAmountLayers<T>(rows: readonly DiagnosticClaimRow<T>[], layers: readonly AmountLayerDefinition[]): DiagnosticClaimRow<T>[];
|
|
113
|
-
export interface DiagnosticLossRow<TDimensions = unknown> {
|
|
114
|
-
id: string;
|
|
115
|
-
group: string;
|
|
116
|
-
origin: string;
|
|
117
|
-
valuation: string;
|
|
118
|
-
ageMonths: number;
|
|
119
|
-
/** Optional caller-mapped policy/fiscal period (for example a Q3-Q2 year). */
|
|
120
|
-
policyPeriod?: string;
|
|
121
|
-
/** Optional caller-owned grouping metadata; `group` remains the stable key. */
|
|
122
|
-
dimensions?: TDimensions;
|
|
123
|
-
measures: DiagnosticMeasureMap;
|
|
124
|
-
}
|
|
125
|
-
export interface DiagnosticExposureRow<TDimensions = unknown> {
|
|
126
|
-
/** Stable exposure identity. Repeated snapshots with the same key count once. */
|
|
127
|
-
key: string;
|
|
128
|
-
group: string;
|
|
129
|
-
origin: string;
|
|
130
|
-
valuation?: string;
|
|
131
|
-
measures: DiagnosticMeasureMap;
|
|
132
|
-
complete?: boolean;
|
|
133
|
-
dimensions?: TDimensions;
|
|
134
|
-
}
|
|
135
|
-
export interface DiagnosticsFilter {
|
|
136
|
-
groups?: readonly string[];
|
|
137
|
-
origins?: readonly string[];
|
|
138
|
-
originFrom?: string;
|
|
139
|
-
originThrough?: string;
|
|
140
|
-
valuations?: readonly string[];
|
|
141
|
-
valuationFrom?: string;
|
|
142
|
-
valuationThrough?: string;
|
|
143
|
-
policyPeriods?: readonly string[];
|
|
144
|
-
minAgeMonths?: number;
|
|
145
|
-
maxAgeMonths?: number;
|
|
146
|
-
}
|
|
147
|
-
export interface DiagnosticEmergencePoint<TDimensions = unknown> {
|
|
148
|
-
group: string;
|
|
149
|
-
dimensions?: TDimensions;
|
|
150
|
-
origin: string;
|
|
151
|
-
valuation: string;
|
|
152
|
-
ageMonths: number;
|
|
153
|
-
components: Record<string, number | null>;
|
|
154
|
-
componentWarnings: DiagnosticWarning[];
|
|
155
|
-
metrics: Record<string, MetricEvaluation>;
|
|
156
|
-
}
|
|
157
|
-
export interface DiagnosticMetricTriangle {
|
|
158
|
-
group: string;
|
|
159
|
-
metricId: string;
|
|
160
|
-
origins: string[];
|
|
161
|
-
ages: number[];
|
|
162
|
-
values: (number | null)[][];
|
|
163
|
-
cells: (MetricEvaluation | null)[][];
|
|
164
|
-
}
|
|
165
|
-
export interface MetricDiagnosticsResult<TDimensions = unknown> {
|
|
166
|
-
emergence: DiagnosticEmergencePoint<TDimensions>[];
|
|
167
|
-
triangles: DiagnosticMetricTriangle[];
|
|
168
|
-
latestDiagonal: DiagnosticEmergencePoint<TDimensions>[];
|
|
169
|
-
}
|
|
170
|
-
export interface RunMetricDiagnosticsInput<TDimensions = unknown> {
|
|
171
|
-
losses: readonly DiagnosticLossRow<TDimensions>[];
|
|
172
|
-
exposures?: readonly DiagnosticExposureRow<TDimensions>[];
|
|
173
|
-
metrics: readonly MetricDefinition[];
|
|
174
|
-
sparsePolicy?: SparseValuePolicy;
|
|
175
|
-
filter?: DiagnosticsFilter;
|
|
176
|
-
/** Maps source group keys to requested aggregate keys before summation. */
|
|
177
|
-
groupMap?: Readonly<Record<string, string>>;
|
|
178
|
-
/** Metadata for mapped/combined output groups. */
|
|
179
|
-
groupDimensions?: Readonly<Record<string, TDimensions>>;
|
|
180
|
-
}
|
|
181
|
-
export interface DiagnosticExposureReconciliationFinding {
|
|
182
|
-
code: "DUPLICATE_EXPOSURE_KEY" | "CONFLICTING_EXPOSURE";
|
|
183
|
-
exposureKey: string;
|
|
184
|
-
group: string;
|
|
185
|
-
origin: string;
|
|
186
|
-
message: string;
|
|
187
|
-
}
|
|
188
|
-
export interface ReconciledDiagnosticExposures<TDimensions = unknown> {
|
|
189
|
-
exposures: DiagnosticExposureRow<TDimensions>[];
|
|
190
|
-
findings: DiagnosticExposureReconciliationFinding[];
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* Reconciles stable exposure keys before aggregation. Identical valuation
|
|
194
|
-
* copies collapse to one row. Conflicting copies become one incomplete/null
|
|
195
|
-
* row so exposure-based metrics fail closed rather than using a partial base.
|
|
196
|
-
*/
|
|
197
|
-
export declare function reconcileDiagnosticExposureKeys<TDimensions = unknown>(rows: readonly DiagnosticExposureRow<TDimensions>[]): ReconciledDiagnosticExposures<TDimensions>;
|
|
198
|
-
/**
|
|
199
|
-
* Generic quarterly diagnostics engine. Loss rows aggregate by
|
|
200
|
-
* group/origin/valuation; exposure rows aggregate once by stable exposure key;
|
|
201
|
-
* every metric then divides the aggregated expressions exactly once.
|
|
202
|
-
*/
|
|
203
|
-
export declare function runMetricDiagnostics<TDimensions = unknown>(input: RunMetricDiagnosticsInput<TDimensions>): MetricDiagnosticsResult<TDimensions>;
|
|
204
|
-
export declare function metricTriangleFromEmergence(points: readonly DiagnosticEmergencePoint<unknown>[], metricId: string): DiagnosticMetricTriangle;
|
|
205
|
-
export declare function sameMaturity<TDimensions>(result: MetricDiagnosticsResult<TDimensions>, ageMonths: number, groups?: readonly string[]): DiagnosticEmergencePoint<TDimensions>[];
|
|
206
|
-
export interface CommonMaturityResult<TDimensions = unknown> {
|
|
207
|
-
ageMonths: number | null;
|
|
208
|
-
points: DiagnosticEmergencePoint<TDimensions>[];
|
|
209
|
-
}
|
|
210
|
-
/** Latest maturity present in every selected group; selection is caller-defined. */
|
|
211
|
-
export declare function commonMaturity<TDimensions>(result: MetricDiagnosticsResult<TDimensions>, groups: readonly string[]): CommonMaturityResult<TDimensions>;
|
|
212
|
-
//# sourceMappingURL=metricDiagnostics.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"metricDiagnostics.d.ts","sourceRoot":"","sources":["../src/metricDiagnostics.ts"],"names":[],"mappings":"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"}
|