Loss runs decide the price — and they’re the messiest document in the packet. Every carrier formats theirs differently: PDFs with one grid per line, Excel with stacked claim-identity headers and grouped Loss / ALAE / Total reserve columns, five years of history across GL, Auto and WC. Miss a reserve column or fumble a status code and the incurred is wrong. Here’s how InsightXtract reads them cleanly.

Why loss runs are hard

  • Stacked claim-identity headers — File # / Loss Date / Eff Date stacked in one cell block, then Claim # / LOB / Exposure in the next.
  • Grouped reserve columns — Loss, ALAE and Total each split into Paid / Reserve / Incurred under a merged group header.
  • Per-line grids — separate GL, Auto and WC tables, each with its own carrier and valuation date.
  • Status & cause vocabularies — “O”, “Open”, “OP” all mean the same thing; cause descriptions vary endlessly.

Flatten the stacked headers

InsightXtract detects the multi-row claim-identity header, flattens each leaf column, and keys the claim on the correct identifier (the leftmost File Number, not a downstream tier claim number):

Raw (stacked identity + grouped reserves)
[ File # / Loss Dt / Eff Dt ][ Loss    ][ ALAE  ][ Total ]
                              Paid|Res|Inc  ...
CIG-0417 | 03/12/24 | ...
Flattened claim row
claim_number: CIG-0417
date_of_loss: 2024-03-12
loss_paid / loss_reserve / loss_incurred
total_incurred: 128,400

Extract every claim, normalized

Each claim becomes a typed row; coverage line, status and cause are normalized against governed glossaries. A slice of the extracted GL loss run:

Claim #CoverageLoss DateStatusCausePaidReserveIncurred
CIG-0417GL coverage_lines2024-03-12open claim_statusesSlip/Fall$42,000$86,400$128,400
CIG-0388GL2023-09-01closedProperty Damage$61,000$0$61,000
… 5 policy years × {GL, Auto, WC} · each with its own carrier & valuation date

Roll it up — deterministically

The loss_run document type declares derived rollups over the claim rows — exact, reproducible, and grouped by line for the loss-pick:

$1.94M
Total incurred
∑ claims.incurred
$1.31M
Total paid
∑ claims.paid
$0.63M
Total reserve
∑ claims.reserve
61
Claim count
count(claims)

Incurred by line falls out of a single group_by rule — GL / Auto / WC subtotals for the loss-development view — and every figure ties back to a claim row and a valuation date loss run p.1.

Incurred by line — the loss pick view

A single group_by coverage_line rule turns the claim rows into the by-line view an underwriter actually prices on — frequency and severity separated per coverage, over five valued years:

Coverage lineClaimsPaidReserveIncurred
General Liability34$742,000$318,000$1,060,000
Automobile18$451,000$205,000$656,000
Workers Compensation9$117,000$107,000$224,000

Because each claim carries a normalized status and cause, the same data supports open-vs-closed, cause-of-loss and large-loss (over-threshold) views without re-reading the PDF — a where filter on the extracted rows is all it takes.

Why “currently valued” and “in full” matter

  • Five years, currently valued — incurred moves as reserves develop, so the valuation date on every claim is captured; a stale loss run misprices the tail.
  • Every claim, not a sample — a large loss run can run to dozens or hundreds of rows and truncate a naive extraction mid-table. The pipeline runs at a 64K output budget and retries with escalation, so the whole table comes through — the total actually adds up.
  • Coded, not transcribed — coverage line, status and cause are normalized to glossaries, so the loss run joins directly to the exposure schedules and the rating, rather than sitting as free text.
  • Cited — each rolled-up figure traces to its claim rows and valuation date, so a file review or an actuary can verify the pick.