Load and validate an OED exposure¶
Run this tutorial yourself
This page is a Jupyter notebook, executed when the docs are built. Download load-validate-oed.ipynb
Set up an environment and open it in Jupyter:
python -m venv venv && source venv/bin/activate
pip install oasislmf jupyterlab matplotlib
jupyter lab load-validate-oed.ipynbThe example data ships in the ODS_Tools repository (under docs/source/tutorials/); tutorials that run a model need that model’s data and the loss engine — follow the prerequisites described on this page.
ods_tools reads OED (Open Exposure Data) files into typed pandas DataFrames and
validates them against the OED standard. This notebook loads a location file,
runs validation, catches an issue, fixes it, and re-validates.
Note
Executable notebook — the cells below run the ods_tools library at docs-build
time (fast, no model run), so the outputs always reflect the current code and OED
schema.
import warnings; warnings.filterwarnings("ignore")
from pathlib import Path
import ods_tools.oed as oed
_c = [Path("data/oed"), Path("tutorials/data/oed"), Path("docs/source/tutorials/data/oed")]
DATA = next((c for c in _c if c.exists()), None)
assert DATA is not None, "OED example data not found"
LOCATION = DATA / "SourceLocOEDPiWind10Currency.csv"
Load an OED location file¶
OedExposure loads each OED source (location, account, reinsurance) into a typed
DataFrame — column data types follow the OED specification.
exposure = oed.OedExposure(location=str(LOCATION))
loc = exposure.location.dataframe
print(f"{loc.shape[0]} locations, {loc.shape[1]} columns")
loc[["PortNumber", "AccNumber", "LocNumber", "CountryCode",
"OccupancyCode", "ConstructionCode", "BuildingTIV"]].head()
10 locations, 25 columns
| PortNumber | AccNumber | LocNumber | CountryCode | OccupancyCode | ConstructionCode | BuildingTIV | |
|---|---|---|---|---|---|---|---|
| 0 | 1 | A11111 | 10002082046 | GB | 1050 | 5000 | 220000.0 |
| 1 | 1 | A11111 | 10002082047 | GB | 1050 | 5000 | 790000.0 |
| 2 | 1 | A11111 | 10002082048 | GB | 1050 | 5000 | 160000.0 |
| 3 | 1 | A11111 | 10002082049 | GB | 1050 | 5000 | 30000.0 |
| 4 | 1 | A11111 | 10002082050 | GB | 1050 | 5000 | 250000.0 |
Validate against the OED standard¶
ods_tools ships the OED validation rules (required/conditional fields, valid code
lists, peril codes, …). We run them in return mode so the findings come back as
data instead of raising:
from ods_tools.oed.common import DEFAULT_VALIDATION_CONFIG
return_config = [{**check, "on_error": "return"} for check in DEFAULT_VALIDATION_CONFIG]
findings = exposure.check(return_config)
print(f"{len(findings)} validation finding(s)")
for f in findings:
print(f"- [{f['name']}] {f['msg'].splitlines()[0]}")
1 validation finding(s)
- [location] Conditionally required column missing.
This example file is missing a conditionally required column: OED requires a
peril to be specified (LocPeril) when perils-related terms are present.
Fix and re-validate¶
Add the missing peril (PiWind is a windstorm model, peril WW1) and re-run
validation:
exposure.location.dataframe["LocPeril"] = "WW1"
findings = exposure.check(return_config)
print(f"{len(findings)} validation finding(s) after fix")
0 validation finding(s) after fix
Enforcing validation¶
Passing check_oed=True (or on_error='raise' in the config) makes ods_tools
raise on the first failing check instead of returning — this is what the CLI does:
ods_tools check --location SourceLocOEDPiWind10Currency.csv
Where next¶
ODTF — transform other exposure formats (e.g. AIR CEDE) into OED.
Currency conversion — convert a multi-currency exposure to a reporting currency.
The OED field definitions and code lists (the standard) are single-sourced in the
ODS_OpenExposureDatarepository.