@actuarial-ts/core 0.3.0 → 0.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.
- package/README.md +115 -0
- package/dist/berquist.d.ts.map +1 -1
- package/dist/berquist.js +4 -12
- package/dist/berquist.js.map +1 -1
- package/dist/caseOutstanding.d.ts.map +1 -1
- package/dist/caseOutstanding.js +2 -9
- package/dist/caseOutstanding.js.map +1 -1
- package/dist/casualtyDiagnostics.d.ts +53 -0
- package/dist/casualtyDiagnostics.d.ts.map +1 -0
- package/dist/casualtyDiagnostics.js +124 -0
- package/dist/casualtyDiagnostics.js.map +1 -0
- package/dist/fisherLange.d.ts.map +1 -1
- package/dist/fisherLange.js +2 -9
- package/dist/fisherLange.js.map +1 -1
- package/dist/freqSev.d.ts.map +1 -1
- package/dist/freqSev.js +3 -10
- package/dist/freqSev.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/metricDiagnostics.d.ts +212 -0
- package/dist/metricDiagnostics.d.ts.map +1 -0
- package/dist/metricDiagnostics.js +627 -0
- package/dist/metricDiagnostics.js.map +1 -0
- package/dist/munichChainLadder.d.ts.map +1 -1
- package/dist/munichChainLadder.js +2 -7
- package/dist/munichChainLadder.js.map +1 -1
- package/dist/periods.d.ts +46 -0
- package/dist/periods.d.ts.map +1 -0
- package/dist/periods.js +121 -0
- package/dist/periods.js.map +1 -0
- package/dist/util.d.ts +8 -0
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +15 -0
- package/dist/util.js.map +1 -1
- package/package.json +1 -1
- package/src/berquist.ts +4 -15
- package/src/caseOutstanding.ts +12 -14
- package/src/casualtyDiagnostics.ts +204 -0
- package/src/fisherLange.ts +12 -14
- package/src/freqSev.ts +11 -15
- package/src/index.ts +3 -0
- package/src/metricDiagnostics.ts +876 -0
- package/src/munichChainLadder.ts +6 -12
- package/src/periods.ts +177 -0
- package/src/util.ts +20 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import {
|
|
2
|
+
measureExpressionComponents,
|
|
3
|
+
type AmountLayerDefinition,
|
|
4
|
+
type MeasureExpression,
|
|
5
|
+
type MetricDefinition,
|
|
6
|
+
type MetricWarningRule,
|
|
7
|
+
} from "./metricDiagnostics.js";
|
|
8
|
+
import { ReservingError } from "./types.js";
|
|
9
|
+
|
|
10
|
+
const m = (measure: string): MeasureExpression => ({ op: "measure", measure });
|
|
11
|
+
const sub = (left: MeasureExpression, right: MeasureExpression): MeasureExpression => ({ op: "subtract", left, right });
|
|
12
|
+
|
|
13
|
+
function definedProperties<T extends object>(value: T | undefined): Partial<T> {
|
|
14
|
+
if (value === undefined) return {};
|
|
15
|
+
return Object.fromEntries(
|
|
16
|
+
Object.entries(value).filter(([, item]) => item !== undefined),
|
|
17
|
+
) as Partial<T>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface CasualtyDiagnosticComponentKeys {
|
|
21
|
+
reported: string;
|
|
22
|
+
open: string;
|
|
23
|
+
closedNoPay: string;
|
|
24
|
+
closedWithPay: string;
|
|
25
|
+
exposure: string;
|
|
26
|
+
paid250: string;
|
|
27
|
+
incurred250: string;
|
|
28
|
+
paidPrimary: string;
|
|
29
|
+
incurredPrimary: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const CASUALTY_DIAGNOSTIC_COMPONENTS: Readonly<CasualtyDiagnosticComponentKeys> = {
|
|
33
|
+
reported: "reportedCount",
|
|
34
|
+
open: "openCount",
|
|
35
|
+
closedNoPay: "closedNoPayCount",
|
|
36
|
+
closedWithPay: "closedWithPayCount",
|
|
37
|
+
exposure: "exposure",
|
|
38
|
+
paid250: "paid250",
|
|
39
|
+
incurred250: "incurred250",
|
|
40
|
+
paidPrimary: "paidPrimary",
|
|
41
|
+
incurredPrimary: "incurredPrimary",
|
|
42
|
+
} as const;
|
|
43
|
+
|
|
44
|
+
type MetricDisplayOverride = Partial<Pick<
|
|
45
|
+
MetricDefinition,
|
|
46
|
+
"displayName" | "description" | "unit" | "numeratorLabel" | "denominatorLabel" | "basis"
|
|
47
|
+
>>;
|
|
48
|
+
|
|
49
|
+
export interface CasualtyMetricPresetOptions {
|
|
50
|
+
/** Caller source/output measure keys, including the exposure key. */
|
|
51
|
+
components?: Partial<CasualtyDiagnosticComponentKeys>;
|
|
52
|
+
frequencyScale?: number;
|
|
53
|
+
frequencyUnit?: MetricDefinition["unit"];
|
|
54
|
+
definitionVersion?: string;
|
|
55
|
+
basisLabels?: { limited250?: string; primary?: string; counts?: string };
|
|
56
|
+
/** Per-metric display/basis overrides; formulas remain the documented preset formulas. */
|
|
57
|
+
displayOverrides?: Readonly<Record<string, MetricDisplayOverride>>;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function metric(
|
|
61
|
+
id: string,
|
|
62
|
+
displayName: string,
|
|
63
|
+
description: string,
|
|
64
|
+
unit: MetricDefinition["unit"],
|
|
65
|
+
scale: number,
|
|
66
|
+
numerator: MeasureExpression,
|
|
67
|
+
denominator: MeasureExpression,
|
|
68
|
+
numeratorLabel: string,
|
|
69
|
+
denominatorLabel: string,
|
|
70
|
+
basis: string,
|
|
71
|
+
version: string,
|
|
72
|
+
override: MetricDisplayOverride | undefined,
|
|
73
|
+
warningRules?: readonly MetricWarningRule[],
|
|
74
|
+
): MetricDefinition {
|
|
75
|
+
const definition: MetricDefinition = {
|
|
76
|
+
id,
|
|
77
|
+
version,
|
|
78
|
+
displayName,
|
|
79
|
+
description,
|
|
80
|
+
unit,
|
|
81
|
+
scale,
|
|
82
|
+
numerator,
|
|
83
|
+
denominator,
|
|
84
|
+
numeratorLabel,
|
|
85
|
+
denominatorLabel,
|
|
86
|
+
basis,
|
|
87
|
+
requiredComponents: [...new Set([
|
|
88
|
+
...measureExpressionComponents(numerator),
|
|
89
|
+
...measureExpressionComponents(denominator),
|
|
90
|
+
])],
|
|
91
|
+
warningRules,
|
|
92
|
+
};
|
|
93
|
+
return { ...definition, ...definedProperties(override) };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const paidWarning: readonly MetricWarningRule[] = [{
|
|
97
|
+
code: "PAID_EXCEEDS_INCURRED",
|
|
98
|
+
when: "numerator-greater-than-denominator",
|
|
99
|
+
message: "Paid exceeds incurred on the selected amount basis",
|
|
100
|
+
tolerance: 1e-9,
|
|
101
|
+
}];
|
|
102
|
+
|
|
103
|
+
/** Builds the optional 22-metric reference preset from caller-selected keys and display metadata. */
|
|
104
|
+
export function createCasualtyQuarterlyMetrics(
|
|
105
|
+
options: CasualtyMetricPresetOptions = {},
|
|
106
|
+
): readonly MetricDefinition[] {
|
|
107
|
+
const C = {
|
|
108
|
+
...CASUALTY_DIAGNOSTIC_COMPONENTS,
|
|
109
|
+
...definedProperties(options.components),
|
|
110
|
+
};
|
|
111
|
+
const frequencyScale = options.frequencyScale ?? 1_000_000;
|
|
112
|
+
if (!Number.isFinite(frequencyScale) || frequencyScale <= 0) {
|
|
113
|
+
throw new ReservingError("BAD_RATIO", `Casualty frequency scale must be positive; got ${frequencyScale}`);
|
|
114
|
+
}
|
|
115
|
+
const version = options.definitionVersion ?? "casualty-quarterly-v1";
|
|
116
|
+
const frequencyUnit = options.frequencyUnit ?? (frequencyScale === 1_000_000
|
|
117
|
+
? "count-per-million"
|
|
118
|
+
: "count-per-exposure-scale");
|
|
119
|
+
const limitedBasis = options.basisLabels?.limited250 ?? "$250K pre-capped total";
|
|
120
|
+
const primaryBasis = options.basisLabels?.primary ?? "$1M capped indemnity plus unlimited expense";
|
|
121
|
+
const countBasis = options.basisLabels?.counts ?? "count";
|
|
122
|
+
const override = (id: string) => options.displayOverrides?.[id];
|
|
123
|
+
const nonClosedNoPay = sub(m(C.reported), m(C.closedNoPay));
|
|
124
|
+
return [
|
|
125
|
+
metric("reported-frequency", "Reported claim frequency", "Reported claims per scaled exposure units", frequencyUnit, frequencyScale, m(C.reported), m(C.exposure), "reported claims", "exposure", countBasis, version, override("reported-frequency")),
|
|
126
|
+
metric("open-frequency", "Open claim frequency", "Open claims per scaled exposure units", frequencyUnit, frequencyScale, m(C.open), m(C.exposure), "open claims", "exposure", countBasis, version, override("open-frequency")),
|
|
127
|
+
metric("closed-no-pay-frequency", "Closed-no-pay frequency", "Closed-no-pay claims per scaled exposure units", frequencyUnit, frequencyScale, m(C.closedNoPay), m(C.exposure), "closed-no-pay claims", "exposure", countBasis, version, override("closed-no-pay-frequency")),
|
|
128
|
+
metric("closed-with-pay-frequency", "Closed-with-pay frequency", "Closed-with-pay claims per scaled exposure units", frequencyUnit, frequencyScale, m(C.closedWithPay), m(C.exposure), "closed-with-pay claims", "exposure", countBasis, version, override("closed-with-pay-frequency")),
|
|
129
|
+
metric("non-closed-no-pay-frequency", "Non-closed-no-pay frequency", "Reported less closed-no-pay claims per scaled exposure units", frequencyUnit, frequencyScale, nonClosedNoPay, m(C.exposure), "reported less closed-no-pay claims", "exposure", countBasis, version, override("non-closed-no-pay-frequency")),
|
|
130
|
+
metric("closed-no-pay-share", "Closed-no-pay share", "Closed-no-pay claims divided by reported claims", "ratio", 1, m(C.closedNoPay), m(C.reported), "closed-no-pay claims", "reported claims", countBasis, version, override("closed-no-pay-share")),
|
|
131
|
+
metric("closed-with-pay-share", "Closed-with-pay share", "Closed-with-pay claims divided by reported claims", "ratio", 1, m(C.closedWithPay), m(C.reported), "closed-with-pay claims", "reported claims", countBasis, version, override("closed-with-pay-share")),
|
|
132
|
+
metric("closed-with-pay-share-of-non-cnp", "Closed-with-pay share of non-CNP claims", "Closed-with-pay claims divided by reported less closed-no-pay claims", "ratio", 1, m(C.closedWithPay), nonClosedNoPay, "closed-with-pay claims", "reported less closed-no-pay claims", countBasis, version, override("closed-with-pay-share-of-non-cnp")),
|
|
133
|
+
metric("open-share", "Open share", "Open claims divided by reported claims", "ratio", 1, m(C.open), m(C.reported), "open claims", "reported claims", countBasis, version, override("open-share")),
|
|
134
|
+
metric("open-share-of-non-cnp", "Open share of non-CNP claims", "Open claims divided by reported less closed-no-pay claims", "ratio", 1, m(C.open), nonClosedNoPay, "open claims", "reported less closed-no-pay claims", countBasis, version, override("open-share-of-non-cnp")),
|
|
135
|
+
metric("paid-to-incurred-250", "Paid-to-incurred ($250K)", "Paid divided by incurred on the pre-capped $250K basis", "ratio", 1, m(C.paid250), m(C.incurred250), "$250K paid", "$250K incurred", limitedBasis, version, override("paid-to-incurred-250"), paidWarning),
|
|
136
|
+
metric("paid-to-incurred-primary", "Paid-to-incurred (primary)", "Paid divided by incurred on the primary basis", "ratio", 1, m(C.paidPrimary), m(C.incurredPrimary), "primary paid", "primary incurred", primaryBasis, version, override("paid-to-incurred-primary"), paidWarning),
|
|
137
|
+
metric("incurred-250-per-exposure", "Incurred per exposure ($250K)", "$250K incurred divided by exposure", "currency-per-exposure", 1, m(C.incurred250), m(C.exposure), "$250K incurred", "exposure", limitedBasis, version, override("incurred-250-per-exposure")),
|
|
138
|
+
metric("incurred-primary-per-exposure", "Incurred per exposure (primary)", "Primary incurred divided by exposure", "currency-per-exposure", 1, m(C.incurredPrimary), m(C.exposure), "primary incurred", "exposure", primaryBasis, version, override("incurred-primary-per-exposure")),
|
|
139
|
+
metric("incurred-250-per-non-cnp", "Incurred severity ($250K)", "$250K incurred divided by reported less closed-no-pay claims", "currency-per-claim", 1, m(C.incurred250), nonClosedNoPay, "$250K incurred", "reported less closed-no-pay claims", limitedBasis, version, override("incurred-250-per-non-cnp")),
|
|
140
|
+
metric("incurred-primary-per-non-cnp", "Incurred severity (primary)", "Primary incurred divided by reported less closed-no-pay claims", "currency-per-claim", 1, m(C.incurredPrimary), nonClosedNoPay, "primary incurred", "reported less closed-no-pay claims", primaryBasis, version, override("incurred-primary-per-non-cnp")),
|
|
141
|
+
metric("paid-250-per-exposure", "Paid per exposure ($250K)", "$250K paid divided by exposure", "currency-per-exposure", 1, m(C.paid250), m(C.exposure), "$250K paid", "exposure", limitedBasis, version, override("paid-250-per-exposure")),
|
|
142
|
+
metric("paid-primary-per-exposure", "Paid per exposure (primary)", "Primary paid divided by exposure", "currency-per-exposure", 1, m(C.paidPrimary), m(C.exposure), "primary paid", "exposure", primaryBasis, version, override("paid-primary-per-exposure")),
|
|
143
|
+
metric("paid-250-per-closed-with-pay", "Paid severity ($250K)", "$250K paid divided by closed-with-pay claims", "currency-per-claim", 1, m(C.paid250), m(C.closedWithPay), "$250K paid", "closed-with-pay claims", limitedBasis, version, override("paid-250-per-closed-with-pay")),
|
|
144
|
+
metric("paid-primary-per-closed-with-pay", "Paid severity (primary)", "Primary paid divided by closed-with-pay claims", "currency-per-claim", 1, m(C.paidPrimary), m(C.closedWithPay), "primary paid", "closed-with-pay claims", primaryBasis, version, override("paid-primary-per-closed-with-pay")),
|
|
145
|
+
metric("case-250-per-open", "Case reserve per open claim ($250K)", "$250K incurred less paid divided by open claims", "currency-per-claim", 1, sub(m(C.incurred250), m(C.paid250)), m(C.open), "$250K incurred less paid", "open claims", limitedBasis, version, override("case-250-per-open")),
|
|
146
|
+
metric("case-primary-per-open", "Case reserve per open claim (primary)", "Primary incurred less paid divided by open claims", "currency-per-claim", 1, sub(m(C.incurredPrimary), m(C.paidPrimary)), m(C.open), "primary incurred less paid", "open claims", primaryBasis, version, override("case-primary-per-open")),
|
|
147
|
+
];
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export const CASUALTY_QUARTERLY_METRICS = createCasualtyQuarterlyMetrics();
|
|
151
|
+
|
|
152
|
+
export interface CasualtyAmountLayerOptions {
|
|
153
|
+
components?: Partial<Pick<CasualtyDiagnosticComponentKeys, "paid250" | "incurred250" | "paidPrimary" | "incurredPrimary">>;
|
|
154
|
+
limited250?: {
|
|
155
|
+
id?: string;
|
|
156
|
+
displayName?: string;
|
|
157
|
+
paidSourceMeasure?: string;
|
|
158
|
+
incurredSourceMeasure?: string;
|
|
159
|
+
};
|
|
160
|
+
primary?: {
|
|
161
|
+
id?: string;
|
|
162
|
+
displayName?: string;
|
|
163
|
+
indemnityPaidMeasure?: string;
|
|
164
|
+
indemnityIncurredMeasure?: string;
|
|
165
|
+
expensePaidMeasure?: string;
|
|
166
|
+
expenseIncurredMeasure?: string;
|
|
167
|
+
indemnityLimit?: number;
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export function createCasualtyAmountLayers(
|
|
172
|
+
options: CasualtyAmountLayerOptions = {},
|
|
173
|
+
): readonly AmountLayerDefinition[] {
|
|
174
|
+
const C = {
|
|
175
|
+
...CASUALTY_DIAGNOSTIC_COMPONENTS,
|
|
176
|
+
...definedProperties(options.components),
|
|
177
|
+
};
|
|
178
|
+
const limit = options.primary?.indemnityLimit ?? 1_000_000;
|
|
179
|
+
if (!Number.isFinite(limit) || limit <= 0) {
|
|
180
|
+
throw new ReservingError("BAD_CAP", `Primary indemnity limit must be positive; got ${limit}`);
|
|
181
|
+
}
|
|
182
|
+
return [
|
|
183
|
+
{
|
|
184
|
+
id: options.limited250?.id ?? "250k-pre-capped-total",
|
|
185
|
+
displayName: options.limited250?.displayName ?? "$250K pre-capped total",
|
|
186
|
+
paidMeasure: C.paid250,
|
|
187
|
+
incurredMeasure: C.incurred250,
|
|
188
|
+
paid: { op: "measure", measure: options.limited250?.paidSourceMeasure ?? "preCapped250Paid" },
|
|
189
|
+
incurred: { op: "measure", measure: options.limited250?.incurredSourceMeasure ?? "preCapped250Incurred" },
|
|
190
|
+
basis: "pre-capped-additive",
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
id: options.primary?.id ?? "primary-1m-indemnity-plus-expense",
|
|
194
|
+
displayName: options.primary?.displayName ?? "Primary: $1M capped indemnity plus unlimited expense",
|
|
195
|
+
paidMeasure: C.paidPrimary,
|
|
196
|
+
incurredMeasure: C.incurredPrimary,
|
|
197
|
+
paid: { op: "add", terms: [{ op: "claim-cap", measure: options.primary?.indemnityPaidMeasure ?? "indemnityPaid", limit }, { op: "measure", measure: options.primary?.expensePaidMeasure ?? "expensePaid" }] },
|
|
198
|
+
incurred: { op: "add", terms: [{ op: "claim-cap", measure: options.primary?.indemnityIncurredMeasure ?? "indemnityIncurred", limit }, { op: "measure", measure: options.primary?.expenseIncurredMeasure ?? "expenseIncurred" }] },
|
|
199
|
+
basis: "claim-level-cap",
|
|
200
|
+
},
|
|
201
|
+
];
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export const CASUALTY_AMOUNT_LAYERS = createCasualtyAmountLayers();
|
package/src/fisherLange.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import type { Triangle } from "./types.js";
|
|
2
2
|
import { ReservingError } from "./types.js";
|
|
3
3
|
import { cumulativeToIncremental } from "./triangleAlgebra.js";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
assertSameShape,
|
|
6
|
+
isNum,
|
|
7
|
+
lastJointObservedIndex,
|
|
8
|
+
lastObservedIndex,
|
|
9
|
+
safeRatio,
|
|
10
|
+
} from "./util.js";
|
|
5
11
|
|
|
6
12
|
/**
|
|
7
13
|
* Fisher-Lange disposal-rate (average-cost-per-claim-settled) method: the
|
|
@@ -92,25 +98,17 @@ export interface FisherLangeResult {
|
|
|
92
98
|
warnings: string[];
|
|
93
99
|
}
|
|
94
100
|
|
|
95
|
-
function assertSameShape(a: Triangle, b: Triangle): void {
|
|
96
|
-
const sameOrigins =
|
|
97
|
-
a.origins.length === b.origins.length && a.origins.every((o, i) => o === b.origins[i]);
|
|
98
|
-
const sameAges = a.ages.length === b.ages.length && a.ages.every((v, j) => v === b.ages[j]);
|
|
99
|
-
if (!sameOrigins || !sameAges) {
|
|
100
|
-
throw new ReservingError(
|
|
101
|
-
"SHAPE",
|
|
102
|
-
"The paid and closed-count triangles must share identical origins and development ages",
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
101
|
export function runFisherLange(
|
|
108
102
|
paid: Triangle,
|
|
109
103
|
closedCounts: Triangle,
|
|
110
104
|
ultimateCounts: number[],
|
|
111
105
|
options: FisherLangeOptions,
|
|
112
106
|
): FisherLangeResult {
|
|
113
|
-
assertSameShape(
|
|
107
|
+
assertSameShape(
|
|
108
|
+
paid,
|
|
109
|
+
closedCounts,
|
|
110
|
+
"The paid and closed-count triangles must share identical origins and development ages",
|
|
111
|
+
);
|
|
114
112
|
const nOrigins = paid.origins.length;
|
|
115
113
|
const nAges = paid.ages.length;
|
|
116
114
|
if (nAges < 2) {
|
package/src/freqSev.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { TriangleKind, LdfSelections, Triangle } from "./types.js";
|
|
2
2
|
import { ReservingError } from "./types.js";
|
|
3
|
-
import { isNum, lastObservedIndex, safeRatio } from "./util.js";
|
|
3
|
+
import { assertSameShape, isNum, lastObservedIndex, safeRatio } from "./util.js";
|
|
4
4
|
import { runChainLadder } from "./chainladder.js";
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -57,7 +57,11 @@ export interface FrequencySeverityResult {
|
|
|
57
57
|
* missing, zero, or negative count yields a null severity cell.
|
|
58
58
|
*/
|
|
59
59
|
export function severityTriangle(lossTri: Triangle, countTri: Triangle): Triangle {
|
|
60
|
-
assertSameShape(
|
|
60
|
+
assertSameShape(
|
|
61
|
+
lossTri,
|
|
62
|
+
countTri,
|
|
63
|
+
"The loss and count triangles must share identical origins and development ages",
|
|
64
|
+
);
|
|
61
65
|
return {
|
|
62
66
|
kind: lossTri.kind,
|
|
63
67
|
origins: [...lossTri.origins],
|
|
@@ -68,24 +72,16 @@ export function severityTriangle(lossTri: Triangle, countTri: Triangle): Triangl
|
|
|
68
72
|
};
|
|
69
73
|
}
|
|
70
74
|
|
|
71
|
-
function assertSameShape(a: Triangle, b: Triangle): void {
|
|
72
|
-
const sameOrigins =
|
|
73
|
-
a.origins.length === b.origins.length && a.origins.every((o, i) => o === b.origins[i]);
|
|
74
|
-
const sameAges = a.ages.length === b.ages.length && a.ages.every((v, i) => v === b.ages[i]);
|
|
75
|
-
if (!sameOrigins || !sameAges) {
|
|
76
|
-
throw new ReservingError(
|
|
77
|
-
"SHAPE",
|
|
78
|
-
"The loss and count triangles must share identical origins and development ages",
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
75
|
export function runFrequencySeverity(
|
|
84
76
|
lossTri: Triangle,
|
|
85
77
|
countTri: Triangle,
|
|
86
78
|
options: FrequencySeverityOptions,
|
|
87
79
|
): FrequencySeverityResult {
|
|
88
|
-
assertSameShape(
|
|
80
|
+
assertSameShape(
|
|
81
|
+
lossTri,
|
|
82
|
+
countTri,
|
|
83
|
+
"The loss and count triangles must share identical origins and development ages",
|
|
84
|
+
);
|
|
89
85
|
const warnings: string[] = [];
|
|
90
86
|
|
|
91
87
|
const countCl = runChainLadder(countTri, {
|
package/src/index.ts
CHANGED
|
@@ -14,6 +14,9 @@ export * from "./tail.js";
|
|
|
14
14
|
export * from "./berquist.js";
|
|
15
15
|
export * from "./clark.js";
|
|
16
16
|
export * from "./diagnostics.js";
|
|
17
|
+
export * from "./periods.js";
|
|
18
|
+
export * from "./metricDiagnostics.js";
|
|
19
|
+
export * from "./casualtyDiagnostics.js";
|
|
17
20
|
export * from "./mack.js";
|
|
18
21
|
export * from "./capping.js";
|
|
19
22
|
export * from "./ilf.js";
|