Windstorm through Oasis: the PiWind lane, with insured and net losses
The model lab's oasis-piwind lane runs PiWind, the reference windstorm model of the Oasis Loss Modelling Framework, over the places you send. It always gives ground-up losses. Send policy terms and reinsurance with the spec and Oasis's own financial module adds two more views of the same simulated years: insured losses and losses net of reinsurance. How to submit a run is in the agent walk; every figure's meaning is in Lab metrics. Every lab model is an open model, run as its authors published it on fixed inputs. Craton has not validated it.
Spec model |
Version | Framework | Where |
|---|---|---|---|
oasis-piwind |
oasislmf-2.5.7-r3 |
Oasis LMF 2.5.7, PiWind at commit 94820c59 |
A demonstration grid about 4 km by 7 km in England: lat 52.734 to 52.795, lon -0.918 to -0.857 |
Basis: a synthetic event set over a demonstration-grade hazard footprint: not observed history, not a forecast. PiWind describes itself as a toy model. It is here because it is the one openly runnable Oasis model, so it shows the whole Oasis pipeline working end to end, financial terms included; its figures are not a view of real windstorm risk.
Up to 100 places and 1 to 100 samples a run. Places outside the grid come back unmodeled, not refused, and a schedule with no place inside answers at once with no loss figure.
On this page
The terms
terms is optional. Leave it out and the run is ground-up only, exactly as before. Every field inside is optional too:
{"model": "oasis-piwind",
"samples": 10,
"terms": {
"policy": {"place_deductible": 10000, "place_limit": 750000,
"account_deductible": 25000, "account_limit": 1000000},
"reinsurance": {"quota_share": {"ceded_share": 0.3},
"layers": [{"attachment": 100000, "limit": 150000},
{"attachment": 250000, "limit": 400000,
"placed_share": 0.8}]}},
"exposure": {"points": [
{"lat": 52.767, "lon": -0.895, "value": 250000},
{"lat": 52.74, "lon": -0.86, "value": 1000000},
{"lat": 25.76, "lon": -80.19, "value": 500000}]}}| Field | What it is | Default |
|---|---|---|
policy.place_deductible |
Deducted from each place's building loss | 0 |
policy.place_limit |
The most paid for one place, after its deductible | none |
policy.account_deductible |
Deducted from the sum over places, after the place terms | 0 |
policy.account_limit |
The most paid for the whole account, after its deductible | none |
policy.account_share |
The share of the account this insurer writes | 1 (all of it) |
reinsurance.quota_share.ceded_share |
The share of every insured loss ceded to reinsurers | none |
reinsurance.layers[].attachment |
Where a catastrophe layer starts, for one event | required |
reinsurance.layers[].limit |
The most a layer pays for one event | required |
reinsurance.layers[].placed_share |
The share of a layer placed with reinsurers | 1 |
Amounts are in the unit of your values; nothing is converted. A deductible or an attachment is 0 or more, a limit is above 0 (null for no limit on a policy limit), and a share is above 0 and at most 1 (0.3 is 30%). Every amount is at most 1,000,000,000,000. reinsurance needs a quota share or at least one layer; there are at most three layers, listed from the lowest up, each starting at or above the top of the one before (its attachment plus its limit). GET /models publishes the fields, labels and caps under the lane's terms. A run with terms takes two to three minutes, and it runs only on the lab's model machines: if none can be reached, it fails with the reason rather than falling back to the lab's own small host.
The steps apply in this order, to every sample of every event:
- each place's deductible, then its limit;
- the account's deductible, limit and share, on the sum over places: this is the insured loss;
- the quota share cedes its share of the insured loss;
- the layers, each event on its own, on what the insurer keeps after the quota share: each pays the part above its attachment, up to its limit, times its placed share. What is left is the loss net of reinsurance.
What comes back
result.metricsstays the ground-up block, with every field it had.result.perspectives.il(insured) andresult.perspectives.ri(net of reinsurance, when reinsurance is given) are full metrics blocks with the same fields, marked byperspective: average annual loss, standard deviation and standard error, OEP and AEP to 1 in 100, TVaR, each place's share, the largest events, and the year and event loss tables.result.terms_summarysays where the ground-up average annual loss goes: a sentence (text) and its parts (split).
Per-place insured and net figures are Oasis's own: it shares account and reinsurance amounts back to the places in proportion to each place's loss at the step before, so the places add up to the total.
A worked example
The spec above: two places inside the grid and one in Miami, which PiWind does not cover, 10 samples. Figures in the unit of the values.
| Ground-up | Insured | Net | |
|---|---|---|---|
| Average annual loss | 53,155 | 42,095 | 15,167 |
| Standard deviation | 163,912 | 142,816 | 39,801 |
| 1 in 10, OEP | 149,798 | 110,336 | 77,235 |
| 1 in 100, OEP | 805,844 | 759,461 | 156,325 |
| 1 in 100, AEP | 868,679 | 798,006 | 174,864 |
| First place (250,000), AAL | 17,029 | 11,713 | 4,947 |
| Second place (1,000,000), AAL | 36,126 | 30,382 | 10,220 |
Of the ground-up average annual loss of 53,155, the policyholder keeps 21%, reinsurers take 51% and the insurer keeps 28%. The layers flatten the net tail: the 1-in-100 net OEP is 156,325 against 759,461 insured.
Each step on its own, on the same schedule:
| Terms | Insured AAL | Net AAL | Net 1 in 100, OEP |
|---|---|---|---|
terms: {} (every default) |
53,155 | ||
| The place and account terms above | 42,095 | ||
| Those, and the 30% quota share | 42,095 | 29,466 | 531,623 |
| Those, and the two layers without the quota share | 42,095 | 20,439 | 289,461 |
| All of it | 42,095 | 15,167 | 156,325 |
With every term at its default the insured loss is the ground-up loss, figure for figure.
The ground-up block of this run is byte for byte the ground-up block of the same spec without terms: terms never change the simulated losses, only what is read from them.
How the terms become OED
The runner writes the terms as Open Exposure Data files (OED 5.0.0), checks all of them with the ods_tools validator before Oasis starts, and passes them to oasislmf model run as the location, account, reinsurance info and reinsurance scope files:
| Terms | OED |
|---|---|
place_deductible, place_limit |
Location file: LocDed1Building, LocLimit1Building (type 0, an amount; LocPeril WW1) |
account_deductible, account_limit, account_share |
Account file, one policy with one layer: LayerAttachment, LayerLimit, LayerParticipation |
quota_share.ceded_share |
Reinsurance info: ReinsType QS, CededPercent, InuringPriority 1 |
layers[] |
Reinsurance info: ReinsType CXL, one ReinsLayerNumber each, OccAttachment, OccLimit, PlacedPercent, InuringPriority 2 (1 without a quota share) |
| Scope | Reinsurance scope: every contract covers the one account |
OED writes "no limit" as 0, so a null limit becomes 0 there. Every file carries the location file's currency code, so Oasis converts nothing.
What it leaves out
- Terms for contents, other structures and business interruption: PiWind values are buildings only.
- Percentage, minimum and maximum deductibles, sublimits, step policies, and more than one policy or layer on the account.
- Per-risk treaties (a surplus share or per-risk excess of loss by place), aggregate layer limits, reinstatements and reinsurance premium: a layer pays in full for every event.
- More than one account, or reinsurance scoped to part of it.
Checked against Oasis itself
PiWind ships an example portfolio beside its location file: ten places, one account with policy layers at a 30% participation, and a surplus share. Run straight through oasislmf model run, with the example's identifiers renamed to the ones the lab writes (Oasis seeds its sampling from them), its ground-up and insured figures are identical, field for field, to the lab's run of the same places with an account deductible of 500,000, a limit of 5,000,000 and a share of 0.3: an insured average annual loss of 36,069.70 both ways. With a quota share and two layers written by hand in PiWind's own reinsurance format, the net figures are identical too. The surplus share itself is a per-risk treaty, which this lane does not take. On one place, for every event and every sample, the insured loss is the ground-up loss less the deductible, capped at the limit, and the net loss is what the quota share and the layer leave of it, to within 0.02; insured never exceeds ground-up, and net never exceeds insured.
Replaying a result
Run ids are content addresses over the spec, the model version and the pinned inputs, so the same spec with the same terms is the same id, and the terms are part of it: the same places with and without terms are two runs. A spec that leaves a field at its default and one that writes the default out are one run. Documents stored under oasislmf-2.5.7-r2 and earlier keep answering their own ids.