@actuarial-ts/core 0.1.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.
- package/LICENSE +202 -0
- package/NOTICE +5 -0
- package/README.md +133 -0
- package/dist/benktander.d.ts +45 -0
- package/dist/benktander.d.ts.map +1 -0
- package/dist/benktander.js +38 -0
- package/dist/benktander.js.map +1 -0
- package/dist/berquist.d.ts +14 -0
- package/dist/berquist.d.ts.map +1 -0
- package/dist/berquist.js +292 -0
- package/dist/berquist.js.map +1 -0
- package/dist/bf.d.ts +23 -0
- package/dist/bf.d.ts.map +1 -0
- package/dist/bf.js +83 -0
- package/dist/bf.js.map +1 -0
- package/dist/capping.d.ts +96 -0
- package/dist/capping.d.ts.map +1 -0
- package/dist/capping.js +207 -0
- package/dist/capping.js.map +1 -0
- package/dist/caseOutstanding.d.ts +80 -0
- package/dist/caseOutstanding.d.ts.map +1 -0
- package/dist/caseOutstanding.js +147 -0
- package/dist/caseOutstanding.js.map +1 -0
- package/dist/chainladder.d.ts +15 -0
- package/dist/chainladder.d.ts.map +1 -0
- package/dist/chainladder.js +81 -0
- package/dist/chainladder.js.map +1 -0
- package/dist/clark.d.ts +91 -0
- package/dist/clark.d.ts.map +1 -0
- package/dist/clark.js +490 -0
- package/dist/clark.js.map +1 -0
- package/dist/diagnostics.d.ts +80 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +359 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/discounting.d.ts +166 -0
- package/dist/discounting.d.ts.map +1 -0
- package/dist/discounting.js +210 -0
- package/dist/discounting.js.map +1 -0
- package/dist/elrMethods.d.ts +104 -0
- package/dist/elrMethods.d.ts.map +1 -0
- package/dist/elrMethods.js +151 -0
- package/dist/elrMethods.js.map +1 -0
- package/dist/factors.d.ts +19 -0
- package/dist/factors.d.ts.map +1 -0
- package/dist/factors.js +136 -0
- package/dist/factors.js.map +1 -0
- package/dist/fisherLange.d.ts +92 -0
- package/dist/fisherLange.d.ts.map +1 -0
- package/dist/fisherLange.js +224 -0
- package/dist/fisherLange.js.map +1 -0
- package/dist/freqSev.d.ts +57 -0
- package/dist/freqSev.d.ts.map +1 -0
- package/dist/freqSev.js +82 -0
- package/dist/freqSev.js.map +1 -0
- package/dist/ilf.d.ts +111 -0
- package/dist/ilf.d.ts.map +1 -0
- package/dist/ilf.js +449 -0
- package/dist/ilf.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/mack.d.ts +55 -0
- package/dist/mack.d.ts.map +1 -0
- package/dist/mack.js +244 -0
- package/dist/mack.js.map +1 -0
- package/dist/merzWuthrich.d.ts +29 -0
- package/dist/merzWuthrich.d.ts.map +1 -0
- package/dist/merzWuthrich.js +132 -0
- package/dist/merzWuthrich.js.map +1 -0
- package/dist/munichChainLadder.d.ts +101 -0
- package/dist/munichChainLadder.d.ts.map +1 -0
- package/dist/munichChainLadder.js +254 -0
- package/dist/munichChainLadder.js.map +1 -0
- package/dist/odpBootstrap.d.ts +65 -0
- package/dist/odpBootstrap.d.ts.map +1 -0
- package/dist/odpBootstrap.js +243 -0
- package/dist/odpBootstrap.js.map +1 -0
- package/dist/onlevel.d.ts +39 -0
- package/dist/onlevel.d.ts.map +1 -0
- package/dist/onlevel.js +104 -0
- package/dist/onlevel.js.map +1 -0
- package/dist/salvageSubro.d.ts +82 -0
- package/dist/salvageSubro.d.ts.map +1 -0
- package/dist/salvageSubro.js +100 -0
- package/dist/salvageSubro.js.map +1 -0
- package/dist/stochastic.d.ts +56 -0
- package/dist/stochastic.d.ts.map +1 -0
- package/dist/stochastic.js +99 -0
- package/dist/stochastic.js.map +1 -0
- package/dist/tail.d.ts +18 -0
- package/dist/tail.d.ts.map +1 -0
- package/dist/tail.js +121 -0
- package/dist/tail.js.map +1 -0
- package/dist/trend.d.ts +46 -0
- package/dist/trend.d.ts.map +1 -0
- package/dist/trend.js +99 -0
- package/dist/trend.js.map +1 -0
- package/dist/triangle.d.ts +19 -0
- package/dist/triangle.d.ts.map +1 -0
- package/dist/triangle.js +163 -0
- package/dist/triangle.js.map +1 -0
- package/dist/triangleAlgebra.d.ts +10 -0
- package/dist/triangleAlgebra.d.ts.map +1 -0
- package/dist/triangleAlgebra.js +97 -0
- package/dist/triangleAlgebra.js.map +1 -0
- package/dist/types.d.ts +280 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +79 -0
- package/dist/types.js.map +1 -0
- package/dist/ulae.d.ts +172 -0
- package/dist/ulae.d.ts.map +1 -0
- package/dist/ulae.js +164 -0
- package/dist/ulae.js.map +1 -0
- package/dist/util.d.ts +24 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +66 -0
- package/dist/util.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factors.js","sourceRoot":"","sources":["../src/factors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { Triangle } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Fisher-Lange disposal-rate (average-cost-per-claim-settled) method: the
|
|
4
|
+
* reserve is future settlements x trended severity, cell by cell.
|
|
5
|
+
*
|
|
6
|
+
* Ground truth:
|
|
7
|
+
* - Disposal rates d[i][j] = incremental CLOSED counts / SUPPLIED ultimate
|
|
8
|
+
* counts (the ultimates are the caller's independent estimate - e.g. a
|
|
9
|
+
* count chain ladder - never derived here). The rate used per age is the
|
|
10
|
+
* caller's `disposalSelections[j]` or, by default, the latest observed
|
|
11
|
+
* diagonal rate for that age.
|
|
12
|
+
* - Future closed counts for origin i at a future age j = ultimateCounts[i]
|
|
13
|
+
* x selected d[j].
|
|
14
|
+
* - Severities by settlement age: incremental paid / incremental closed per
|
|
15
|
+
* cell. The selected severity for age j is the closed-count-weighted
|
|
16
|
+
* average of the observed cell severities, each trended FROM its cell's
|
|
17
|
+
* calendar period TO the latest observed diagonal (the internal
|
|
18
|
+
* reference).
|
|
19
|
+
* - Reserve = sum over future cells of counts x severity trended to that
|
|
20
|
+
* cell's calendar period.
|
|
21
|
+
*
|
|
22
|
+
* Severity trend convention (compounds by CALENDAR distance): a cell's
|
|
23
|
+
* calendar position is originIndex x ageStep + age (months), where the
|
|
24
|
+
* origin cadence is inferred from the (required equal) development-age
|
|
25
|
+
* spacing. A severity moved y calendar years is multiplied by
|
|
26
|
+
* (1 + severityTrend)^y, fractional years allowed (quarterly triangles
|
|
27
|
+
* compound by quarter-year fractions). Because every observed severity is
|
|
28
|
+
* trended to one reference and then forward to each future cell, the
|
|
29
|
+
* projection is invariant to the reference choice; `targetYear` only shifts
|
|
30
|
+
* the calendar year the DISPLAYED selectedSeverities are stated at.
|
|
31
|
+
*
|
|
32
|
+
* Projection zeros are loud, never silent: an age with no selectable
|
|
33
|
+
* disposal rate projects zero closures with a warning, and a needed age
|
|
34
|
+
* with no observable severity projects zero payment with a warning (the
|
|
35
|
+
* "sparse cell" warnings).
|
|
36
|
+
*/
|
|
37
|
+
export interface FisherLangeOptions {
|
|
38
|
+
/**
|
|
39
|
+
* Selected disposal rate per development age (length = ages.length);
|
|
40
|
+
* null falls back to the latest observed diagonal rate for that age.
|
|
41
|
+
*/
|
|
42
|
+
disposalSelections?: (number | null)[];
|
|
43
|
+
/** Annual severity trend (e.g. 0.05 = +5%/calendar year). */
|
|
44
|
+
severityTrend: number;
|
|
45
|
+
/**
|
|
46
|
+
* Calendar year the displayed selectedSeverities are stated at (default:
|
|
47
|
+
* the latest diagonal's year). Display only - the reserve is invariant.
|
|
48
|
+
* Requires an annual triangle (12-month spacing, first age 12) with
|
|
49
|
+
* numeric origin labels; otherwise ignored with a warning.
|
|
50
|
+
*/
|
|
51
|
+
targetYear?: number;
|
|
52
|
+
}
|
|
53
|
+
export interface FisherLangeRow {
|
|
54
|
+
origin: string;
|
|
55
|
+
/** Age (months) of the latest cell observed in BOTH triangles. */
|
|
56
|
+
latestAge: number;
|
|
57
|
+
paidToDate: number;
|
|
58
|
+
closedToDate: number;
|
|
59
|
+
ultimateCounts: number;
|
|
60
|
+
/** Future closed counts per remaining age column (after latestAge). */
|
|
61
|
+
futureClosedCounts: number[];
|
|
62
|
+
/**
|
|
63
|
+
* Trended severity applied per remaining age column; null where no
|
|
64
|
+
* severity was observable (that cell projected zero payment, warned).
|
|
65
|
+
*/
|
|
66
|
+
futureSeverities: (number | null)[];
|
|
67
|
+
unpaid: number;
|
|
68
|
+
ultimate: number;
|
|
69
|
+
}
|
|
70
|
+
export interface FisherLangeResult {
|
|
71
|
+
method: "fisherLange";
|
|
72
|
+
/** Historical incremental severities (paid / closed) per cell. */
|
|
73
|
+
severities: (number | null)[][];
|
|
74
|
+
/** Historical disposal rates (incremental closed / ultimate counts). */
|
|
75
|
+
disposalRates: (number | null)[][];
|
|
76
|
+
/** Disposal rate used per age (caller's selection or diagonal default). */
|
|
77
|
+
selectedDisposalRates: (number | null)[];
|
|
78
|
+
/** Selected severity per age, stated at referenceYear (display only). */
|
|
79
|
+
selectedSeverities: (number | null)[];
|
|
80
|
+
/** Calendar year selectedSeverities are stated at; null when origin labels don't parse. */
|
|
81
|
+
referenceYear: number | null;
|
|
82
|
+
ultimateCounts: number[];
|
|
83
|
+
rows: FisherLangeRow[];
|
|
84
|
+
totals: {
|
|
85
|
+
paidToDate: number;
|
|
86
|
+
unpaid: number;
|
|
87
|
+
ultimate: number;
|
|
88
|
+
};
|
|
89
|
+
warnings: string[];
|
|
90
|
+
}
|
|
91
|
+
export declare function runFisherLange(paid: Triangle, closedCounts: Triangle, ultimateCounts: number[], options: FisherLangeOptions): FisherLangeResult;
|
|
92
|
+
//# sourceMappingURL=fisherLange.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fisherLange.d.ts","sourceRoot":"","sources":["../src/fisherLange.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAK3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IACvC,6DAA6D;IAC7D,aAAa,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,uEAAuE;IACvE,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B;;;OAGG;IACH,gBAAgB,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,aAAa,CAAC;IACtB,kEAAkE;IAClE,UAAU,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;IAChC,wEAAwE;IACxE,aAAa,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;IACnC,2EAA2E;IAC3E,qBAAqB,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IACzC,yEAAyE;IACzE,kBAAkB,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IACtC,2FAA2F;IAC3F,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,IAAI,EAAE,cAAc,EAAE,CAAC;IACvB,MAAM,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACjE,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAcD,wBAAgB,cAAc,CAC5B,IAAI,EAAE,QAAQ,EACd,YAAY,EAAE,QAAQ,EACtB,cAAc,EAAE,MAAM,EAAE,EACxB,OAAO,EAAE,kBAAkB,GAC1B,iBAAiB,CAsQnB"}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { ReservingError } from "./types.js";
|
|
2
|
+
import { cumulativeToIncremental } from "./triangleAlgebra.js";
|
|
3
|
+
import { isNum, lastJointObservedIndex, lastObservedIndex, safeRatio } from "./util.js";
|
|
4
|
+
function assertSameShape(a, b) {
|
|
5
|
+
const sameOrigins = a.origins.length === b.origins.length && a.origins.every((o, i) => o === b.origins[i]);
|
|
6
|
+
const sameAges = a.ages.length === b.ages.length && a.ages.every((v, j) => v === b.ages[j]);
|
|
7
|
+
if (!sameOrigins || !sameAges) {
|
|
8
|
+
throw new ReservingError("SHAPE", "The paid and closed-count triangles must share identical origins and development ages");
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export function runFisherLange(paid, closedCounts, ultimateCounts, options) {
|
|
12
|
+
assertSameShape(paid, closedCounts);
|
|
13
|
+
const nOrigins = paid.origins.length;
|
|
14
|
+
const nAges = paid.ages.length;
|
|
15
|
+
if (nAges < 2) {
|
|
16
|
+
throw new ReservingError("TOO_SMALL", "Fisher-Lange requires at least two development ages");
|
|
17
|
+
}
|
|
18
|
+
const step = paid.ages[1] - paid.ages[0];
|
|
19
|
+
for (let j = 1; j < nAges; j++) {
|
|
20
|
+
if (paid.ages[j] - paid.ages[j - 1] !== step) {
|
|
21
|
+
throw new ReservingError("SHAPE", "Fisher-Lange infers calendar distance from the age step, which requires equally spaced development ages");
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (ultimateCounts.length !== nOrigins) {
|
|
25
|
+
throw new ReservingError("SHAPE", `Expected ${nOrigins} ultimate claim counts (one per origin), got ${ultimateCounts.length}`);
|
|
26
|
+
}
|
|
27
|
+
ultimateCounts.forEach((u, i) => {
|
|
28
|
+
if (!isNum(u) || u < 0) {
|
|
29
|
+
throw new ReservingError("BAD_COUNTS", `Ultimate counts must be finite and non-negative; origin ${paid.origins[i]} has ${u}`);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
if (!isNum(options.severityTrend) || options.severityTrend <= -1) {
|
|
33
|
+
throw new ReservingError("BAD_TREND", "Severity trend must be greater than -100%");
|
|
34
|
+
}
|
|
35
|
+
if (options.disposalSelections !== undefined && options.disposalSelections.length !== nAges) {
|
|
36
|
+
throw new ReservingError("SELECTION_SHAPE", `Expected ${nAges} disposal-rate selections (one per age), got ${options.disposalSelections.length}`);
|
|
37
|
+
}
|
|
38
|
+
if (options.targetYear !== undefined && !Number.isInteger(options.targetYear)) {
|
|
39
|
+
throw new ReservingError("BAD_DATE", `targetYear must be an integer calendar year, got ${options.targetYear}`);
|
|
40
|
+
}
|
|
41
|
+
const warnings = [];
|
|
42
|
+
const growth = 1 + options.severityTrend;
|
|
43
|
+
const incPaid = cumulativeToIncremental(paid).values;
|
|
44
|
+
const incClosed = cumulativeToIncremental(closedCounts).values;
|
|
45
|
+
const calMonths = (i, j) => i * step + paid.ages[j];
|
|
46
|
+
// Calendar guard: calMonths places origins by array index, which assumes
|
|
47
|
+
// consecutive origin periods. For annual triangles with numeric year
|
|
48
|
+
// labels the assumption is checkable for free - a gap (e.g. 2020, 2023,
|
|
49
|
+
// 2024) silently compresses severity-trend distances, so warn loudly.
|
|
50
|
+
// Quarterly/non-numeric labels stay unchecked (integer label spacing can
|
|
51
|
+
// never equal a quarterly step; the cadence inference is documented above).
|
|
52
|
+
if (step === 12 && paid.origins.every((o) => /^\d+$/.test(o))) {
|
|
53
|
+
for (let i = 1; i < nOrigins; i++) {
|
|
54
|
+
const gap = Number(paid.origins[i]) - Number(paid.origins[i - 1]);
|
|
55
|
+
if (gap !== 1) {
|
|
56
|
+
warnings.push(`Origins ${paid.origins[i - 1]} and ${paid.origins[i]} are ${gap} years apart but are trended as consecutive; with a nonzero severity trend the reserve is misstated - insert explicit null rows for the missing years`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Historical severity and disposal-rate triangles (null-safe by safeRatio).
|
|
61
|
+
const severities = [];
|
|
62
|
+
const disposalRates = [];
|
|
63
|
+
for (let i = 0; i < nOrigins; i++) {
|
|
64
|
+
const ult = ultimateCounts[i];
|
|
65
|
+
severities.push(paid.ages.map((_, j) => safeRatio(incPaid[i][j] ?? null, incClosed[i][j] ?? null)));
|
|
66
|
+
disposalRates.push(paid.ages.map((_, j) => safeRatio(incClosed[i][j] ?? null, ult > 0 ? ult : null)));
|
|
67
|
+
}
|
|
68
|
+
// Reference: the latest observed calendar position across both incremental
|
|
69
|
+
// triangles. All severity statements below are internally at REF.
|
|
70
|
+
let refMonths = -1;
|
|
71
|
+
let refI = -1;
|
|
72
|
+
let refJ = -1;
|
|
73
|
+
for (let i = 0; i < nOrigins; i++) {
|
|
74
|
+
for (let j = 0; j < nAges; j++) {
|
|
75
|
+
if (!isNum(incPaid[i][j] ?? null) && !isNum(incClosed[i][j] ?? null))
|
|
76
|
+
continue;
|
|
77
|
+
const cal = calMonths(i, j);
|
|
78
|
+
if (cal > refMonths) {
|
|
79
|
+
refMonths = cal;
|
|
80
|
+
refI = i;
|
|
81
|
+
refJ = j;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (refMonths < 0) {
|
|
86
|
+
throw new ReservingError("NO_DATA", "No observed cells in the paid or closed-count triangles");
|
|
87
|
+
}
|
|
88
|
+
// Selected disposal rate per age: caller's, else latest diagonal.
|
|
89
|
+
const diagonalDisposal = (j) => {
|
|
90
|
+
for (let i = nOrigins - 1; i >= 0; i--) {
|
|
91
|
+
const d = disposalRates[i][j] ?? null;
|
|
92
|
+
if (isNum(d))
|
|
93
|
+
return d;
|
|
94
|
+
}
|
|
95
|
+
return null;
|
|
96
|
+
};
|
|
97
|
+
const selectedDisposalRates = paid.ages.map((age, j) => {
|
|
98
|
+
const caller = options.disposalSelections?.[j] ?? null;
|
|
99
|
+
if (isNum(caller)) {
|
|
100
|
+
if (caller >= 0)
|
|
101
|
+
return caller;
|
|
102
|
+
warnings.push(`Negative disposal-rate selection for age ${age} months; ignored in favor of the latest diagonal rate`);
|
|
103
|
+
}
|
|
104
|
+
return diagonalDisposal(j);
|
|
105
|
+
});
|
|
106
|
+
const disposalSum = selectedDisposalRates.reduce((a, d) => a + (isNum(d) ? d : 0), 0);
|
|
107
|
+
if (Math.abs(disposalSum - 1) > 0.01) {
|
|
108
|
+
warnings.push(`Selected disposal rates sum to ${disposalSum.toFixed(4)} across all ages; ` +
|
|
109
|
+
(disposalSum < 1
|
|
110
|
+
? "claims closing beyond the last development age are NOT projected"
|
|
111
|
+
: "more closures than ultimate counts are projected - review the pattern"));
|
|
112
|
+
}
|
|
113
|
+
// Selected severity per age at REF: closed-count-weighted average of the
|
|
114
|
+
// observed cell severities, each trended to REF.
|
|
115
|
+
const selectedSevAtRef = paid.ages.map((_, j) => {
|
|
116
|
+
let trendedPaid = 0;
|
|
117
|
+
let closed = 0;
|
|
118
|
+
for (let i = 0; i < nOrigins; i++) {
|
|
119
|
+
if (!isNum(severities[i][j] ?? null))
|
|
120
|
+
continue;
|
|
121
|
+
trendedPaid += incPaid[i][j] * growth ** ((refMonths - calMonths(i, j)) / 12);
|
|
122
|
+
closed += incClosed[i][j];
|
|
123
|
+
}
|
|
124
|
+
return safeRatio(trendedPaid, closed);
|
|
125
|
+
});
|
|
126
|
+
// Projection.
|
|
127
|
+
const warnedNoDisposal = new Set();
|
|
128
|
+
const warnedNoSeverity = new Set();
|
|
129
|
+
const rows = [];
|
|
130
|
+
for (let i = 0; i < nOrigins; i++) {
|
|
131
|
+
const paidRow = paid.values[i];
|
|
132
|
+
const closedRow = closedCounts.values[i];
|
|
133
|
+
const lastPaid = lastObservedIndex(paidRow);
|
|
134
|
+
const lastClosed = lastObservedIndex(closedRow);
|
|
135
|
+
const k = lastJointObservedIndex(paidRow, closedRow);
|
|
136
|
+
if (k < 0) {
|
|
137
|
+
warnings.push(`Origin ${paid.origins[i]} has no age with both paid and closed counts observed; excluded from results`);
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
if (lastPaid !== lastClosed) {
|
|
141
|
+
warnings.push(`Origin ${paid.origins[i]}: paid and closed-count diagonals end at different ages (${paid.ages[lastPaid]} vs ${paid.ages[lastClosed]}); projected from the latest jointly observed age ${paid.ages[k]}`);
|
|
142
|
+
}
|
|
143
|
+
const futureClosedCounts = [];
|
|
144
|
+
const futureSeverities = [];
|
|
145
|
+
let unpaid = 0;
|
|
146
|
+
for (let j = k + 1; j < nAges; j++) {
|
|
147
|
+
const d = selectedDisposalRates[j];
|
|
148
|
+
if (!isNum(d)) {
|
|
149
|
+
if (!warnedNoDisposal.has(j)) {
|
|
150
|
+
warnedNoDisposal.add(j);
|
|
151
|
+
warnings.push(`No disposal rate is selectable for age ${paid.ages[j]} months (sparse column); future closures there are projected as zero`);
|
|
152
|
+
}
|
|
153
|
+
futureClosedCounts.push(0);
|
|
154
|
+
futureSeverities.push(null);
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
const counts = ultimateCounts[i] * d;
|
|
158
|
+
futureClosedCounts.push(counts);
|
|
159
|
+
const sevRef = selectedSevAtRef[j];
|
|
160
|
+
if (!isNum(sevRef)) {
|
|
161
|
+
if (counts > 0 && !warnedNoSeverity.has(j)) {
|
|
162
|
+
warnedNoSeverity.add(j);
|
|
163
|
+
warnings.push(`No severity is observable for age ${paid.ages[j]} months (sparse column); payments there are projected as zero`);
|
|
164
|
+
}
|
|
165
|
+
futureSeverities.push(null);
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
const sev = sevRef * growth ** ((calMonths(i, j) - refMonths) / 12);
|
|
169
|
+
futureSeverities.push(sev);
|
|
170
|
+
unpaid += counts * sev;
|
|
171
|
+
}
|
|
172
|
+
const paidToDate = paidRow[k];
|
|
173
|
+
rows.push({
|
|
174
|
+
origin: paid.origins[i],
|
|
175
|
+
latestAge: paid.ages[k],
|
|
176
|
+
paidToDate,
|
|
177
|
+
closedToDate: closedRow[k],
|
|
178
|
+
ultimateCounts: ultimateCounts[i],
|
|
179
|
+
futureClosedCounts,
|
|
180
|
+
futureSeverities,
|
|
181
|
+
unpaid,
|
|
182
|
+
ultimate: paidToDate + unpaid,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
if (rows.length === 0) {
|
|
186
|
+
throw new ReservingError("NO_DATA", "No origin period has both paid and closed counts observed at any age");
|
|
187
|
+
}
|
|
188
|
+
// Display statement year for the selected severities. Derivable only for
|
|
189
|
+
// annual triangles whose first age is 12 months and whose origin labels
|
|
190
|
+
// are numeric years; the projection above never depends on it.
|
|
191
|
+
let referenceYear = null;
|
|
192
|
+
if (step === 12 && paid.ages[0] === 12 && /^\d+$/.test(paid.origins[refI] ?? "")) {
|
|
193
|
+
referenceYear = Number(paid.origins[refI]) + refJ;
|
|
194
|
+
}
|
|
195
|
+
let displayShiftYears = 0;
|
|
196
|
+
if (options.targetYear !== undefined) {
|
|
197
|
+
if (referenceYear === null) {
|
|
198
|
+
warnings.push("targetYear ignored: stating severities at a calendar year needs an annual triangle (12-month spacing, first age 12) with numeric origin labels");
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
displayShiftYears = options.targetYear - referenceYear;
|
|
202
|
+
referenceYear = options.targetYear;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
const selectedSeverities = selectedSevAtRef.map((s) => isNum(s) ? s * growth ** displayShiftYears : null);
|
|
206
|
+
const totals = rows.reduce((acc, r) => ({
|
|
207
|
+
paidToDate: acc.paidToDate + r.paidToDate,
|
|
208
|
+
unpaid: acc.unpaid + r.unpaid,
|
|
209
|
+
ultimate: acc.ultimate + r.ultimate,
|
|
210
|
+
}), { paidToDate: 0, unpaid: 0, ultimate: 0 });
|
|
211
|
+
return {
|
|
212
|
+
method: "fisherLange",
|
|
213
|
+
severities,
|
|
214
|
+
disposalRates,
|
|
215
|
+
selectedDisposalRates,
|
|
216
|
+
selectedSeverities,
|
|
217
|
+
referenceYear,
|
|
218
|
+
ultimateCounts: [...ultimateCounts],
|
|
219
|
+
rows,
|
|
220
|
+
totals,
|
|
221
|
+
warnings,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=fisherLange.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fisherLange.js","sourceRoot":"","sources":["../src/fisherLange.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { TriangleKind, LdfSelections, Triangle } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Frequency-severity ultimate method (Friedland, "Estimating Unpaid Claims
|
|
4
|
+
* Using Basic Techniques", ch. 11, the development technique applied to
|
|
5
|
+
* claim counts and average values).
|
|
6
|
+
*
|
|
7
|
+
* Ground truth:
|
|
8
|
+
* - Ultimate claims_i = ultimate counts_i x ultimate severity_i.
|
|
9
|
+
* - Ultimate counts: chain ladder on the (reported) count triangle with the
|
|
10
|
+
* caller's selected count LDFs and tail.
|
|
11
|
+
* - Ultimate severity: chain ladder on the average-severity triangle
|
|
12
|
+
* (losses / counts, cell-wise and null-safe) with the caller's selected
|
|
13
|
+
* severity LDFs and tail — developing average values is the standard
|
|
14
|
+
* Friedland treatment.
|
|
15
|
+
* - Selections are the CALLER's judgment on both bases, per the engine-wide
|
|
16
|
+
* rule; this module never picks factors.
|
|
17
|
+
*
|
|
18
|
+
* Caveat the caller must own (doc, not warning): severity here is per
|
|
19
|
+
* REPORTED claim including closed-without-payment; a drifting CWP share
|
|
20
|
+
* masquerades as severity development. Check closure diagnostics before
|
|
21
|
+
* leaning on this method.
|
|
22
|
+
*/
|
|
23
|
+
export interface FrequencySeverityOptions {
|
|
24
|
+
/** Selected count LDFs, one per development interval (null = unselected -> 1.000 with a warning). */
|
|
25
|
+
countSelected: LdfSelections["selected"];
|
|
26
|
+
countTailFactor?: number;
|
|
27
|
+
/** Selected severity LDFs on the average-severity triangle. */
|
|
28
|
+
severitySelected: LdfSelections["selected"];
|
|
29
|
+
severityTailFactor?: number;
|
|
30
|
+
}
|
|
31
|
+
export interface FrequencySeverityRow {
|
|
32
|
+
origin: string;
|
|
33
|
+
/** Latest observed value on the LOSS triangle (the dollars basis). */
|
|
34
|
+
latestValue: number;
|
|
35
|
+
ultimateCounts: number;
|
|
36
|
+
ultimateSeverity: number;
|
|
37
|
+
ultimate: number;
|
|
38
|
+
unpaid: number;
|
|
39
|
+
}
|
|
40
|
+
export interface FrequencySeverityResult {
|
|
41
|
+
method: "frequencySeverity";
|
|
42
|
+
basis: TriangleKind;
|
|
43
|
+
rows: FrequencySeverityRow[];
|
|
44
|
+
totals: {
|
|
45
|
+
latest: number;
|
|
46
|
+
ultimate: number;
|
|
47
|
+
unpaid: number;
|
|
48
|
+
};
|
|
49
|
+
warnings: string[];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Average-severity triangle: cell-wise losses / counts. Null-safe: a
|
|
53
|
+
* missing, zero, or negative count yields a null severity cell.
|
|
54
|
+
*/
|
|
55
|
+
export declare function severityTriangle(lossTri: Triangle, countTri: Triangle): Triangle;
|
|
56
|
+
export declare function runFrequencySeverity(lossTri: Triangle, countTri: Triangle, options: FrequencySeverityOptions): FrequencySeverityResult;
|
|
57
|
+
//# sourceMappingURL=freqSev.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"freqSev.d.ts","sourceRoot":"","sources":["../src/freqSev.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAKxE;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,WAAW,wBAAwB;IACvC,qGAAqG;IACrG,aAAa,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IACzC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,+DAA+D;IAC/D,gBAAgB,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IAC5C,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,mBAAmB,CAAC;IAC5B,KAAK,EAAE,YAAY,CAAC;IACpB,IAAI,EAAE,oBAAoB,EAAE,CAAC;IAC7B,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7D,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,GAAG,QAAQ,CAUhF;AAcD,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,QAAQ,EACjB,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,wBAAwB,GAChC,uBAAuB,CAiEzB"}
|
package/dist/freqSev.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { ReservingError } from "./types.js";
|
|
2
|
+
import { isNum, lastObservedIndex, safeRatio } from "./util.js";
|
|
3
|
+
import { runChainLadder } from "./chainladder.js";
|
|
4
|
+
/**
|
|
5
|
+
* Average-severity triangle: cell-wise losses / counts. Null-safe: a
|
|
6
|
+
* missing, zero, or negative count yields a null severity cell.
|
|
7
|
+
*/
|
|
8
|
+
export function severityTriangle(lossTri, countTri) {
|
|
9
|
+
assertSameShape(lossTri, countTri);
|
|
10
|
+
return {
|
|
11
|
+
kind: lossTri.kind,
|
|
12
|
+
origins: [...lossTri.origins],
|
|
13
|
+
ages: [...lossTri.ages],
|
|
14
|
+
values: lossTri.values.map((row, i) => row.map((loss, j) => safeRatio(loss ?? null, countTri.values[i][j] ?? null))),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function assertSameShape(a, b) {
|
|
18
|
+
const sameOrigins = a.origins.length === b.origins.length && a.origins.every((o, i) => o === b.origins[i]);
|
|
19
|
+
const sameAges = a.ages.length === b.ages.length && a.ages.every((v, i) => v === b.ages[i]);
|
|
20
|
+
if (!sameOrigins || !sameAges) {
|
|
21
|
+
throw new ReservingError("SHAPE", "The loss and count triangles must share identical origins and development ages");
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export function runFrequencySeverity(lossTri, countTri, options) {
|
|
25
|
+
assertSameShape(lossTri, countTri);
|
|
26
|
+
const warnings = [];
|
|
27
|
+
const countCl = runChainLadder(countTri, {
|
|
28
|
+
selected: options.countSelected,
|
|
29
|
+
tailFactor: options.countTailFactor ?? 1,
|
|
30
|
+
});
|
|
31
|
+
for (const w of countCl.warnings)
|
|
32
|
+
warnings.push(`counts: ${w}`);
|
|
33
|
+
const sevTri = severityTriangle(lossTri, countTri);
|
|
34
|
+
const sevCl = runChainLadder(sevTri, {
|
|
35
|
+
selected: options.severitySelected,
|
|
36
|
+
tailFactor: options.severityTailFactor ?? 1,
|
|
37
|
+
});
|
|
38
|
+
for (const w of sevCl.warnings)
|
|
39
|
+
warnings.push(`severity: ${w}`);
|
|
40
|
+
const countByOrigin = new Map(countCl.rows.map((r) => [r.origin, r]));
|
|
41
|
+
const sevByOrigin = new Map(sevCl.rows.map((r) => [r.origin, r]));
|
|
42
|
+
const rows = [];
|
|
43
|
+
for (let i = 0; i < lossTri.origins.length; i++) {
|
|
44
|
+
const origin = lossTri.origins[i];
|
|
45
|
+
const counts = countByOrigin.get(origin);
|
|
46
|
+
const sev = sevByOrigin.get(origin);
|
|
47
|
+
if (!counts || !sev) {
|
|
48
|
+
warnings.push(`Origin ${origin} has no observed counts or severities; excluded from frequency-severity`);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const latestIdx = lastObservedIndex(lossTri.values[i]);
|
|
52
|
+
const latestValue = latestIdx >= 0 ? lossTri.values[i][latestIdx] : 0;
|
|
53
|
+
const ultimate = counts.ultimate * sev.ultimate;
|
|
54
|
+
if (!isNum(ultimate)) {
|
|
55
|
+
warnings.push(`Origin ${origin}: the frequency-severity ultimate is not computable`);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
rows.push({
|
|
59
|
+
origin,
|
|
60
|
+
latestValue,
|
|
61
|
+
ultimateCounts: counts.ultimate,
|
|
62
|
+
ultimateSeverity: sev.ultimate,
|
|
63
|
+
ultimate,
|
|
64
|
+
unpaid: ultimate - latestValue,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
if (rows.length === 0) {
|
|
68
|
+
throw new ReservingError("NO_DATA", "No origin period has both observed counts and observed severities");
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
method: "frequencySeverity",
|
|
72
|
+
basis: lossTri.kind,
|
|
73
|
+
rows,
|
|
74
|
+
totals: {
|
|
75
|
+
latest: rows.reduce((a, r) => a + r.latestValue, 0),
|
|
76
|
+
ultimate: rows.reduce((a, r) => a + r.ultimate, 0),
|
|
77
|
+
unpaid: rows.reduce((a, r) => a + r.unpaid, 0),
|
|
78
|
+
},
|
|
79
|
+
warnings,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=freqSev.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"freqSev.js","sourceRoot":"","sources":["../src/freqSev.ts"],"names":[],"mappings":"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"}
|
package/dist/ilf.d.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import type { ClaimSnapshot } from "./types.js";
|
|
2
|
+
export declare function normalCdf(z: number): number;
|
|
3
|
+
export type SeverityDistribution = {
|
|
4
|
+
kind: "lognormal";
|
|
5
|
+
mu: number;
|
|
6
|
+
sigma: number;
|
|
7
|
+
} | {
|
|
8
|
+
kind: "pareto";
|
|
9
|
+
theta: number;
|
|
10
|
+
alpha: number;
|
|
11
|
+
};
|
|
12
|
+
/** Mean E[X]; null when infinite (Pareto alpha <= 1). */
|
|
13
|
+
export declare function severityMean(dist: SeverityDistribution): number | null;
|
|
14
|
+
/** Limited expected value E[X ∧ c]. */
|
|
15
|
+
export declare function limitedExpectedValue(dist: SeverityDistribution, c: number): number;
|
|
16
|
+
/**
|
|
17
|
+
* The uncap factor to a target limit: E[X ∧ target] / E[X ∧ cap], with
|
|
18
|
+
* target null meaning unlimited (E[X] / E[X ∧ cap]). Throws when the
|
|
19
|
+
* distribution has no finite mean and target is unlimited.
|
|
20
|
+
*/
|
|
21
|
+
export declare function uncapFactor(dist: SeverityDistribution, cap: number, target: number | null): number;
|
|
22
|
+
export interface SeverityObservation {
|
|
23
|
+
/** Severity at the claim's latest evaluation, at base-year cost level. */
|
|
24
|
+
value: number;
|
|
25
|
+
/**
|
|
26
|
+
* True when the claim is still open. Its reported incurred is then treated
|
|
27
|
+
* as a right-censoring floor on ultimate severity - a CASE-ADEQUACY
|
|
28
|
+
* ASSUMPTION, not a fact: redundant case reserves overstate the fitted
|
|
29
|
+
* tail, deficient ones understate it. Fits must carry this caveat.
|
|
30
|
+
*/
|
|
31
|
+
censored: boolean;
|
|
32
|
+
}
|
|
33
|
+
export interface SeverityFit {
|
|
34
|
+
distribution: SeverityDistribution;
|
|
35
|
+
logLikelihood: number;
|
|
36
|
+
nExact: number;
|
|
37
|
+
nCensored: number;
|
|
38
|
+
nExcludedNonPositive: number;
|
|
39
|
+
valid: boolean;
|
|
40
|
+
warnings: string[];
|
|
41
|
+
/**
|
|
42
|
+
* Kaplan-Meier (censoring-adjusted) empirical quantiles vs fitted
|
|
43
|
+
* unconditional quantiles. Closed-claims-only quantiles are biased small
|
|
44
|
+
* (large claims stay open), so the empirical side uses the product-limit
|
|
45
|
+
* estimator; null where censoring exhausts the observable range.
|
|
46
|
+
*/
|
|
47
|
+
quantileCheck: {
|
|
48
|
+
p: number;
|
|
49
|
+
empirical: number | null;
|
|
50
|
+
fitted: number;
|
|
51
|
+
}[];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Fits a severity distribution by maximum likelihood with right-censoring:
|
|
55
|
+
* closed claims contribute the density, open claims the survival at their
|
|
56
|
+
* reported incurred. Treating reported incurred as a floor on ultimate
|
|
57
|
+
* severity is a CASE-ADEQUACY assumption - on books with redundant reserves
|
|
58
|
+
* the fitted tail (and any uncap factor from it) is overstated. Fits are
|
|
59
|
+
* additionally gated on censored share and parameter sanity: a likelihood
|
|
60
|
+
* dominated by open claims can push the tail arbitrarily heavy while looking
|
|
61
|
+
* converged.
|
|
62
|
+
*/
|
|
63
|
+
export declare function fitSeverity(observations: SeverityObservation[], kind: SeverityDistribution["kind"]): SeverityFit;
|
|
64
|
+
/**
|
|
65
|
+
* Kaplan-Meier product-limit quantiles over exact + right-censored values:
|
|
66
|
+
* the censoring-adjusted empirical benchmark (closed-only quantiles are
|
|
67
|
+
* biased small because large claims stay open). Returns null for probes the
|
|
68
|
+
* survival curve cannot reach (censoring exhausts the observable range).
|
|
69
|
+
* Ties convention: events precede censorings at the same value.
|
|
70
|
+
*/
|
|
71
|
+
export declare function kaplanMeierQuantiles(exact: number[], censored: number[], probes: number[]): (number | null)[];
|
|
72
|
+
/**
|
|
73
|
+
* Structural validation shared by every ILF-table write path (import route,
|
|
74
|
+
* workspace patch) and by interpolation: >= 2 rows, positive limits and
|
|
75
|
+
* factors, unique limits, factors non-decreasing in the limit. Throws
|
|
76
|
+
* ReservingError so garbage is rejected at the door, identically everywhere.
|
|
77
|
+
*/
|
|
78
|
+
export declare function validateIlfTable(table: IlfTableRow[]): IlfTableRow[];
|
|
79
|
+
/**
|
|
80
|
+
* Base-year-level severity observations from a loss run: each claim's latest
|
|
81
|
+
* evaluation on or before asOfDate, deflated by the cap index, open claims
|
|
82
|
+
* censored at reported incurred.
|
|
83
|
+
*/
|
|
84
|
+
export declare function severityObservations(claims: ClaimSnapshot[], options: {
|
|
85
|
+
asOfDate?: string;
|
|
86
|
+
indexRate?: number;
|
|
87
|
+
baseYear: number;
|
|
88
|
+
}): SeverityObservation[];
|
|
89
|
+
export interface IlfTableRow {
|
|
90
|
+
limit: number;
|
|
91
|
+
factor: number;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Log-log interpolated ILF at a limit. Exact at knots; throws when the
|
|
95
|
+
* table does not bracket the requested limit (extrapolating an ILF table is
|
|
96
|
+
* how excess layers get silently mispriced).
|
|
97
|
+
*/
|
|
98
|
+
export declare function interpolateIlf(table: IlfTableRow[], limit: number): number;
|
|
99
|
+
/** Table-based uncap factor: ILF(target)/ILF(cap). */
|
|
100
|
+
export declare function tableUncapFactor(table: IlfTableRow[], cap: number, target: number): number;
|
|
101
|
+
/**
|
|
102
|
+
* Illustrative severity curves for when no licensed table and no credible
|
|
103
|
+
* own-data fit exist. Parameters are textbook-plausible shapes, NOT ISO or
|
|
104
|
+
* NCCI factors - the UI must say so loudly.
|
|
105
|
+
*/
|
|
106
|
+
export declare const ILLUSTRATIVE_CURVES: {
|
|
107
|
+
id: string;
|
|
108
|
+
label: string;
|
|
109
|
+
distribution: SeverityDistribution;
|
|
110
|
+
}[];
|
|
111
|
+
//# sourceMappingURL=ilf.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ilf.d.ts","sourceRoot":"","sources":["../src/ilf.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAgChD,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE3C;AAKD,MAAM,MAAM,oBAAoB,GAC5B;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAErD,yDAAyD;AACzD,wBAAgB,YAAY,CAAC,IAAI,EAAE,oBAAoB,GAAG,MAAM,GAAG,IAAI,CAMtE;AAED,uCAAuC;AACvC,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,oBAAoB,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAgBlF;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,oBAAoB,EAC1B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GAAG,IAAI,GACpB,MAAM,CA0BR;AAKD,MAAM,WAAW,mBAAmB;IAClC,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,oBAAoB,CAAC;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB;;;;;OAKG;IACH,aAAa,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC1E;AAoGD;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CACzB,YAAY,EAAE,mBAAmB,EAAE,EACnC,IAAI,EAAE,oBAAoB,CAAC,MAAM,CAAC,GACjC,WAAW,CAmJb;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EAAE,EACf,QAAQ,EAAE,MAAM,EAAE,EAClB,MAAM,EAAE,MAAM,EAAE,GACf,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CA4BnB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,CAsBpE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,aAAa,EAAE,EACvB,OAAO,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACnE,mBAAmB,EAAE,CAiBvB;AAKD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAoB1E;AAED,sDAAsD;AACtD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAK1F;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,oBAAoB,CAAC;CACpC,EAgBA,CAAC"}
|