About the model · v1.0.0
How Storm Ledger estimates damage
For every building and event the model estimates the gust at roof height, how exposed and how vulnerable the building is, the probability of any damage and the expected repair cost. It then compares that cost with the building's value. It is a model estimate calibrated on fire brigade calls, not on insurer claims.
Calibration
Spatial pattern checked against emergency calls (P2000, NL). Loss level is a model estimate; with your claims data it becomes a calibrated figure. That is the pilot. Fire brigade calls catch only part of the damage: people call insurers, not 112, for a leaking roof or a flooded shed. Expected loss is therefore shown as a band for reporting rates of 2% to 20% of damaged buildings producing a call, around the central 10%.
Unit: street segment within a buurt (4119 segments, 107,923 buildings, 312 with a storm call). P(call) = 1 − exp(−ρ·Σ P_i) with ρ = 0.1 fixed (calls per damaged building; not identifiable from calls alone). AUC is pooled out-of-fold, leave-one-buurt-out. Ciara-only AUC 0.603; logistic benchmark (log Σ MDD_adj, log n) 0.639. P2000 coverage: see data/p2000/SOURCES.md. treePer was fitted to 0 but is kept at its 0.06 prior: Overpass was unavailable for many study buurten (58 mirror failures in this run), so most buurten outside Amsterdam had no tree data and the fit could not see a tree effect. P2000 windows: Ciara 9 Feb 2020 00:00–21:00 (1,378 geocoded incidents); 18 Jan 2018 10:00–18:00 (2,459), so the morning landfall in the west is missing and calls there are under-counted. Some regions are barely present in the archive (Noord-Holland Noord in 2020; the northern provinces in 2018); control buurten drawn there look undamaged when they were only unobserved, which pulls k down and the AUC with it. Half of the study buurten were chosen because they had calls (case-control sampling), which inflates the absolute call rate and so k; the AUC (ranking) is not affected. Treat absolute P(damage) as indicative.
AUC by buurt fold (160)
| Event : buurt | Buildings | Segments with calls | AUC |
|---|---|---|---|
| storm-ciara-2020-02-09:BU05183826 | 839 | 4 | 0.838 |
| storm-ciara-2020-02-09:BU19260101 | 1490 | 4 | 0.804 |
| storm-ciara-2020-02-09:BU06290103 | 1542 | 5 | 0.789 |
| storm-ciara-2020-02-09:BU0363MA09 | 88 | 3 | 0.389 |
| storm-ciara-2020-02-09:BU05182811 | 1209 | 3 | 0.774 |
| storm-ciara-2020-02-09:BU0363KH02 | 56 | 1 | 0.875 |
| storm-ciara-2020-02-09:BU0363KF01 | 500 | 4 | 0.250 |
| storm-ciara-2020-02-09:BU01060003 | 234 | 1 | 0.158 |
| storm-ciara-2020-02-09:BU02160100 | 565 | 1 | 0.923 |
| storm-ciara-2020-02-09:BU19591391 | 1 | 0 | – |
| storm-ciara-2020-02-09:BU0363MQ05 | 89 | 2 | 0.813 |
| storm-ciara-2020-02-09:BU05031104 | 782 | 3 | 0.696 |
| storm-ciara-2020-02-09:BU19920401 | 847 | 4 | 0.419 |
| storm-ciara-2020-02-09:BU0363EB10 | 116 | 2 | 0.900 |
| storm-ciara-2020-02-09:BU0363AC04 | 183 | 2 | 0.938 |
| storm-ciara-2020-02-09:BU02000603 | 1669 | 2 | 0.867 |
| storm-ciara-2020-02-09:BU0363KG01 | 333 | 2 | 0.393 |
| storm-ciara-2020-02-09:BU02890504 | 26 | 1 | 1.000 |
| storm-ciara-2020-02-09:BU0363KL02 | 378 | 3 | 0.467 |
| storm-ciara-2020-02-09:BU19301204 | 133 | 2 | 0.318 |
| storm-ciara-2020-02-09:BU15251405 | 466 | 2 | 0.400 |
| storm-ciara-2020-02-09:BU19480432 | 224 | 3 | 0.758 |
| storm-ciara-2020-02-09:BU04890817 | 390 | 1 | 0.700 |
| storm-ciara-2020-02-09:BU19420000 | 479 | 2 | 0.978 |
| storm-ciara-2020-02-09:BU04411701 | 452 | 1 | 1.000 |
| storm-ciara-2020-02-09:BU02020101 | 282 | 2 | 0.536 |
| storm-ciara-2020-02-09:BU0363KQ04 | 347 | 2 | 0.977 |
| storm-ciara-2020-02-09:BU02280402 | 800 | 2 | 0.341 |
| storm-ciara-2020-02-09:BU0363KE04 | 848 | 6 | 0.483 |
| storm-ciara-2020-02-09:BU02320203 | 545 | 2 | 0.952 |
| storm-ciara-2020-02-09:BU04847011 | 622 | 2 | 0.875 |
| storm-ciara-2020-02-09:BU18920404 | 688 | 1 | 0.947 |
| storm-ciara-2020-02-09:BU02890701 | 626 | 2 | 0.400 |
| storm-ciara-2020-02-09:BU02670105 | 664 | 2 | 0.842 |
| storm-ciara-2020-02-09:BU04020505 | 801 | 2 | 0.923 |
| storm-ciara-2020-02-09:BU05130604 | 1411 | 3 | 0.676 |
| storm-ciara-2020-02-09:BU0363MM08 | 710 | 2 | 0.514 |
| storm-ciara-2020-02-09:BU19311202 | 1524 | 2 | 0.551 |
| storm-ciara-2020-02-09:BU06290102 | 893 | 1 | 0.000 |
| storm-ciara-2020-02-09:BU06290100 | 524 | 0 | – |
| storm-ciara-2020-02-09:BU06290110 | 218 | 1 | 0.167 |
| storm-ciara-2020-02-09:BU06290104 | 689 | 1 | 0.026 |
| storm-ciara-2020-02-09:BU19260102 | 1449 | 0 | – |
| storm-ciara-2020-02-09:BU19260104 | 1355 | 0 | – |
| storm-ciara-2020-02-09:BU19260105 | 926 | 0 | – |
| storm-ciara-2020-02-09:BU19260107 | 1038 | 0 | – |
| storm-ciara-2020-02-09:BU19260110 | 146 | 0 | – |
| storm-ciara-2020-02-09:BU19260114 | 356 | 0 | – |
| storm-ciara-2020-02-09:BU19260115 | 94 | 0 | – |
| storm-ciara-2020-02-09:BU19260116 | 167 | 0 | – |
| storm-ciara-2020-02-09:BU05182718 | 938 | 1 | 0.800 |
| storm-ciara-2020-02-09:BU05183819 | 225 | 1 | 0.773 |
| storm-ciara-2020-02-09:BU05183822 | 284 | 0 | – |
| storm-ciara-2020-02-09:BU05183825 | 1414 | 2 | 0.618 |
| storm-ciara-2020-02-09:BU06030111 | 565 | 0 | – |
| storm-ciara-2020-02-09:BU06030221 | 868 | 0 | – |
| storm-ciara-2020-02-09:BU06030112 | 886 | 0 | – |
| storm-ciara-2020-02-09:BU06030223 | 87 | 1 | 0.600 |
| storm-ciara-2020-02-09:BU19161100 | 633 | 1 | 0.591 |
| storm-ciara-2020-02-09:BU19161202 | 749 | 0 | – |
| storm-ciara-2020-02-09:BU19161200 | 899 | 0 | – |
| storm-ciara-2020-02-09:BU05180448 | 530 | 1 | 0.813 |
| storm-ciara-2020-02-09:BU05180546 | 1767 | 0 | – |
| storm-ciara-2020-02-09:BU05181041 | 175 | 0 | – |
| storm-ciara-2020-02-09:BU05182110 | 1222 | 0 | – |
| storm-ciara-2020-02-09:BU05182144 | 1756 | 1 | 0.875 |
| storm-ciara-2020-02-09:BU05182347 | 549 | 0 | – |
| storm-ciara-2020-02-09:BU05182812 | 1103 | 0 | – |
| storm-ciara-2020-02-09:BU05182814 | 1442 | 1 | 0.926 |
| storm-ciara-2020-02-09:BU05182916 | 1381 | 0 | – |
| storm-ciara-2020-02-09:BU05182915 | 1676 | 0 | – |
| storm-ciara-2020-02-09:BU05183032 | 485 | 0 | – |
| storm-ciara-2020-02-09:BU05182917 | 855 | 0 | – |
| storm-ciara-2020-02-09:BU0363AK05 | 302 | 0 | – |
| storm-ciara-2020-02-09:BU05183033 | 624 | 0 | – |
| storm-ciara-2020-02-09:BU0363AK06 | 28 | 0 | – |
| storm-ciara-2020-02-09:BU0363MA06 | 362 | 0 | – |
| storm-ciara-2020-02-09:BU0363MA07 | 27 | 1 | 0.429 |
| storm-ciara-2020-02-09:BU05020776 | 226 | 1 | 0.538 |
| storm-ciara-2020-02-09:BU05050206 | 338 | 3 | 0.778 |
| storm-2018-01-18:BU01500801 | 703 | 4 | 0.542 |
| storm-2018-01-18:BU09882201 | 1386 | 5 | 0.538 |
| storm-2018-01-18:BU02283001 | 1401 | 7 | 0.725 |
| storm-2018-01-18:BU03010001 | 903 | 6 | 0.712 |
| storm-2018-01-18:BU02021993 | 1268 | 7 | 0.832 |
| storm-2018-01-18:BU01931310 | 1712 | 5 | 0.832 |
| storm-2018-01-18:BU01500101 | 915 | 4 | 0.882 |
| storm-2018-01-18:BU01500306 | 606 | 5 | 0.787 |
| storm-2018-01-18:BU17830902 | 954 | 5 | 0.642 |
| storm-2018-01-18:BU02000101 | 1182 | 9 | 0.624 |
| storm-2018-01-18:BU02000801 | 1081 | 5 | 0.960 |
| storm-2018-01-18:BU01500401 | 1076 | 6 | 0.567 |
| storm-2018-01-18:BU03760105 | 57 | 3 | 0.778 |
| storm-2018-01-18:BU02320005 | 895 | 3 | 0.798 |
| storm-2018-01-18:BU02281003 | 1356 | 6 | 0.573 |
| storm-2018-01-18:BU02431001 | 509 | 4 | 0.947 |
| storm-2018-01-18:BU02220205 | 659 | 4 | 0.611 |
| storm-2018-01-18:BU09881201 | 963 | 5 | 0.627 |
| storm-2018-01-18:BU09831403 | 1015 | 4 | 0.686 |
| storm-2018-01-18:BU09832101 | 1486 | 6 | 0.459 |
| storm-2018-01-18:BU02940000 | 1421 | 7 | 0.542 |
| storm-2018-01-18:BU02283003 | 1400 | 8 | 0.566 |
| storm-2018-01-18:BU01500502 | 542 | 5 | 0.283 |
| storm-2018-01-18:BU02620501 | 345 | 5 | 0.360 |
| storm-2018-01-18:BU02430102 | 458 | 3 | 0.865 |
| storm-2018-01-18:BU19420304 | 309 | 6 | 0.417 |
| storm-2018-01-18:BU19420300 | 339 | 4 | 0.375 |
| storm-2018-01-18:BU05182569 | 891 | 5 | 0.391 |
| storm-2018-01-18:BU02890701 | 626 | 4 | 0.750 |
| storm-2018-01-18:BU02281202 | 699 | 3 | 0.646 |
| storm-2018-01-18:BU17340203 | 385 | 3 | 0.489 |
| storm-2018-01-18:BU02741203 | 235 | 4 | 0.786 |
| storm-2018-01-18:BU01500902 | 628 | 3 | 0.524 |
| storm-2018-01-18:BU02281101 | 1238 | 3 | 0.648 |
| storm-2018-01-18:BU01770103 | 138 | 4 | 1.000 |
| storm-2018-01-18:BU09881301 | 748 | 4 | 0.625 |
| storm-2018-01-18:BU01500604 | 765 | 3 | 0.719 |
| storm-2018-01-18:BU01500802 | 841 | 3 | 0.492 |
| storm-2018-01-18:BU0363SD03 | 999 | 4 | 0.777 |
| storm-2018-01-18:BU03071301 | 323 | 0 | – |
| storm-2018-01-18:BU02021884 | 654 | 0 | – |
| storm-2018-01-18:BU02021886 | 657 | 0 | – |
| storm-2018-01-18:BU02021885 | 128 | 0 | – |
| storm-2018-01-18:BU02021989 | 367 | 0 | – |
| storm-2018-01-18:BU02022319 | 304 | 0 | – |
| storm-2018-01-18:BU02021887 | 273 | 0 | – |
| storm-2018-01-18:BU09882301 | 884 | 1 | 0.944 |
| storm-2018-01-18:BU01500803 | 633 | 0 | – |
| storm-2018-01-18:BU02022317 | 1497 | 0 | – |
| storm-2018-01-18:BU01501001 | 157 | 1 | 0.769 |
| storm-2018-01-18:BU01500901 | 1077 | 1 | 0.050 |
| storm-2018-01-18:BU01501007 | 507 | 0 | – |
| storm-2018-01-18:BU03010101 | 345 | 0 | – |
| storm-2018-01-18:BU01501005 | 429 | 1 | 0.143 |
| storm-2018-01-18:BU03010102 | 222 | 1 | 0.000 |
| storm-2018-01-18:BU03010104 | 621 | 0 | – |
| storm-2018-01-18:BU03010201 | 574 | 2 | 0.269 |
| storm-2018-01-18:BU01500102 | 302 | 1 | 0.706 |
| storm-2018-01-18:BU03010103 | 528 | 0 | – |
| storm-2018-01-18:BU01500103 | 305 | 1 | 0.174 |
| storm-2018-01-18:BU01500104 | 120 | 0 | – |
| storm-2018-01-18:BU01500106 | 247 | 0 | – |
| storm-2018-01-18:BU01500107 | 454 | 0 | – |
| storm-2018-01-18:BU01500301 | 441 | 2 | 1.000 |
| storm-2018-01-18:BU01500303 | 723 | 0 | – |
| storm-2018-01-18:BU01500105 | 278 | 1 | 0.654 |
| storm-2018-01-18:BU01500403 | 447 | 2 | 0.667 |
| storm-2018-01-18:BU02850106 | 119 | 2 | 0.500 |
| storm-2018-01-18:BU01500404 | 765 | 1 | 1.000 |
| storm-2018-01-18:BU17830901 | 374 | 1 | 0.700 |
| storm-2018-01-18:BU01931300 | 502 | 0 | – |
| storm-2018-01-18:BU17830903 | 711 | 0 | – |
| storm-2018-01-18:BU01935000 | 471 | 0 | – |
| storm-2018-01-18:BU01931320 | 1237 | 2 | 0.522 |
| storm-2018-01-18:BU01935010 | 360 | 0 | – |
| storm-2018-01-18:BU01931200 | 1177 | 0 | – |
| storm-2018-01-18:BU01935020 | 521 | 0 | – |
| storm-2018-01-18:BU01935130 | 234 | 0 | – |
| storm-2018-01-18:BU01935030 | 1133 | 0 | – |
| storm-2018-01-18:BU01500601 | 478 | 3 | 0.867 |
Check against insured losses
The probability ranking is calibrated; the euro amounts are not. A rough outside check uses what Dutch insurers reported for the two calibration storms:
- Storm of 18 January 2018: first Verbond van Verzekeraars estimate about €90 m for homes and cars, later reported at about €436–450 m in total; together with the storm of 3 January insurers handled close to 300,000 claims (Hart van Nederland, NOS, ESB).
- Storm Ciara, 9 February 2020: first Verbond estimate about €150 m, mainly homes and cars (report).
That puts the average claim at roughly €1,500 (including cars). In the five demo areas the model's typical repair given that a building is damaged is €180–1,300 (median per area), and a building with many dwellings would usually produce several claims. Two separate questions follow.
How many buildings are damaged is set by k = 1147, fitted on fire-brigade calls with a fixed share ρ = 0.1 of damaged buildings producing a call. A few thousand P2000 calls against several hundred thousand claims suggests ρ is nearer 0.01, which would mean many more damaged buildings than shown, each with a smaller loss: with P = 1 − exp(−k·MDDadj) the loss of a damaged building averages about 1/k of rebuild cost (0.09% now). That split is a modelling assumption, not data.
How much money in total is Σ MDDadj × rebuild cost. It does not depend on k: it comes straight from the Schwierz et al. (2010) curve and the €/m³ rule, and has not yet been compared with the national insured totals above. The next calibration step is to run the model for the whole country for these two storms and scale the curve to the insured totals. Until then, read euro amounts as indicative and use P(damage) for ranking.
Equations
- Gust at the building. g10 = inverse-distance-weighted (power 2) event peak of hourly max gust FX at the 4 nearest KNMI land stations. g(h) = g10 · (h/10)^α, α = 0.22 where built-up share within 100 m exceeds 0.15, else 0.14. h is the 70th-percentile roof height above ground (min 3 m).
- Exposure E = clamp(0.6, 1.4, 1 + 0.25·log₂(clamp(h/h̄up, 0.5, 2)) + 0.5·(fetch/200 − 0.5) + 0.2·corner + 0.05·detached). h̄up is the mean roof height of buildings within 60 m upwind (±30°). Fetch is the upwind distance to the nearest building; water and parks hold no buildings, so they count as open.
- Vulnerability V = roof type × face orientation (area-weighted: windward 0.85, edge 1.15, leeward 1.3, flat 1) × slope band × build-year band × floors band × (1 + 0.06·min(ntrees, 6)), where ntrees counts trees taller than their distance to the facade.
- Mean damage degree MDD = min(1, a·max(0, g − g0)^b) with a = 1.3415e-13, b = 5.2874, g0 = 72 km/h, fitted to the Schwierz et al. (2010) curve (PAA × MDD). MDD_adj = min(1, MDD · E · V).
- Damage probability P = 1 − exp(−k · MDD_adj). Given damage, the damage ratio is exponential with mean MDD_adj/P, which splits P into minor (< 1% of reconstruction cost), moderate (< 8%) and severe. Expected state: none if P < 5%, else severe if MDD_adj ≥ 0.03, moderate if ≥ 0.004, otherwise minor.
- Value impact repair = MDD_adj × reconstruction cost, reconstruction = 3DBAG LoD 2.2 volume × €/m³ by class. Value decrease % = expected repair ÷ value × 100. P10 and P90 are quantiles of the same damage distribution. This is repair cost relative to value, not a market price effect.
- Value from the CSV when given; otherwise CBS mean WOZ × dwellings in the buurt, shared by floor area (area view), or, in the portfolio, the buurt mean WOZ scaled by the addressor the buurt mean WOZ per address (portfolio, which carries its floor-area share of the building's repair cost)apos;s usable area relative to a 100 m² dwelling; the address carries its floor-area share of the building's repair cost.
Every parameter
| Parameter | Value |
|---|---|
| version | 1.0.0 |
| idwStations | 4 |
| idwPower | 2 |
| alphaUrban | 0.22 |
| alphaOpen | 0.14 |
| urbanDensity | 0.15 |
| urbanRadiusM | 100 |
| minHeightM | 3 |
| shelterRadiusM | 60 |
| sectorHalfDeg | 30 |
| fetchMaxM | 200 |
| wShelter | 0.25 |
| wFetch | 0.5 |
| wCorner | 0.2 |
| wDetached | 0.05 |
| exposureMin | 0.6 |
| exposureMax | 1.4 |
| roofType | slanted: 1.1, multiple horizontal: 0.9, single horizontal: 0.85, horizontal: 0.85, unknown: 1 |
| faceWindward | 0.85 |
| faceEdge | 1.15 |
| faceLeeward | 1.3 |
| faceFlat | 1 |
| slopeBands | max 10 → f 0.9; max 15 → f 1; max 35 → f 1.25; max 50 → f 1.1; max 91 → f 1 |
| yearBands | before 1945 → f 1.3; before 1975 → f 1.15; before 2000 → f 1; before 9999 → f 0.8 |
| yearUnknown | 1.1 |
| floorBands | max 3 → f 1; max 6 → f 1.08; max 999 → f 1.15 |
| treePer | 0.06 |
| treeCap | 6 |
| treeSearchM | 30 |
| treeDefaultHeightM | 10 |
| mddA | 1.3415e-13 |
| mddB | 5.2874 |
| mddG0 | 72 |
| k | 1147 |
| pVisible | 0.05 |
| tModerate | 0.004 |
| tSevere | 0.03 |
| ratioMinorMax | 0.01 |
| ratioModerateMax | 0.08 |
| eurPerM3 | house: 450, apartment: 400, large: 280, annex: 180 |
| refDwellingM2 | 100 |
| reportingRate | 0.1 |
Defined in model/params.ts; fitted values come from model/calibration.json, written by scripts/calibrate.ts.
Sources and licences
| Need | Source | Licence |
|---|---|---|
| Buildings, heights, roof faces | 3DBAG (TU Delft 3D geoinformation), LoD 2.2, api.3dbag.nl | CC BY 4.0 |
| Streets, water, parks, trees | OpenStreetMap via Overpass API | ODbL |
| Street trees with height class | Gemeente Amsterdam, Bomen (stamgegevens), api.data.amsterdam.nl; elsewhere OSM natural=tree | CC0 / ODbL |
| Place search, address → building | PDOK Locatieserver v3.1; Kadaster BAG OGC API v2 (verblijfsobject → pand) | CC0 |
| Buurt and wijk boundaries, mean WOZ value, dwellings | CBS Wijk- en buurtkaart 2024 via PDOK | CC BY 4.0 |
| Province and municipality outlines | CBS Gebiedsindelingen (generalised) via PDOK | CC BY 4.0 |
| Wind gusts (FX) and direction (DD) | KNMI hourly station data (uurgegevens) | CC BY 4.0 |
| Wind gusts, Germany | DWD Climate Data Center, 10-minute extreme wind (FX_10, DX_10), 26 events | CC BY 4.0 |
| Buildings, streets and water, Germany | OpenStreetMap via OpenFreeMap vector tiles (render height; lower geometric detail, no roof faces) | ODbL |
| Place search and addresses, Germany | Photon (komoot), OpenStreetMap data | ODbL |
| Forecasts in the sales demo | NOAA GFS 0.5°, NCEI archive, runs of 6, 7 and 8 February 2020 | Public domain |
| Event catalogue | KNMI code orange/red archive and event factsheets, checked against station data | CC BY 4.0 |
| Damage curve | Schwierz et al. (2010), Climatic Change 101:485–514, doi:10.1007/s10584-009-9712-1; table as in CLIMADA ImpfStormEurope.from_schwierz | Published |
| Ground truth | P2000 fire brigade storm calls (public archive), geocoded with PDOK | See data/p2000/SOURCES.md |
What is approximated, and what would replace it
| Approximation | Better data |
|---|---|
| Calibrated on fire brigade calls, which capture a small, unknown share of damage and are geocoded to street level. | Insurer claims per address (Verbond van Verzekeraars / individual insurers), with claim amount. |
| Roof covering is inferred from roof type and slope (tiles assumed on pitched roofs). | Roof material per building (aerial imagery classification or municipal roof registers). |
| Building value is a buurt mean WOZ shared by floor area. | WOZ value per address (WOZ-waardeloket / Basisregistratie WOZ). |
| Reconstruction cost is volume × a €/m³ rule of thumb by class. | Herbouwwaarde per building from insurers or taxation reports. |
| Gusts are interpolated from about 45 KNMI stations; convective gusts between stations are missed. | ERA5 fg10 or HARMONIE-AROME gust grids; radar-derived downburst tracks. |
| Wind direction per building is the station direction at its peak hour. | Gridded wind field at the hour of the local peak. |
| Tree heights come from Amsterdam's register; elsewhere OSM trees, usually without height (default 10 m). | AHN-derived tree crowns and heights or other municipal tree registers. |
| Hail, rain and flood are listed but not modelled. | KNMI hail and radar products, flood footprints with depth, and fragility curves. |