diff --git a/docs/.gitignore b/docs/.gitignore
new file mode 100644
index 00000000..b22a55e9
--- /dev/null
+++ b/docs/.gitignore
@@ -0,0 +1,6 @@
+build/
+source/reference/_generated/
+**/__pycache__/
+.jupyter_cache/
+jupyter_execute/
+.DS_Store
diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644
index 00000000..11797053
--- /dev/null
+++ b/docs/Makefile
@@ -0,0 +1,13 @@
+# Minimal Sphinx makefile for the ORD reference site
+SPHINXOPTS ?=
+SPHINXBUILD ?= sphinx-build
+SOURCEDIR = source
+BUILDDIR = build
+
+help:
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+%: Makefile
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/docs/source/_ext/gen_oed_reference.py b/docs/source/_ext/gen_oed_reference.py
new file mode 100644
index 00000000..a47f602c
--- /dev/null
+++ b/docs/source/_ext/gen_oed_reference.py
@@ -0,0 +1,134 @@
+"""Generate OED reference pages from ``oed.json`` (single source of truth).
+
+The OED standard is defined by ``oed.json`` at the repo root — the same machine-readable
+spec that ods-tools consumes. Rather than hand-maintain reference tables, this extension
+reads ``oed.json`` at build time and writes MyST Markdown into ``reference/_generated/``
+which the reference pages include. Edit ``oed.json`` (and its source CSVs), not the
+generated Markdown.
+
+Runs on the Sphinx ``config-inited`` event; also runnable standalone for quick checks.
+"""
+import json
+import os
+
+HERE = os.path.dirname(os.path.abspath(__file__))
+REPO_ROOT = os.path.abspath(os.path.join(HERE, os.pardir, os.pardir, os.pardir))
+OED_JSON = os.path.join(REPO_ROOT, "oed.json")
+OUT_DIR = os.path.join(HERE, os.pardir, "reference", "_generated")
+
+# input-file groups, in exposure-modelling order
+FILE_ORDER = [("Loc", "Location"), ("Acc", "Account"),
+ ("ReinsInfo", "Reinsurance Info"), ("ReinsScope", "Reinsurance Scope")]
+
+
+def _cell(text):
+ return str(text).replace("|", "\\|").replace("\n", " ").replace("\r", " ").strip()
+
+
+def _pipe_table(columns, rows):
+ out = ["| " + " | ".join(columns) + " |",
+ "| " + " | ".join(["---"] * len(columns)) + " |"]
+ for row in rows:
+ out.append("| " + " | ".join(_cell(c) for c in row) + " |")
+ return "\n".join(out)
+
+
+def _write(name, text):
+ os.makedirs(OUT_DIR, exist_ok=True)
+ with open(os.path.join(OUT_DIR, name), "w", encoding="utf-8") as fh:
+ fh.write(text + "\n")
+
+
+def generate_fields(oed):
+ """input_fields -> field reference, grouped by input file."""
+ fields = oed["input_fields"]
+ parts = [""]
+ total = 0
+ for key, title in FILE_ORDER:
+ recs = fields.get(key)
+ if not recs:
+ continue
+ parts.append(f"\n## {title} (`{key}`)\n")
+ rows = []
+ for rec in recs.values():
+ rows.append([
+ rec.get("Input Field Name", ""),
+ rec.get("Type & Description", ""),
+ rec.get("Data Type", ""),
+ rec.get("Property field status", ""),
+ rec.get("Default", ""),
+ ])
+ total += 1
+ parts.append(_pipe_table(
+ ["Field", "Description", "Data type", "Status", "Default"], rows))
+ _write("oed_fields.md", "\n".join(parts))
+ return total
+
+
+def generate_values(oed):
+ """Coded value lists -> code reference tables."""
+ parts = [""]
+ total = 0
+
+ # perils: nested under 'info'
+ perils = oed.get("perils", {}).get("info", {})
+ if perils:
+ parts.append("\n## Perils\n")
+ rows = [[code, r.get("DB table PerilCode", ""), r.get("Peril Description", ""),
+ r.get("Grouped PerilCode", "")] for code, r in perils.items()]
+ parts.append(_pipe_table(["Code", "PerilCode", "Description", "Grouped"], rows))
+ total += len(rows)
+
+ def simple(key, title, cols):
+ nonlocal total
+ v = oed.get(key)
+ if not isinstance(v, dict):
+ return
+ parts.append(f"\n## {title}\n")
+ rows = [[code] + [rec.get(c, "") for _, c in cols] for code, rec in v.items()]
+ parts.append(_pipe_table(["Code"] + [h for h, _ in cols], rows))
+ total += len(rows)
+
+ simple("occupancy", "Occupancy codes",
+ [("Name", "Name"), ("Description", "Description"), ("Broad Category", "Broad Category")])
+ simple("construction", "Construction codes",
+ [("Name", "Name"), ("Description", "Description"), ("Broad Category", "Broad Category")])
+ simple("country", "Country codes", [("Name", "Name")])
+ simple("CoverageValues", "Coverage types",
+ [("CoverageID", "CoverageID"), ("Description", "Description"), ("Type", "Type")])
+ _write("oed_values.md", "\n".join(parts))
+ return total
+
+
+def _ensure_oed_json():
+ """oed.json is a generated artifact (utils/gen-json.py builds it from the CSVs) and is not
+ committed. Generate it if missing so the docs build is self-sufficient in CI."""
+ if os.path.exists(OED_JSON):
+ return
+ import subprocess
+ import sys
+ gen = os.path.join(REPO_ROOT, "utils", "gen-json.py")
+ subprocess.run([sys.executable, gen, "--output-path", OED_JSON], cwd=REPO_ROOT, check=True)
+
+
+def run(app=None, config=None):
+ _ensure_oed_json()
+ with open(OED_JSON, encoding="utf-8") as fh:
+ oed = json.load(fh)
+ n_fields = generate_fields(oed)
+ n_values = generate_values(oed)
+ msg = f"[gen_oed_reference] wrote {n_fields} fields, {n_values} coded values -> reference/_generated/"
+ if app is not None:
+ from sphinx.util import logging
+ logging.getLogger(__name__).info(msg)
+ else:
+ print(msg)
+
+
+def setup(app):
+ app.connect("config-inited", run)
+ return {"parallel_read_safe": True, "parallel_write_safe": True}
+
+
+if __name__ == "__main__":
+ run()
diff --git a/docs/source/_static/OASIS_LMF_COLOUR.png b/docs/source/_static/OASIS_LMF_COLOUR.png
new file mode 100644
index 00000000..eac8dc49
Binary files /dev/null and b/docs/source/_static/OASIS_LMF_COLOUR.png differ
diff --git a/docs/source/_static/OASIS_LMF_WHITE.png b/docs/source/_static/OASIS_LMF_WHITE.png
new file mode 100644
index 00000000..8aec5a7a
Binary files /dev/null and b/docs/source/_static/OASIS_LMF_WHITE.png differ
diff --git a/docs/source/conf.py b/docs/source/conf.py
new file mode 100644
index 00000000..71525338
--- /dev/null
+++ b/docs/source/conf.py
@@ -0,0 +1,77 @@
+"""Sphinx configuration for the Open Exposure Data (OED) standard reference site.
+
+The field and coded-value reference is generated at build time from ``oed.json`` by the
+local ``gen_oed_reference`` extension (single source of truth). Theme and MyST setup mirror
+the other OasisLMF documentation sites for a consistent aggregated site.
+"""
+import datetime
+import os
+import sys
+
+sys.path.insert(0, os.path.abspath("_ext"))
+
+project = "Open Exposure Data (OED)"
+author = "Oasis LMF"
+copyright = f"{datetime.date.today().year} Oasis LMF"
+
+extensions = [
+ "myst_parser",
+ "sphinx_design",
+ "sphinx_copybutton",
+ "gen_oed_reference", # build-time reference generation from oed.json
+]
+
+source_suffix = {".rst": "restructuredtext", ".md": "markdown"}
+master_doc = "index"
+language = "en"
+# _generated/*.md are include-only fragments, not standalone documents
+exclude_patterns = ["reference/_generated/**"]
+
+myst_enable_extensions = ["colon_fence", "deflist", "substitution", "tasklist"]
+myst_heading_anchors = 6
+
+html_theme = "furo"
+html_title = "Open Exposure Data (OED)"
+html_static_path = ["_static"] if os.path.isdir(os.path.join(os.path.dirname(__file__), "_static")) else []
+
+
+# -- Cross-component links (intersphinx, aggregated site) --------------------
+# The GenerateDocs orchestrator sets OASIS_INTERSPHINX_MAP (JSON) to point cross-references at
+# the other components' built inventories; standalone builds add nothing. Use explicit roles,
+# e.g. {external+ord:doc}`reference/tables` or :external+oed:ref:`some-label`.
+import json as _ix_json
+import os as _ix_os
+if "sphinx.ext.intersphinx" not in extensions:
+ extensions = list(extensions) + ["sphinx.ext.intersphinx"]
+try:
+ intersphinx_mapping
+except NameError:
+ intersphinx_mapping = {}
+intersphinx_mapping.update({
+ _k: (_v[0], _v[1])
+ for _k, _v in _ix_json.loads(_ix_os.environ.get("OASIS_INTERSPHINX_MAP") or "{}").items()
+})
+# -- Oasis shared branding (logo, palette, GitHub footer) -------------------
+if globals().get("html_theme") == "furo":
+ if "_static" not in (globals().get("html_static_path") or []):
+ html_static_path = list(globals().get("html_static_path") or []) + ["_static"]
+ try:
+ html_theme_options
+ except NameError:
+ html_theme_options = {}
+ html_theme_options.setdefault("light_logo", "OASIS_LMF_COLOUR.png")
+ html_theme_options.setdefault("dark_logo", "OASIS_LMF_WHITE.png")
+ _lcv = html_theme_options.setdefault("light_css_variables", {})
+ _lcv.setdefault("color-brand-primary", "#862633")
+ _lcv.setdefault("color-brand-content", "#d22630")
+ _lcv.setdefault("font-stack", "Raleway, sans-serif")
+ _dcv = html_theme_options.setdefault("dark_css_variables", {})
+ _dcv.setdefault("color-brand-primary", "#e2919b")
+ _dcv.setdefault("color-brand-content", "#ef8b93")
+ # GitHub link — Furo's conventional spot is the footer icons (bottom of every page)
+ html_theme_options.setdefault("footer_icons", [{
+ "name": "GitHub", "url": "https://github.com/OasisLMF", "class": "",
+ "html": '',
+ }])
+ if "https://fonts.googleapis.com/css?family=Raleway" not in (globals().get("html_css_files") or []):
+ html_css_files = list(globals().get("html_css_files") or []) + ["https://fonts.googleapis.com/css?family=Raleway"]
diff --git a/docs/source/explanation/asset-details.rst b/docs/source/explanation/asset-details.rst
new file mode 100644
index 00000000..70e9a2bb
--- /dev/null
+++ b/docs/source/explanation/asset-details.rst
@@ -0,0 +1,113 @@
+Asset Related Details
+======================
+
+The following sections describe the OED specification for the asset value, usage, construction, and other modifiers that can influence the susceptibility of an asset to damage from a peril.
+Coverage total insurable value (TIV)
+
+Total insurable value (TIV) for each property is captured in four location level fields:
+
+• **BuildingTIV**: The total insurable value of the buildings.
+
+• **ContentsTIV**: The total insurance value of contents and stock.
+
+• **BITIV**: The total business interruption, or other time related, total insurable value.
+
+• **OtherTIV**: The total insurable value for elements other than the main building / contents / time elements. Typically used to represent the TIV for outbuildings / ap
+
+Total insurable value is not peril dependent. The currency of the TIV is specified in the **LocCurrency** field.
+
+|
+
+Occupancy Type
+##############
+
+Occupancy codes are stored in the **OccupancyCode** field. The occupancy type list is predominantly a one to one mapping from the AIR CEDE occupancy codes, although some extra codes have been added. The broad categories of code and the number ranges are shown in the table below.
+
+
+.. csv-table::
+ :widths: 10,10
+ :header: "OED Occupancy Code Range", "Broad Category of Occupancy"
+
+ "1000", "Unknown"
+ "1050 – 1099", "Residential"
+ "1100 – 1149", "Commercial"
+ "1150 – 1199", "Industrial"
+ "1200 – 1249", "Religion / Government / Education"
+ "1250 – 1299", "Transportation"
+ "1300 – 1349", "Utilities"
+ "1350 – 1399", "Miscellaneous"
+ "2000 – 2799", "Industrial Facility"
+ "3000 – 3999", "Offshore"
+
+Although the code ranges above infer an extremely long list of codes there are less than 200 distinct occupancy codes in total. Yachts and automobiles are included under construction type codes rather than occupancy codes.
+Some users may have translated from a different (original) occupancy code to the OED occupancy code but would like to store the original occupancy code information. This can be done using the **OrgOccupancyScheme** and **OrgOccupancyCode** fields.
+
+|
+
+Construction Type
+##################
+
+Construction codes are stored in the **ConstructionCode** field. The construction type list is predominantly a one to one mapping from the AIR CEDE construction codes, although some extra codes have been added. The broad categories of code and the number ranges are shown in table below.
+
+
+.. csv-table::
+ :widths: 10,10
+ :header: "OED Construction Code Range", "Broad Category of Construction"
+
+ "5000", "Unknown"
+ "5050 – 5099", "Wood"
+ "5100 – 5149", "Masonry"
+ "5150 – 5199", "Concrete"
+ "5200 – 5249", "Steel"
+ "5250 – 5299", "Composite"
+ "5300 – 5349", "Special"
+ "5350 – 5399", "Mobile Homes"
+ "5400 – 5449", "Bridges"
+ "5450 – 5499", "Roads, Railroads, Runways"
+ "5500 – 5549", "Dams"
+ "5550 – 5599", "Tunnels"
+ "5600 – 5649", "Storage Tanks"
+ "5650 – 5699", "Pipelines"
+ "5700 – 5749", "Chimneys"
+ "5750 – 5799", "Towers"
+ "5800 – 5849", "Equipment"
+ "5850 – 5899", "Automobiles"
+ "5900 – 5949", "Yachts"
+ "5950 – 5999", "Miscellaneous"
+ "6000 – 6099", "Marine Cargo General"
+ "6100 – 6149", "Marine Cargo Combustible"
+ "6150 – 6199", "Marine Cargo Non-Combustible"
+ "7000 - 7999", "Offshore"
+
+|
+
+Although the code ranges above infer a very long list of codes there are less than 200 construction codes in total.
+Some users may have translated from a different (original) construction code scheme to the OED construction code scheme but would like to store the original construction code information. This can be done using the **OrgConstructionScheme** and **OrgConstructionCode** fields.
+
+|
+
+Other Common Modifiers
+######################
+
+While different catastrophe models will use different modifiers to adjust the vulnerability of an asset, the following are the most commonly used modifiers:
+
+• **YearBuilt**: the year the building was built. **YearUpgraded**, **RoofYearBuil** are also modifiers that allow the user to add additional information.
+
+• **NumberOfStoreys**: The total number of storeys in a building. **BuildingHeight** is also available for the user to add in the precise height of the building if this is known. **FloorsOccupied** allows the specific floors in the building that are occupied to be specified.
+
+• **NumberOfBuildings**: The number of buildings represented by this location. This is commonly used to indicate the presence of aggregated data. If, instead, a user has specific details about different locations, but wants to denote a linkage of some kind between each location then the **LocGroup** field can be used to link individual locations (either for reporting purposes or to define a reinsurance ‘risk’ level). **CorrelationGroup** can be used to denote a correlation in secondary uncertainty between groups of locations.
+
+• **FloorArea** & **FloorAreaUnit**: The total floor area occupied, summing the area of multiple floors.
+
+Other modifiers, either peril specific or less commonly used by models, are available and are listed in the specification spreadsheet. They can be identified by filtering on the SecMod column in the ‘OED Input Fields’ sheet in the specification spreadsheet.
+
+|
+
+Flexi-tables
+############
+
+Despite the wide range of fields available in OED, there is always the possibility that a user needs to enter or store information without a corresponding OED field. This can be achieved through the flexi-table functionality within OED, which essentially provides a key-value pair back end table at the main hierarchical levels.
+To enter additional field / values, a user can enter additional columns: **FlexiLocZZZ**, **FlexPolZZZ**, **FlexiAccZZZ**, where ‘ZZZ’ contains the name of the new field.
+For example, if a user wants to store information on house colour, they could add an additional column to the location input file with the fieldname *FlexiLocHouseColour*.
+
+
diff --git a/docs/source/explanation/financial-policy-conditions.rst b/docs/source/explanation/financial-policy-conditions.rst
new file mode 100644
index 00000000..578b93b8
--- /dev/null
+++ b/docs/source/explanation/financial-policy-conditions.rst
@@ -0,0 +1,596 @@
+
+
+Policy Special Conditions
+#########################
+
+Policy special conditions are financial structures that apply to only a subset of locations within a policy. They apply after all location terms, but before any blanket policy terms or layer terms. As well as the deductibles and limits for conditions which begin with 'Cond' and follow the same field name convention as for location and policy terms, there are the following required fields:
+
+In the OED location and account file:
+
+* **CondTag** identifies the locations that a condition applies to in the locations file, and links them to the condition terms in the account file.
+
+In the OED account file:
+
+* **CondNumber** identifies a unique set of financial terms of the condition
+* **CondPeril** identifies the perils that the condition applies to
+* **CondPriority** identifies the order in which special conditions apply in case more than one condition applies to the same locations.
+
+Optionally in the OED account file;
+
+* **CondName** is a descriptive field for the condition
+* **CondClass** can be used to specify a policy restriction condition
+
+|
+
+CondTag
+#######
+
+The scope of each special condition is specified using a **CondTag** on each location in the location input file that corresponds with the **CondTag** in the account input file. This field is normally a meaningful string describing the scope of the condition, such as 'California'.
+
+|
+
+**Example 1 - a California sub-limit**
+
+|
+
+OED Location file:
+
+.. csv-table::
+ :widths: 15,15,15,15,20
+ :header: "AccNumber", "LocNumber", "CountryCode", "AreaCode", "CondTag"
+
+ "Acc1", "Loc1", "US", "CA", "California"
+ "Acc1", "Loc2", "US", "CA", "California"
+ "Acc1", "Loc3", "US", "IN", ""
+ "Acc1", "Loc4", "US", "NV", ""
+
+The **CondTag** is also included in the accounts file for the policies the condition applies to.
+
+|
+
+OED Account file:
+
+.. csv-table::
+ :widths: 20,20,20,20,20
+ :header: "AccNumber", "PolNumber", "CondTag", "CondNumber", "CondLimit6All"
+
+ "Acc1", "Pol1", "California", "1", "10,000,000"
+
+In this example, a 'sub-limit' of $10,000,000 applies to the combined loss for locations 1 and 2 in California. This applies after any location terms specified and before any policy terms which apply to all locations under the account.
+
+Some example ground up losses are as follows;
+
+|
+
+Example losses:
+
+.. csv-table::
+ :widths: 15,15,15,15,20
+ :header: "AccNumber", "LocNumber", "CountryCode", "AreaCode", "Ground up loss"
+
+ "Acc1", "Loc1", "US", "CA", "5,000,000"
+ "Acc1", "Loc2", "US", "CA", "7,000,000"
+ "Acc1", "Loc3", "US", "IN", "0"
+ "Acc1", "Loc4", "US", "NV", "4,000,000"
+
+The policy loss for an earthquake affecting California and Nevada in this scenario would be **$14,000,000** due to the California losses being limited to $10,000,000.
+
+It is common to have multiple conditions on a policy, applying to different groups of locations. When this is the case, the policy record in the account file must be duplicated for each different **CondTag** on the locations, as demonstrated in the next example.
+
+|
+
+
+CondNumber
+##########
+
+The set of financial terms for each condition is identified by the **CondNumber** field in the account file.
+
+For each policy in the account file, the financial terms identified by the **CondNumber** will be applied to the locations under the scope defined by each CondTag.
+
+In Example 2, **CondNumber** 1 is a $10,000,000 sub-limit applies to California losses and **CondNumber** 2 is a $15,000,000 sublimit for losses in the New Madrid region.
+
+**CondNumber** is normally a policy condition reference number, and may be numeric or alphanumeric. An optional field **CondName** can be used to describe the condition in meaningful terms.
+
+Note that although these types of conditions are referred to as sub-limits, they can be any combination of the regular types of financial terms such as deductibles, min and max deductibles, and limits.
+
+|
+
+**Example 2 - a California sub-limit and a New Madrid sub-limit**
+
+|
+
+OED Location file:
+
+.. csv-table::
+ :widths: 15,15,15,15,20
+ :header: "AccNumber", "LocNumber", "CountryCode", "AreaCode", "CondTag"
+
+ "Acc2", "Loc1", "US", "CA", "California"
+ "Acc2", "Loc2", "US", "CA", "California"
+ "Acc2", "Loc3", "US", "IN", "New Madrid"
+ "Acc2", "Loc4", "US", "NV", ""
+
+|
+
+OED Account file:
+
+.. csv-table::
+ :widths: 20,20,20,20,20,20
+ :header: "AccNumber", "PolNumber", "CondTag", "CondNumber", "CondLimit6All", "CondName"
+
+ "Acc2", "Pol1", "California", "1", "10,000,000", "CA sub-limit"
+ "Acc2", "Pol1", "New Madrid", "2", "15,000,000", "NM sub-limit"
+
+In this example, a sub-limit of $10,000,000 will apply to the sum of losses from locations 1 and 2 for an earthquake in the California area, and a sub-limit of $15,000,000 will apply to the loss from Indiana location 3 from an earthquake in the New Madrid region, before any policy terms.
+
+No sub-limits apply to losses for the Nevada location 4, because it is not subject to any condition (CondTag field is blank).
+
+|
+
+CondPeril
+#########
+
+Commonly, sub-limit conditions are peril-specific as well as region-specific. The **CondPeril** field specifies which perils the condition applies to. This can be a single peril code, or a string of peril codes separated by semi-colons.
+
+**CondPeril** must always be included in the account file whenever there are conditions, and it must be filled in with the appropriate peril codes.
+
+For example, a California earthquake sub-limit may be specified as follows;
+
+|
+
+**Example 3 - California earthquake sub-limit**
+
+|
+
+OED Location file
+
+|
+
+.. csv-table::
+ :widths: 15,15,15,15,20,20
+ :header: "AccNumber", "LocNumber", "CountryCode", "AreaCode", "CondTag", "LocPerilsCovered"
+
+ "Acc3", "Loc1", "US", "CA", "California", "OO1;QQ1"
+ "Acc3", "Loc2", "US", "CA", "California", "OO1;QQ1"
+ "Acc3", "Loc3", "US", "IN", "", "OO1;QQ1"
+ "Acc3", "Loc4", "MX", "02", "", "OO1;QQ1"
+
+The **LocPerilsCovered** field specify that each location in the account is subject to 'All flood perils' and 'All earthquake perils'.
+
+|
+
+OED Account file:
+
+|
+
+.. csv-table::
+ :widths: 20,20,20,20,20,20,20
+ :header: "AccNumber", "PolNumber", "CondTag", "CondNumber", "CondLimit6All", "PolPerilsCovered", "CondPeril"
+
+ "Acc3", "Pol1", "California", "1", "10,000,000", "OO1;QQ1", "QQ1"
+
+|
+
+The **PolPerilsCovered** field specifies that the policy is subject to 'All flood perils' and 'All earthquake perils'.
+
+However the **CondPeril** field specifies that the condition is subject to 'All earthquake perils' only.
+
+This means that the sub-limit will only apply to losses arising from earthquake perils on the policy.
+
+|
+
+Nested hierarchal conditions
+############################
+
+In the above examples with multiple conditions, each condition applied to a different group of locations.
+
+There can also be multiple sub-limits that apply to the same location in a nested hierarchy.
+
+An example of this might be a US Wind sub-limit with nested state-level sub-limits, say for Florida and Texas, on an account covering global locations.
+
+We must 'tag' all of the locations for each condition that applies to them by adding more records in the locations file.
+
+|
+
+**Example 4 - nested hierarchal conditions**
+
+|
+
+
+
+
+OED Location file:
+
+.. csv-table::
+ :widths: 15,15,15,15,20
+ :header: "AccNumber", "LocNumber", "CountryCode", "AreaCode", "CondTag"
+
+ "Acc4", "Loc1", "US", "FL", "Florida"
+ "Acc4", "Loc1", "US", "FL", "US"
+ "Acc4", "Loc2", "US", "FL", "Florida"
+ "Acc4", "Loc2", "US", "FL", "US"
+ "Acc4", "Loc3", "US", "TX", "Texas"
+ "Acc4", "Loc3", "US", "TX", "US"
+ "Acc4", "Loc4", "US", "LA", "US"
+ "Acc4", "Loc5", "MX", "02", ""
+
+
+We have two location records for Locations 1,2 and 3, with a CondTag for the 'Florida' or 'Texas' sub-limits and a second CondTag 'US' for the US wind sub-limit. Location 5 is outside the scope of all conditions.
+
+In the account file, we have policy record for each condition: Florida, Texas and US sub-limit.
+
+|
+
+OED Account file:
+
+.. csv-table::
+ :widths: 20,20,20,20,20,20,20,20
+ :header: "AccNumber", "PolNumber", "CondTag", "CondNumber", "CondLimit6All", "CondName", "CondPeril","CondPriority"
+
+ "Acc4", "Pol1", "Florida", "1", "10,000,000", "FL sub-limit", "WW1", "1"
+ "Acc4", "Pol1", "Texas", "2", "5,000,000", "TX sub-limit", "WW1", "1"
+ "Acc4", "Pol1", "US", "3", "12,500,000", "US sub-limit", "WW1", "2"
+
+The Florida and Texas sub-limits apply first, and the US sub-limit applies second. This would result in any combined losses from Florida and Texas exceeding the US sub-limit being limited to $12,500,000. Then policy terms would apply to the sum of limited US locations and the rest of world locations.
+
+|
+
+Example losses:
+
+.. csv-table::
+ :widths: 15,15,15,15,20
+ :header: "AccNumber", "LocNumber", "CountryCode", "AreaCode", "Ground up loss"
+
+ "Acc4", "Loc1", "US", "FL", "5,000,000"
+ "Acc4", "Loc2", "US", "FL", "6,000,000"
+ "Acc4", "Loc3", "US", "TX", "7,000,000"
+ "Acc4", "Loc4", "US", "LA", "1,000,000"
+ "Acc4", "Loc5", "MX", "02", "0"
+
+The Florida sub-limit applies to the losses from Locations 1 and 2 and limits them to $10,000,000. The Texas sub-limit limits the Location 3 loss to $5,000,000.
+
+The US sub-limit applies to the sum of the **limited** state level losses of $10,000,000 and $5,000,000, and the $1,000,000 loss from Location 4 which is only subject to the US sub-limit . The total gross loss before policy terms is **$12,500,000**.
+
+The Florida and Texas sub-limits can be referred to as 'child' conditions, with the US sub-limit referred to as the 'parent' condition.
+
+'Nested' means that all locations in the child sub-limit regions also belong to the parent sub-limit region. There may be locations belonging
+to the parent sub-limit region but not any child sub-limit region.
+
+It is possible to represent an unlimited number of hierarchal levels in OED, but in practice the number of hierarchal levels rarely exceeds two.
+
+|
+
+
+
+CondPriority
+############
+
+When there are hierarchal conditions as in the example above, it is necessary to specify the order in which the conditions apply. **CondPriority** is an integer field in the accounts file which specifies the relative order in which the conditions apply.
+
+In the previous example, the value in the **CondPriority** field is equivalent to the hierarchal level of each condition.
+
+However in practice, where there are many children conditions, there is often an overall ranking or priority assigned to each condition regardless of whether there is a hierarchy or not.
+
+|
+
+**Example 5 - parent and child conditions**
+
+|
+
+OED Location file:
+
+.. csv-table::
+ :widths: 20,20,20
+ :header: "AccNumber", "LocNumber", "CondTag"
+
+ "Acc5", "Loc1", "child1"
+ "Acc5", "Loc1", "parent"
+ "Acc5", "Loc2", "child2"
+ "Acc5", "Loc2", "parent"
+ "Acc5", "Loc3", "child3"
+ "Acc5", "Loc3", "parent"
+ "Acc5", "Loc4", "parent"
+ "Acc5", "Loc5", ""
+
+The location file must have two records for each location subject to a child condition and the parent condition. Locations 1-3 all appear twice in the locations file with two different CondTags and are part of the nested hierarchal conditions.
+
+Location 4 is subject to the parent condition only so it appears only once.
+
+Location 5 appears once and is outside of the hierarchy with no conditions, and its loss is carried into the policy terms with no sub-limits applied.
+
+|
+
+OED Account file:
+
+.. csv-table::
+ :widths: 20,20,20,20,20,20,20
+ :header: "AccNumber", "PolNumber", "CondTag", "CondNumber", "CondLimit6All", "CondName", "CondPriority"
+
+ "Acc5", "Pol1", "child1", "1", "10,000,000", "child1", "1"
+ "Acc5", "Pol1", "child2", "2", "5,000,000", "child2", "2"
+ "Acc5", "Pol1", "child3", "3", "5,000,000", "child3", "3"
+ "Acc5", "Pol1", "parent", "5", "20,000,000", "parent", "4"
+
+
+The relative values of CondPriority between the child conditions do not matter when the conditions apply to non-overlapping groups of locations. All that matters is that the relative value of the CondPriority of the parent condition is greater than the value of CondPriority of each of the child conditions.
+
+Hierarchal conditions are only recognised by the presence of duplicate locations in the locations file, and not by the values in CondPriority or the descriptions of the conditions in CondName.
+
+It is only when the same location appears twice in the location file with different CondTag values that the relative values of **CondPriority** will be used to determine the order in which the conditions apply. **CondPriority** is disregarded in the case that there are multiple non-overlapping conditions.
+
+|
+
+Policy restrictions
+###################
+
+In all of previous examples, the conditions have been 'sub-limit' types, where the set of financial terms apply to the locations which are assigned a particular CondTag. This is the default case and it does not need to be explicitly specified.
+
+For accounts with multiple locations, the default assumption is that if there is more than one policy on the account, then every policy applies to every location in the account.
+
+However, policies on an account can sometimes have certain locations excluded. Policy restrictions are specified in OED using the **CondClass** field.
+
+|
+
+CondClass
+#########
+
+Policy restrictions are implemented as an alternative classification of special conditions which can be specified by the **CondClass** field in the account file. A value of 1 means 'Policy restriction', otherwise the default value of 0 (sub-limit) is assumed.
+
+The difference between them is what happens to losses for locations under the account that do not have a CondTag.
+
+* When the condition is a sub-limit - the locations that have no CondTag will still contribute loss to the policy on the account.
+* When the condition is a policy restriction - the locations that have no CondTag **will not** contribute loss to the policy on the account.
+
+There are usually no financial terms such as limits or deductibles that apply in policy restrictions. A policy restriction is normally only used to exclude locations from contributing to a policy.
+
+Next is an example which excludes Florida locations from the policy.
+
+|
+
+**Example 6 - Single policy restriction**
+
+|
+
+OED Location file:
+
+.. csv-table::
+ :widths: 15,15,15,15,20
+ :header: "AccNumber", "LocNumber", "CountryCode", "AreaCode", "CondTag"
+
+ "Acc6", "Loc1", "US", "NC", "366"
+ "Acc6", "Loc2", "US", "NC", "366"
+ "Acc6", "Loc3", "US", "FL", ""
+ "Acc6", "Loc4", "US", "TX", "366"
+
+|
+
+OED Account file:
+
+.. csv-table::
+ :widths: 20,20,20,20,20,20
+ :header: "AccNumber", "PolNumber", "CondTag", "CondNumber", "CondName", "CondClass"
+
+ "Acc6", "Pol1", "366", "366450", "EXCL FL LOCS", "1"
+
+Only Locations 1, 2, and 4 are subject to the policy terms and Florida location 3 is excluded.
+
+|
+
+Example losses:
+
+.. csv-table::
+ :widths: 15,15,15,15,20
+ :header: "AccNumber", "LocNumber", "CountryCode", "AreaCode", "Ground up loss"
+
+ "Acc6", "Loc1", "US", "NC", "4,000,000"
+ "Acc6", "Loc2", "US", "NC", "2,000,000"
+ "Acc6", "Loc3", "US", "FL", "20,000,000"
+ "Acc6", "Loc4", "US", "TX", "10,000,000"
+
+The policy restriction means that the Florida loss is excluded, The gross loss is the sum of losses from the non-Florida locations which is **$16,000,000**.
+
+|
+
+Conditions on multi-policy accounts
+###################################
+
+When there are multiple policies on an account, conditions can be symmetric (same conditions apply to all policies) or assymmetric (different conditions per policy).
+
+Continuing the regional sub-limit example 2, we can add a second excess policy to the account with the same conditions.
+
+|
+
+**Example 7 - Symmetric policy conditions**
+
+|
+
+OED Location file:
+
+.. csv-table::
+ :widths: 15,15,15,15,20
+ :header: "AccNumber", "LocNumber", "CountryCode", "AreaCode", "CondTag"
+
+ "Acc7", "Loc1", "US", "CA", "California"
+ "Acc7", "Loc2", "US", "CA", "California"
+ "Acc7", "Loc3", "US", "IN", "New Madrid"
+ "Acc7", "Loc4", "US", "NV", ""
+
+|
+
+OED Account file:
+
+.. csv-table::
+ :widths: 20,20,20,20,20,20,20
+ :header: "AccNumber", "PolNumber", "CondTag", "CondNumber", "CondLimit6All", "LayerAttachment", "LayerLimit"
+
+ "Acc7", "Pol1", "California", "1", "10,000,000", "0", "10,000,000"
+ "Acc7", "Pol1", "New Madrid", "2", "5,000,000", "0", "10,000,000"
+ "Acc7", "Pol2", "California", "1", "10,000,000", "10,000,000", "15,000,000"
+ "Acc7", "Pol2", "New Madrid", "2", "5,000,000", "10,000,000", "15,000,000"
+
+Some layer terms are added to distinguish between Pol1 and Pol2. This is an example where conditions are symmetric across policies.
+
+|
+
+Example losses:
+
+.. csv-table::
+ :widths: 15,15,15,15,20
+ :header: "AccNumber", "LocNumber", "CountryCode", "AreaCode", "Ground up loss"
+
+ "Acc7", "Loc1", "US", "CA", "5,000,000"
+ "Acc7", "Loc2", "US", "CA", "7,000,000"
+ "Acc7", "Loc3", "US", "IN", "0"
+ "Acc7", "Loc4", "US", "NV", "4,000,000"
+
+
+Pol1: California losses are limited to $10,000,000. Loss before layer terms = $14,000,000. Gross loss after layer limit = **$10,000,000**
+
+Pol2: California losses are limited to $10,000,000. Loss before layer terms = $14,000,000. Gross loss after layer attachement and limit = **$4,000,000**
+
+|
+
+**Example 8 - Asymmetric policy conditions**
+
+Policies may be defined to apply to different locations within an account. When this is the case, policy restrictions can be used to specify the exclusion of different locations from each policy. This leads to assymmetric policy conditions.
+
+In this example, a policy restriction is used to exclude location 4 from policy A. In addition, a normal sub-limit applies to a location in policy A. The sub-limit is applied as priority 1, and the restriction as priority 2.
+
+Policy B covers all 4 locations without the sub-limit.
+
+|
+
+OED Location file:
+
+.. csv-table::
+ :widths: 15,15,15
+ :header: "AccNumber", "LocNumber", "CondTag"
+
+ "Acc8", "Loc1", "PolA"
+ "Acc8", "Loc2", "Sublimit_400k"
+ "Acc8", "Loc2", "PolA"
+ "Acc8", "Loc3", "PolA"
+ "Acc8", "Loc4", ""
+
+|
+
+OED Account file:
+
+.. csv-table::
+ :widths: 20,20,20,20,20,20,20
+ :header: "AccNumber", "PolNumber", "CondTag", "CondNumber", "CondPriority", "CondClass", "CondLimit6All"
+
+ "Acc8", "PolA", "Sublimit_400k", "1", "1", "0", "400,000"
+ "Acc8", "PolA", "PolA", "2", "2", "1", ""
+ "Acc8", "PolB", "", "", "", "", ""
+
+|
+
+Example losses:
+
+.. csv-table::
+ :widths: 15,15,20
+ :header: "AccNumber", "LocNumber", "Ground up loss"
+
+ "Acc8", "Loc1", "800,000"
+ "Acc8", "Loc2", "1,000,000"
+ "Acc8", "Loc3", "500,000"
+ "Acc8", "Loc4", "300,000"
+
+
+PolA: Location 2 is limited to $400,000. Location 4 is excluded. Gross loss before policy terms = $800k + $400k + $500k = **$1,700,000**
+
+PolB: All location losses are included. Gross loss before policy terms = $800k + $1000k + $500k + $300k = **$2,600,000**
+
+|
+
+For each specified CondTag in the locations file, there must be least one associated policy condition in the accounts file, and vice versa. In other words, there must not be any CondTags in the one file not appearing in the other file.
+
+Finally, below are some examples of sub-limits in combination with other policy terms.
+
+We show two examples, firstly where the sub-limits are not nested and secondly where the sub-limits are nested.
+
+|
+
+**Example 9 – Commercial lines – multiple locations per policy with location and policy deductibles but with a sub-limit for tier 1 wind**
+
+The tables below show an example of a commercial portfolio with 1 account containing 6 locations. The policy covers earthquake and wind with the same overall policy limit for both perils. However, for certain locations two different sub-limits apply for wind (e.g. Florida wind sub-limit and Texas wind sub-limit).
+
+|
+
+OED Location file:
+
+.. csv-table::
+ :widths: 15,15,20,25,20,15
+ :header: "AccNumber", "LocNumber", "BuildingTIV", "LocDedType1Building", "LocDed1Building", "CondTag"
+
+ "Acc9", "1", "1,000,000", "0", "10,000", "1"
+ "Acc9", "2", "1,000,000", "2", "0.01", "1"
+ "Acc9", "3", "1,000,000", "1", "0.05", "2"
+ "Acc9", "4", "2,000,000", "0", "15,000", "2"
+ "Acc9", "5", "2,000,000", "0", "10,000", ""
+ "Acc9", "6", "2,000,000", "2", "0.10", ""
+
+|
+
+OED Account file:
+
+.. csv-table::
+ :widths: 20,30,30, 30,30,30,30,30,25
+ :header: "AccNumber", "PolNumber", "PolPerilsCovered", "PolLimit6All", "CondTag", "CondNumber", "CondPriority", "CondPeril", "CondLimit6All"
+
+ "Acc9", "1", "QQ1;WW1", "1,500,000", "1", "1", "1", "WW1", "250,000"
+ "Acc9", "1", "QQ1;WW1", "1,500,000", "2", "2", "1", "WW1", "500,000"
+
+|
+
+**Example 10 – Commercial lines – multiple locations per policy with location and policy deductibles with nested hierarchal sub-limits for wind**
+
+If two special conditions are nested or overlap (e.g. Texas tier 1 wind sub-limit of 250,000 (**CondNumber** = 1) and Texas overall wind sub-limit of 500,000 (**CondNumber** = 2)), the tables would be specified as shown below. The example below assumes that locations 1 and 2 are in the Texas tier 1 region, locations 3 and 4 are within Texas but not in the Tier 1 wind region, and locations 5 and 6 are outside Texas.
+
+|
+
+OED Location file:
+
+.. csv-table::
+ :widths: 12,12,15,20,15,10
+ :header: "AccNumber", "LocNumber", "BuildingTIV", "LocDedType1Building", "LocDed1Building", "CondTag"
+
+ "Acc10", "1", "1,000,000", "0", "10,000", "1"
+ "Acc10", "1", "1,000,000", "0", "10,000", "2"
+ "Acc10", "2", "1,000,000", "2", "0.01", "1"
+ "Acc10", "2", "1,000,000", "2", "0.01", "2"
+ "Acc10", "3", "1,000,000", "1", "0.05", "2"
+ "Acc10", "4", "2,000,000", "0", "15,000", "2"
+ "Acc10", "5", "2,000,000", "0", "10,000", ""
+ "Acc10", "6", "2,000,000", "2", "0.10", ""
+
+|
+
+OED Account file:
+
+.. csv-table::
+ :widths: 20,20,30,30,20,20,20,25,25
+ :header: "AccNumber", "PolNumber", "PolPerilsCovered", "PolLimit6All", "CondTag", "CondNumber", "CondPriority", "CondPeril", "CondLimit6All"
+
+
+ "Acc10", "1", "QQ1; WW1", "1,500,000", "1", "1", "1", "WW1", "250,000"
+ "Acc10", "1", "QQ1; WW1", "1,500,000", "2", "2", "2", "WW1", "500,000"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/source/explanation/financial-primary.rst b/docs/source/explanation/financial-primary.rst
new file mode 100644
index 00000000..e6262239
--- /dev/null
+++ b/docs/source/explanation/financial-primary.rst
@@ -0,0 +1,345 @@
+Financial Details - Primary Insurance
+=====================================
+
+OED is designed to allow a wide variety of complex financial structures – beyond that currently possible in Oasis or any other catastrophe modelling platform. To encompass such a variety of financial structures (e.g. different limits for different perils, or multiple policy special conditions) within a limited set of input files (two for primary insurance) it is necessary to allow multiple rows within each file for the same location or policy. The need for this will become clearer in the examples that follow.
+
+The OED hierarchy is described in the *overview* section. Primary financial structures in OED can apply at the following levels:
+
+• Location ‘Loc’
+
+• Special Conditions ‘Cond’
+
+• Policy ‘Pol’
+
+• Account ‘Acc’
+
+The above abbreviations are used consistently throughout OED (for example in the field names).
+Limits, deductibles and minimum and maximum deductibles can be defined at each of these levels and can apply to different combinations of coverages at each of these levels as described in the next section.
+
+|
+
+Coverage Values
+###############
+
+Coverage values to describe which combination of coverage types a financial structure apply to are as follows:
+
+.. csv-table::
+ :widths: 8,20
+ :header: "Coverage Value", "Description"
+
+ "0", "No deductible / limit"
+ "1", "Building"
+ "2", "Other (typically appurtenant structures)"
+ "3", "Contents"
+ "4", "Business Interruption (BI)"
+ "5", "Property Damage (PD: Building + Other + Contents)"
+ "6", "All (PD + BI)"
+
+These coverage values (1 to 6) are embedded in the input field names (as shown in the examples).
+
+|
+
+Deductible and Limit Types
+##########################
+
+The deductible and limit type fields describe whether the deductibles and limits are flat monetary amounts, or percentages of TIV, or percentages of loss:
+
+.. csv-table::
+ :widths: 5,20
+ :header: "Type", "Description"
+
+ "0", "Deductible / limit is flat monetary amount"
+ "1", "Deductible / limit is a percentage of loss"
+ "2", "Deductible / limit is a percentage of TIV"
+
+There are multiple ‘Type’ fields containing the values in the table above, each representing a different combination of hierarchy, financial structure kind and coverage.
+
+|
+
+Deductible and Limit Codes
+##########################
+
+The deductible and limit code fields describe how the deductibles and limits operate. The options for deductible codes are as follows:
+
+
+.. csv-table::
+ :widths: 5,20
+ :header: "Deductible Code", "Description"
+
+ "0", "Regular: applies to an individual loss (or the sum of losses from an individual event depending on the hierarchy level of application)"
+ "1", "Annual aggregate: applies to the sum of losses over a year"
+ "2", "Franchise deductible: disappears when the franchise level is reached"
+ "3", "Non-ranking deductible: a deductible that does not count (or ‘rank’) towards a maximum annual aggregate deductible"
+ "4", "Residual deductible: A deductible (normally lower than the regular deductible) that applies after a maximum annual aggregate deductible amount is reached"
+ "5", "CEA Homeowners: A specific type of deductible applying in a California Earthquake Authority (CEA) Homeowners policy"
+ "6", "CEA Homeowners Choice: A specific type of deductible applying in a California Earthquake Authority (CEA) Homeowners Choice policy"
+
+
+The options for limit codes are as follows:
+
+|
+
+.. csv-table::
+ :widths: 5,30
+ :header: "Limit Code", "Description"
+
+ "0", "Regular: applies to an individual loss (or the sum of losses from an individual event depending on the hierarchy level of application)"
+ "1", "Annual aggregate: applies to the sum of losses over a year"
+
+|
+
+Structure of Financial Field Names
+##################################
+
+
+There are multiple financial fields to store the ‘Type’, ‘Code’ and actual values for the different deductible and limits reflecting the different variations of:
+
+• What hierarchy the financial structure applies at: ‘Loc’, ‘Cond’, ‘Pol’ or ‘Acc’
+
+• Whether the financial structure is a limit or deductible or maximum or minimum deductible: ‘Ded’, ‘Limit’, ‘MaxDed’ or ‘MinDed’
+
+• The coverage that the financial structure applies to (‘1Building’ to ‘6All’)
+
+This is illustrated below:
+
+.. image:: images/Hierarchy.png
+
+|
+
+For example:
+
+**LocDedCode1Building** is the field in the location input file that contains the code for the deductible applicable to losses from building coverages.
+
+**AccLimitCode6All** is the field in the account input file that contains the code for the limit applicable to losses from all coverages at account level.
+
+**PolDed6All** is the field in the account input file that contains the value of the deductible applicable to losses from all coverages at policy level.
+
+**LocMaxDed1Building** is the field in the location input file that contains the value of the maximum deductible applicable to losses from the building coverage.
+
+**CondLimitType6All** is the field in the account input file that contains the type of limit applicable to losses from all coverages for a special condition.
+
+The reason for having both the coverage value (1 to 6) as well as spelling out the coverage kind in the input field names is so that the users of OED can easily associate the value numbers with the coverage types.
+
+|
+
+Policy Special Conditions
+#########################
+
+Policy special conditions are financial structures that apply to only a subset of locations within a policy. They apply after all location terms, but before any blanket policy terms or layer terms.
+
+The scope of each special condition is specified using a **CondTag** on each location (in the location input file) that corresponds with the **CondTag** in the account input file.
+
+A unique set of financial terms and a classification is identified by the **CondNumber** field in the account file.
+
+The specification of the financial details of the condition is done in the same way as any other financial structure within OED but using the field names starting with ‘Cond’. All of the coverage values deductible and limit types and codes can be used for a special condition to specify how the special condition financial structures work.
+
+See the Financial Details Policy Conditions section for a detailed description of how special conditions are specified, and some examples.
+
+|
+
+Participation Fields
+####################
+
+The following fields are available to reflect that an insurer may only have a share of a primary policy or location:
+
+**LayerParticipation** represents the share that an insurer has in a policy.
+
+**LocParticipation** represents the share that an insurer has in a particular location. Occasionally there are cases when this can vary within a policy (e.g. binders or offshore) and so this field is provided to allow flexibility in these circumstances.
+
+|
+
+Currencies
+##########
+
+Three currency fields are available:
+
+• **LocCurrency** contains the currency in the location file and specifies the currency for TIV and location level financial terms.
+
+• **AccCurrency** contains the currency in the account file and specifies the currency for special condition, policy and account level financial terms.
+
+• **ReinsCurrency** contains the currency in the reinsurance file and specifies the currency for reinsurance financial terms.
+
+The currency code values are predominantly those contained within the ISO4217 standard although older (for example pre-euro) codes are also allowed.
+
+|
+
+Examples of Specifying Primary Financial Structures
+####################################################
+
+The following examples illustrate the principles discussed in the previous sections. Not all required fields are shown in the examples below – only those needed to illustrate the principles highlighted.
+
+**Example 1 – Personal lines with coverage deductibles**
+
+Personal lines data often has one location per policy / account, with financial terms only applying at location-coverage or location level. There are two ways that this could be represented in OED, either using one account / policy per location or using an account / policy to represent multiple locations reflecting some natural grouping of personal lines policies. The latter approach is more space efficient. Both approaches are described below.
+
+The tables below show 3 locations, all with the same 100,000 buildings TIV and deductibles that apply at the buildings coverage level. Location 1 has a monetary (**DedType = 0**) deductible of 200, location 2 has a 1% of TIV deductible (**DedType = 2**) and location 3 has a 5% of loss deductible (**DedType = 1**).
+
+|
+
+The OED Account and Location tables using the first approach are as follows:
+
+OED Account file:
+
+.. csv-table::
+ :widths: 25,20
+ :header: "AccNumber", "PolNumber"
+
+ "PolRef1", "PolRef1"
+ "PolRef2", "PolRef2"
+ "PolRef3", "PolRef3"
+
+|
+
+OED Location file:
+
+.. csv-table::
+ :widths: 15,15,15,20,20,15
+ :header: "LocNumber", "AccNumber", "BuildingTIV", "LocDedType1Building","LocDedCode1Building","LocDed1Building"
+
+ "1", "PolRef1", "100,000", "0", "0", "200"
+ "2", "PolRef2", "100,000", "2", "0", "0.01"
+ "3", "PolRef3", "100,000", "1", "0", "0.05"
+
+|
+
+Note that **LocDedCode1Building = 0** which means the deductible is a standard type (not an annual aggregate or franchise etc.) This field is not actually required for standard deductibles – it would default to 0 if not provided.
+
+Not all required fields are shown in the tables above; specifically, **PortNumber, AccCurrency** and **PolPerilsCovered** are required in the account table, and **PortNumber, LocPerilsCovered, CountryCode, OtherTIV, ContentsTIV, BITIV** and **LocCurrency** are required in the location table.
+The second way of representing personal lines data is to group all locations under one ‘policy’ but provide the true policy reference in the **LocNumber** field, as shown below:
+
+|
+
+OED Account file:
+
+.. csv-table::
+ :header: "AccNumber", "PolNumber"
+
+ "1", "1"
+
+|
+
+OED Location file:
+
+.. csv-table::
+ :widths: 15,15,15,22,22,18
+ :header: "LocNumber", "AccNumber", "BuildingTIV", "LocDedType1Building","LocDedCode1Building","LocDed1Building"
+
+ "PolRef1", "1", "100,000", "0", "0", "200"
+ "PolRef2", "1", "100,000", "2", "0", "0.01"
+ "PolRef3", "1", "100,000", "1", "0", "0.05"
+
+|
+
+This is a more efficient approach as the size of the account table is much smaller which is relevant since personal lines portfolios can easily contain several million locations.
+
+|
+
+**Example 2 – Commercial lines – multiple locations per policy with location and policy deductibles and a policy limit**
+
+The tables below show an example of a commercial portfolio with 3 accounts, each with 2 locations. Each location has a coverage deductible and there is an overall policy deductible and an overall policy limit.
+
+
+OED Account file:
+
+.. csv-table::
+ :widths: 15,15,20,18,22,15
+ :header: "AccNumber", "PolNumber", "PolDedType6All", "PolDed6All", "PolLimitType6All", "PolLimit6All"
+
+ "1", "1", "0", "50,000", "0", "1,500,000"
+ "2", "1", "2", "0.05", "0", "1,500,000"
+ "3", "1", "1", "0.10", "2", "0.80"
+
+|
+
+OED Location file:
+
+.. csv-table::
+ :widths: 12,12,15,25,20
+ :header: "LocNumber", "AccNumber", "BuildingTIV", "LocDedType1Building", "LocDed1Building"
+
+ "1", "1", "1,000,000", "0", "10,000"
+ "2", "1", "1,000,000", "2", "0.01"
+ "3", "2", "1,000,000", "1", "0.05"
+ "4", "2", "2,000,000", "0", "15,000"
+ "5", "3", "2,000,000", "0", "10,000"
+ "6", "3", "2,000,000", "2", "0.10"
+
+In the account table above, there are two options for specifying the policy limit: either using the **PolLimit6All** field (as shown) or using the **LayerLimit** field (not shown). If a limit is specified as anything other than a monetary amount (e.g. as a percentage of sum insured) then the **PolLimit6All** field must be used.
+
+If there are underlying limits before a policy layer (e.g. perhaps a sublimit for storm surge that applies to all locations) then **PolLimit6All** must be used. If there is only one monetary policy limit, then the user has a choice of whether to use LayerLimit or **PolLimit6All**. Our recommendation in this case is to use **LayerLimit** rather than **PolLimit6All**, as this may prove more efficient downstream when reporting out on main policy limits.
+
+|
+
+**Example 3 – Commercial lines – multiple locations per policy with different policy level deductibles and limits for different perils**
+
+The tables below show an example of a commercial portfolio with 3 accounts, each with 2 locations. Each account has one policy and each policy covers earthquake **(peril code = QQ1)**, wind **(WW1)** and flood **(OO1)**. Each location has a coverage deductible which applies to all perils. Each policy has deductibles and limits that apply across all coverages; however the policy flood deductibles are higher than those for wind and earthquake and the flood limits are lower than those for wind and earthquake.
+
+|
+
+OED Account file:
+
+.. csv-table::
+ :widths: 18,18,18,25,20,25,20
+ :header: "AccNumber", "PolNumber", "PolPeril", "PolDedType6All", "PolDed6All", "PolLimitType6All", "PolLimit6All"
+
+ "1", "1", "QQ1;WW1", "0", "50,000", "0", "1,500,000"
+ "1", "1", "OO1", "0", "100,000", "0", "500,000"
+ "2", "1", "QQ1;WW1", "2", "0.05", "0", "1,500,000"
+ "2", "1", "OO1", "0", "500,000", "0", "1,000,000"
+ "3", "1", "QQ1;WW1", "1", "0.10", "2", "0.80"
+ "3", "1", "OO1", "1", "0.20", "2", "0.60"
+
+|
+
+OED Location file:
+
+.. csv-table::
+ :widths: 15,15,18,30,20
+ :header: "LocNumber", "AccNumber", "BuildingTIV", "LocDedType1Building", "LocDed1Building"
+
+ "1", "1", "1,000,000", "0", "10,000"
+ "2", "1", "1,000,000", "2", "0.01"
+ "3", "2", "1,000,000", "1", "0.05"
+ "4", "2", "2,000,000", "0", "15,000"
+ "5", "3", "2,000,000", "0", "10,000"
+ "6", "3", "2,000,000", "2", "0.10"
+
+The account table above shows one of the flexible features of the OED – the possibility of having multiple rows for the same policy in the account table. This allows different terms to be specified for different perils as indicated by the **PolPeril** field.
+
+|
+
+**Example 4 – Policy layers**
+
+The tables below show an example of a commercial portfolio with 1 account containing 6 locations and two policy layers. Each location has a coverage deductible and each policy has an underlying deductible applying across all coverage types.
+
+|
+
+OED Account file:
+
+.. csv-table::
+ :widths: 12,12,20,15,20,15,20
+ :header: "AccNumber", "PolNumber", "PolDedType6All", "PolDed6All", "LayerAttachment", "LayerLimit", "LayerParticipation"
+
+ "1", "1", "0", "50,000", "0", "1,500,000", "0.1"
+ "1", "2", "0", "50,000", "1,500,000", "3,500,000", "0.5"
+
+|
+
+OED Location file:
+
+.. csv-table::
+ :widths: 10,12,12,20,15
+ :header: "LocNumber", "AccNumber", "BuildingTIV", "LocDedType1Building", "LocDed1Building"
+
+ "1", "1", "1,000,000", "0", "10,000"
+ "2", "1", "1,000,000", "2", "0.01"
+ "3", "1", "1,000,000", "1", "0.05"
+ "4", "1", "2,000,000", "0", "15,000"
+ "5", "1", "2,000,000", "0", "10,000"
+ "6", "1", "2,000,000", "2", "0.10"
+
+The two different layers in the example above have different policy numbers within the same account. The insurer has a 10% share of the first layer and a 50% share of the second layer specified within **LayerParticipation**. The policy level deductible specified in **PolDedType6All** and **PolDed6All** applies to losses before the layer terms apply.
+
+Although not shown in the example above, it is possible to specify a layer number for each layer using the **LayerNumber** field.
+
+If a policy has a limit that covers all perils and coverage types, then either **PolLimit6All** or **LayerLimit** can be used to represent this limit. In this case the recommendation is to use **LayerLimit** rather than **PolLimit6All**, as this then results in a consistent field containing the ultimate policy limit that can ease subsequent reporting.
diff --git a/docs/source/explanation/geography-perils.rst b/docs/source/explanation/geography-perils.rst
new file mode 100644
index 00000000..5d157293
--- /dev/null
+++ b/docs/source/explanation/geography-perils.rst
@@ -0,0 +1,155 @@
+Geography and Perils
+====================
+
+There are several aspects to geographical information in OED:
+
+• Country codes
+
+• Address information fields
+
+• Geocoding information
+
+|
+
+Country Codes
+#############
+
+Country codes are stored in the **CountryCode** field and are based on the ISO3166 alpha-2 codes with the following additions:
+
+• *XB* = Bonaire
+
+• *XS* = Saba
+
+• *XE* = St Eustatius
+
+• *XW* = Worldwide exposure (not used for modelling)
+
+• Offshore regions have been added as a direct one to one mapping from AIR’s CEDE offshore codes (the AIR three letter codes have been mapped to two-character codes for storage efficiency e.g. 'A1' for Alaska offshore)
+
+Full details of the permitted code values are in the OED specification spreadsheet.
+
+|
+
+Standardised Geographical Fields
+################################
+
+The following fields are available for capturing geographical information in OED:
+
+• **StreetAddress**: The building number and street
+
+• **PostalCode**: The predominant full resolution postal code used (e.g. 5-digit zip code in the US)
+
+• **City**: City name
+
+• **AreaCode**: Code representing typically the largest geographical division in a country (e.g. State code). See the Open Exposure Data Spec spreadsheet for a list of values.
+
+• **AreaName**: Description of the **AreaCode** (e.g. State name)
+
+|
+
+Flexible Geographical Fields
+############################
+
+The OED format caters for a wide variety of models from different model developers. In order to allow sufficient flexibility to cope with different user and model developer requirements there are flexible geographical fields: **GeogSchemeXX / GeogNameXX**. The 'XX' needs to be replaced by an integer so the name pairs become **GeogScheme1/GeogName1** and OED can support up to ninety-nine pairs. It's worth noting that performance time (especially during the 'lookup' phase of analysis) may be affected the more pairs are used. These pairs allow model developers and users to define their own geographical schemes (defined by an appropriate GeogScheme code) each with a corresponding set of GeogName values.
+
+For example, a model developer may want to split each country up into four equal areas ‘A’, ‘B’, ‘C’, ‘D’. In this case they would define a new GeogScheme code e.g. ‘QUAD’. They would communicate to users of their model that they must specify GeogName values ‘A’, ‘B’, ‘C’ or ‘D’ for their new ‘QUAD’ GeogScheme. The model user would then populate one of the GeogScheme / GeogName pairs with ‘QUAD’ and ‘A’, ‘B’, ‘C’ or ‘D’ respectively.
+
+This provides a large amount of flexibility to cope with different user and model developer requirements.
+GeogScheme codes are up to five characters (no special characters). The latest codes can be found in the Open Exposure Data Spec spreadsheet on the OED GitHub repository in https://github.com/OasisLMF/ODS_OpenExposureData/tree/main/Docs
+
+Users can also specify their own schemes (e.g. for reporting purposes). The only requirement here is that any user defined scheme codes **must start with ‘X’** in order to avoid a potential code clash with future model developer schemes.
+
+|
+
+Geocoding
+#########
+
+**Latitude** and **Longitude** fields are available within OED. However, a latitude and longitude pair in isolation gives no indication as to the resolution of the geocode, the confidence in the geocode or the geocoder used to derive the latitude and longitude.
+
+**AddressMatch** allows information about the resolution of the geocode to be captured. For example, whether the latitude / longitude pair represents the centroid of a large area (e.g. a State) or the centre of an individual building.
+
+**GeocodeQuality** allows the capture of a number between 0 and 1 representing a confidence score associated with the geocode (1 denoting perfect confidence, 0 denoting zero confidence).
+
+**Geocoder** is a free text field that allows capture of the name and version of the geocoding engine used.
+
+|
+
+Peril Codes
+###########
+
+The system for capturing which perils apply to different exposure elements and financial structures is designed to be flexible and extensible. Each peril is assigned a code and shown in the table below:
+
+
+.. csv-table::
+ :widths: 130,30
+ :header: "Peril", "Input Format Peril Code"
+
+ "Earthquake - Shake only", "QEQ"
+ "Fire Following", "QFF"
+ "Tsunami", "QTS"
+ "Sprinkler Leakage", "QSL"
+ "Landslide", "QLS"
+ "Liquefaction", "QLF"
+ "Tropical Cyclone", "WTC"
+ "Extra Tropical Cyclone", "WEC"
+ "Storm Surge", "WSS"
+ "River / Fluvial Flood", "ORF"
+ "Flash / Surface / Pluvial Flood", "OSF"
+ "Straight-line / other convective wind","XSL"
+ "Tornado", "XTD"
+ "Hail", "XHL"
+ "Snow", "ZSN"
+ "Ice", "ZIC"
+ "Freeze", "ZFZ"
+ "NonCat", "BFR"
+ "Wildfire / Bushfire", "BBF"
+ "NBCR Terrorism", "MNT"
+ "Conventional Terrorism", "MTR"
+ "Lightning", "XLT"
+ "Winterstorm Wind", "ZST"
+ "Smoke", "BSK"
+ "Drought Induced Subsidence", "SSD"
+ "Crop Hail (From Convective Storm)", "XCH"
+ "Cyber Security Data and Privacy Breach","CSB"
+ "Cyber Security Property Damage", "CPD"
+ "Pandemic Flu", "PNF"
+ "Volcanic Ash Cloud", "VVA"
+ "Volcanic lava flow/eruption", "VVE"
+ "Volcanic landslide/mudslide", "VVL"
+
+
+The input format codes are designed to be easier to populate and recognize by an analyst. The reason for the slightly counterintuitive form of some of the abbreviations is that they are designed so that a predominant peril can quickly be identified by searching for one particular character in the abbreviations: ‘B’ for Fire, ‘O’ for Flood, ‘Q’ for Quake, ‘X’ for Convective storm, ‘Z’ for Winter storm, ‘W’ for Wind, ‘M’ for Terrorism.
+
+As well as the individual peril codes in the above table, there are also codes for common groupings of perils as shown in the table below.
+
+.. csv-table::
+ :widths: 130,30
+ :header: "Peril Group", "Input Code"
+
+ "Earthquake perils", "QQ1"
+ "Windstorm with storm surge", "WW1"
+ "Windstorm w/o storm surge", "WW2"
+ "Flood w/o storm surge", "OO1"
+ "Winter storm", "ZZ1"
+ "Convective storm", "XX1"
+ "Convective storm incl. winter storm (for RMS users)", "XZ1"
+ "Terrorism", "MM1"
+ "Wildfire with smoke", "BB1"
+ "Pandemic", "PP1"
+ "Crop", "GG1"
+ "Cyber", "CC1"
+ "Volcanic", "VV1"
+ "All perils", "AA1"
+
+
+There are several fields in the OED input tables for storing the peril codes.
+
+Firstly, there are two fields that indicate whether or not a peril is covered for a particular location or policy: **LocPerilsCovered** and **PolPerilsCovered** respectively. These can be used to exclude a certain peril completely from a location or a particular policy.
+
+Secondly, there are fields that indicate the perils that a particular level of financial structure covers: **LocPeril, CondPeril, PolPeril, AccPeril** and **ReinsPeril**. These indicate the perils that the financial terms (limits or deductibles) in that particular row of data apply to.
+
+Note that this means there are two peril code fields at location and policy level (**LocPerilsCovered / LocPeril and PolPerilsCovered / PolPeril**). The **LocPerilsCovered** and **PolPerilsCovered** fields define the overall coverage for a location or policy irrespective of financial fields. This makes it much easier for the analyst to filter locations or policies that cover specific perils.
+
+For all of these peril fields, the peril codes (either individual or peril-group codes) are entered separated by semi-colons. So for example, if a location covered wind (including all wind sub-perils) and earthquake (including all EQ sub-perils) then the users would enter *‘QQ1;WW1’* in the **LocPerilsCovered** field. If there is a policy level limit that only applies to wind, then the user would enter *‘WW1’* in the **PolPerils** field.
+
+The way these peril codes have been designed means there is great flexibility in indicating the coverage or exclusion of perils and allowing different limits and deductibles to apply to different perils. Some examples of this are shown in the examples part of the **Financial Details** section.
diff --git a/docs/source/explanation/images/Hierarchy.png b/docs/source/explanation/images/Hierarchy.png
new file mode 100644
index 00000000..61dd4663
Binary files /dev/null and b/docs/source/explanation/images/Hierarchy.png differ
diff --git a/docs/source/explanation/import-format.rst b/docs/source/explanation/import-format.rst
new file mode 100644
index 00000000..f45827c5
--- /dev/null
+++ b/docs/source/explanation/import-format.rst
@@ -0,0 +1,142 @@
+OED Import Format
+====================
+
+The import format for OED is defined by four .csv files:
+
+• Location (loc)
+• Account (acc)
+• Reinsurance info (RIinfo)
+• Reinsurance scope (RIscope)
+
+The fields in each file and their corresponding data type are described in the ‘OED Input Fields’ tab in the OED Data Spec spreadsheet found here:
+
+https://github.com/OasisLMF/ODS_OpenExposureData/tree/main/Docs
+
+
+Location ('loc') Import File
+############################
+
+This file contains details relating to each location such as the value and type of asset (including primary and secondary modifiers), geographical information, the perils covered and the financial structures within the insurance contract relating to the location.
+
+This file is the only mandatory file to run a model and to produce the ground-up losses.
+
+For simple cases, one location is represented by one row in the file. However, for cases with location level financial structures that vary by peril, or where multiple special conditions associated with a particular location exist, one location can be represented by multiple rows. This is necessary to allow the full complexity of financial contracts to be represented in a limited number of input files.
+
+For example, a simple location covering wind ('WW1' – see the Perils section in document 5) and flood ('OO1') with a 100 deductible for buildings (which applies to the combined loss from both perils if both perils happen in a single event) could be represented as follows:
+
+|
+
+.. csv-table::
+ :widths: 25,25,30,20,35,35
+ :header: "LocNumber", "BuildingTIV", "LocPerilsCovered", "LocPeril", "LocDedType1Building", "LocDed1Building"
+
+ "1", "100,000", "OO1;WW1", "OO1;WW1", "0", "100"
+
+|
+
+If the same location had a 100 deductible for wind but a 1000 deductible for flood that applied to losses from each peril separately, this would be represented in the location input file as shown below:
+
+|
+
+.. csv-table::
+ :widths: 25,25,30,20,35,35
+ :header: "LocNumber", "BuildingTIV", "LocPerilsCovered", "LocPeril", "LocDedType1Building", "LocDed1Building"
+
+ "1", "100,000", "OO1;WW1", "WW1", "0", "100"
+ "1", "100,000", "OO1;WW1", "OO1", "0", "1000"
+
+|
+
+The field names in the examples above are described further in documents 4, 5 and 6.
+
+https://github.com/OasisLMF/OpenDataStandards/tree/master/OpenExposureData
+
+The minimum fields required in a location file are **LocNumber, AccNumber, PortNumber, CountryCode, LocPerilsCovered, LocCurrency, BuildingTIV, ContentsTIV, BITIV, OtherTIV**.
+
+The full set of fields in a location import file can be found by filtering on ‘Loc’ in the 'Input File' column of the 'OED Input Fields' sheet within the *Open Exposure Data Spec* spreadsheet.
+
+There are over 200 potential fields that could be used within the location file. However, it is not mandatory to use a field that contains no data and so, most OED location input files will contain far fewer than 200 columns.
+
+|
+
+Account (acc) Import File
+#########################
+
+The account file contains details of the policies and accounts that exist within the import portfolios. Most of the fields in this file relate to financial structures, including special conditions.
+
+This file is always required when modelling for insured (or gross) losses.
+
+An account may contain multiple policies and typically, each row will represent one policy. However, for cases with policy level financial structures that vary by peril or where a policy contains multiple special conditions, one policy may have multiple rows in the account file.
+
+The minimum fields required in an account file are **AccNumber**, **AccCurrency, PolNumber, PortNumber, PolPerilsCovered**.
+
+The full set of fields in an account import file can be found by filtering on ‘Acc’ in the 'Input File' column of the 'OED Input Fields' sheet within the *Open Exposure Data Spec* spreadsheet.
+
+Similarly to the loc file, there are over 200 potential fields that could be used within the account file, but it is not mandatory to use a field that contains no data and so, most OED account input files will contain far fewer than 200 columns.
+
+For example, if account level financial terms are not required (i.e. financial terms that apply across groups of policies) then all the financial fields starting with ‘Acc’ can be omitted (removing the need for 48 fields). If special conditions are not required another 48 fields can be excluded. See the section on financial structures along with the examples for details of how the financial structure fields operate together in document 6.
+
+https://github.com/OasisLMF/OpenDataStandards/tree/master/OpenExposureData
+
+|
+
+Reinsurance Info (RIinfo) Import File
+#####################################
+
+The reinsurance info file contains details of the reinsurance contracts that relate to the underlying portfolios, accounts and locations. There must be exactly one entry per reinsurance contract in this file. Any financial terms relating to reinsurance contracts should be entered in this file with the exception of the **CededPercent** for a surplus treaty (which should be entered in the reinsurance scope file).
+
+For a list of the reinsurance financial terms available and examples about how to specify such terms see the reinsurance section and associated examples.
+If there is no reinsurance, this import file is not required. If there is reinsurance, the minimum fields required are **ReinsNumber, ReinsPeril, ReinsCurrency, InuringPriority, ReinsType, PlacedPercent**.
+
+**ReinsNumber** must be unique, as this links with the reinsurance scope file.
+
+The **RiskLevel** of a reinsurance contract refers to the level at which ‘risk’ terms apply. A ‘risk’ can either be defined at Location ‘LOC’, Location Group ‘LGR’, Policy ‘POL’ or Account level ‘ACC’. If a reinsurance contract does not contain risk specific terms then the **RiskLevel** field should be left blank. Note that it is not only per-risk treaties that have risk level terms. A facultative contract, a quota share treaty or even a catastrophe XL may also have risk level terms and thus require a risk level to be defined.
+
+The full set of fields in a reinsurance info import file can be found by filtering on ‘ReinsInfo’ in the 'Input File' column of the *Open Exposure Data Spec* spreadsheet. There are over 20 potential fields that could be used within the reinsurance info file. However, it is not mandatory to use a field that contains no data.
+
+|
+
+Reinsurance Scope (RIscope) Import File
+#########################################
+
+The reinsurance scope file contains details of two different but related pieces of information:
+
+• The scope of the reinsurance contract: i.e. which portfolios, accounts, locations are covered by a particular reinsurance contract.
+
+• The CededPercent for a surplus treaty: which can vary for each risk covered by the treaty.
+
+The above two points are discussed in turn below.
+
+The scope of what a reinsurance contract applies to is defined by the ten ‘filter fields’ available in the reinsurance scope file: **PortNumber, AccNumber, PolNumber, LocGroup, LocNumber, CedantName, ProducerName, LOB, CountryCode, ReinsTag.**
+
+|
+
+**For example:**
+
+If a reinsurance contract applies to a particular portfolio ‘A’ then the value ‘A’ would be entered in the **PortNumber** field.
+
+If reinsurance applies only to account B in portfolio A, then ‘A’ would be entered in the **PortNumber** field and ‘B’ would be entered in the same row in the **AccNumber** field. In other words, entering criteria in the same row essentially applies an *AND* condition.
+Scope information relating to the same reinsurance contract can also be applied in separate rows: in this case each row would act like an *OR* condition for the filter.
+
+|
+
+**For example:**
+
+If **PortNumber** = ‘A’ is entered in one row and **AccNumber** = ‘B’ is entered in a separate row, then the scope of the reinsurance policy would apply to all records that match the condition: all records in portfolio ‘A’ *OR* any records in account number ‘B’.
+
+If **LocNumber** is used as a scope filter then **AccNumber** and **PortNumber** must be specified too (otherwise **LocNumber** does not uniquely identify a location).
+If **PolNumber** is used as a scope filter then **AccNumber** and **PortNumber** must be specified too (otherwise **PolNumber** does not uniquely identify a policy).
+
+Surplus treaties require entry of **CededPercent** at the risk level. For example, if the risk level within a surplus treaty is location (LOC), then the user must list every location covered by the treaty in the **LocNumber** field (along with **AccNumber** and **PortNumber** to uniquely identify the location within the file) as well as the **CededPercent** for each location.
+
+Although the reinsurance scope and the risk level are two different concepts, for facultative contracts and surplus treaties, the OED format requires that the risk level for a particular contract should also be used to define the scope of the contract. This is because these contracts, by their nature, either apply to individual risks (facultative) or have a ceded percent that varies by risk (surplus), and so to have scope defined by fields different to the risk level would cause ambiguity and confusion.
+
+If there is no reinsurance, the reinsurance scope import file is not required. If there is reinsurance, each reinsurance entry in the reinsurance info file must have at least one entry in the reinsurance scope file; some contracts will have multiple entries in the scope file.
+
+The minimum fields required are: **ReinsNumber**, at least one of the ten filter fields, and **CededPercent** for surplus treaties.
+The full set of fields in a reinsurance scope import file can be found by filtering on ‘ReinsScope’ in the Input File column of the *Open Exposure Data Spec* spreadsheet. There are over 10 potential fields that could be used within the reinsurance scope file. However, it is not mandatory to use a field that contains no data.
+
+These filter fields are mostly optional and can be included in the scope file and used as needed. The exception is when specifying filters using **LocNumber** and **PolNumber**, the fields **AccNumber** and **PortNumber** are conditionally required and must also be populated, and **PortNumber** is required to be populated when **AccNumber** is used as a filter. These field dependencies are expressed as 'Conditionally Required' 'CR' codes and included in the 'OED CR Field Appendix' tab of the *Open Exposure Data Spec*.
+
+For a list of the reinsurance financial terms available and examples about how to specify such terms see the reinsurance section and associated examples.
+
diff --git a/docs/source/explanation/index.md b/docs/source/explanation/index.md
new file mode 100644
index 00000000..281563c8
--- /dev/null
+++ b/docs/source/explanation/index.md
@@ -0,0 +1,66 @@
+# Explanation
+
+Background on the OED standard — what it is, its file structure and the exposure hierarchy.
+Detailed chapters (import format, asset details, geography & perils, financial terms and
+reinsurance) are migrated from the standard's specification documents.
+
+## The four input files
+
+OED comprises four input files, designed to let users enter data in a manageable way without
+having to understand the relationships between many underlying tables:
+
+- **Location (`Loc`)** — the exposed locations and their coverages, characteristics and
+ primary financial terms.
+- **Account (`Acc`)** — accounts and policies, including policy-level financial terms and
+ special conditions.
+- **Reinsurance Info (`ReinsInfo`)** — the reinsurance programme definitions.
+- **Reinsurance Scope (`ReinsScope`)** — what each reinsurance contract applies to.
+
+This trades some duplication for practicality. The full field lists are in the
+{doc}`field reference <../reference/fields>`.
+
+## The exposure hierarchy
+
+OED follows an organisational and financial hierarchy familiar to catastrophe-model users:
+
+Coverage
+: The lowest level — the specific type of cover: **Buildings**, **Other** (e.g. appurtenant
+ structures or motor), **Contents**, and **Business Interruption** (time element). Primary
+ financial terms can attach at coverage level, across property damage (PD = Buildings +
+ Other + Contents), or across all coverages.
+
+Location
+: A site — a group of coverages at one place. Primary financial terms and facultative
+ reinsurance can attach here. A single location record can represent several buildings
+ (`NumberOfBuildings`), and related locations can be linked (`LocGroup`).
+
+Policy
+: A financial structure applying to a set of locations. Multiple policies can exist under
+ the same account and apply to the same locations (e.g. insurance layers). Within a policy,
+ a **special condition** applies sub-limits/sub-deductibles to a subset of locations.
+ Reinsurance can attach at policy level.
+
+Account
+: The top organisational level, grouping policies. A **portfolio** (`PortNumber`) groups
+ accounts.
+
+## Coded values
+
+Many OED fields draw on controlled vocabularies (perils, occupancy, construction, country,
+coverage). Those allowed values are in the {doc}`coded values reference <../reference/values>`.
+
+## Detailed chapters
+
+The full specification narrative, migrated from the OED standard documents:
+
+```{toctree}
+:maxdepth: 1
+
+rationale
+import-format
+asset-details
+geography-perils
+financial-primary
+financial-policy-conditions
+reinsurance
+```
diff --git a/docs/source/explanation/rationale.rst b/docs/source/explanation/rationale.rst
new file mode 100644
index 00000000..fa7de445
--- /dev/null
+++ b/docs/source/explanation/rationale.rst
@@ -0,0 +1,44 @@
+Rationale
+=========
+
+The need for a new (re)insurance industry exposure data standard arose from the lack of such an existing standard for Oasis based models. Exposure data is the starting point for catastrophe risk analysis, and without such a standard in place it is impossible to give users guidance and documentation on how to prepare their input data and enable appropriate validation within Oasis based modelling platforms.
+
+The Oasis financial model (FM) enables a wide variety of model developers to use one consistent financial model: it is a key part of the utility of the Oasis framework. However, it is important that financial fields in the exposure data correspond well with the financial model to enable the full scope of the financial model to be used. The OED has been designed from the outset to work well with, and enable the full functionality of, the Oasis FM.
+
+The OED also provides companies with a starting point for implementing a model-developer-independent exposure data repository, which is strategically beneficial as it prevents firms being locked in to any one particular model developer.
+
+Although OED is designed to work well with Oasis based models, the scope of OED is wider than Oasis. For example, financial fields exist in OED which are not yet implemented in Oasis and secondary modifiers that exist in OED which are not currently used by any Oasis based model. However, Oasis LMF continue to expand the scope of their FM with the aim to support as much of the OED functionality as possible.
+
+In the meantime, users should consult their platform / model specific documentation to understand which elements within OED are being used by a certain model at a particular time.
+
+
+OED Abbreviations
+-----------------
+
+The following abbreviations are used in OED field names:
+
+.. csv-table::
+ :widths: 8, 40
+ :header: "Abbreviation", "Description"
+
+ "Acc", "Account"
+ "Agg", "Aggregate"
+ "BI", "Business interruption, but also used to denote other time-based coverage insurable values such as alternative living expenses"
+ "Cond", "Condition (as in special condition such as sub-limit or sub-deductible)"
+ "Cov", "Coverage"
+ "Ded", "Deductible"
+ "Def", "Defined (as in user defined)"
+ "FX", "Exchange rate"
+ "LOB", "Line of business"
+ "Loc", "Location"
+ "Max", "Maximum"
+ "Min", "Minimum"
+ "Occ", "Occurrence"
+ "Org", "Original"
+ "PD", "Property damage"
+ "POI", "Period of indemnity"
+ "Pol", "Policy"
+ "Port", "Portfolio"
+ "Reins", "Reinsurance"
+ "TIV", "Total insurable value"
+ "Vuln", "Vulnerability"
diff --git a/docs/source/explanation/reinsurance.rst b/docs/source/explanation/reinsurance.rst
new file mode 100644
index 00000000..ebb4c641
--- /dev/null
+++ b/docs/source/explanation/reinsurance.rst
@@ -0,0 +1,364 @@
+Reinsurance
+============
+
+There are many different types of reinsurance available and many different combinations of financial terms that can apply within each type of reinsurance. The scope of each reinsurance contract, and the definition of risk level that applies within a contract (if there are per-risk terms), are also important considerations that are discussed in the following sections.
+
+|
+
+Reinsurance Types and Terms
+###########################
+
+OED has been designed to allow capture of a broad range of reinsurance terms without the need to enter any information directly through a user interface. The range of reinsurance types that are currently considered within OED are as follows.
+
+|
+
+.. csv-table::
+ :header: "Type of Reinsurance", "Value in ReinsType Field", "Notes"
+
+ "Facultative", "FAC", "Excess of loss (or sometimes proportional) contract applicable at location, location group, policy or account level. The risk level must be consistent with the field used to define the scope. **RiskLimit, RiskAttachment** and **PlacedPercent** are typically the fields used."
+ "Quota Share", "QS", "A proportional contract applicable to a tranche of exposure defined using the reinsurance scope filter fields. **PlacedPercent**, and sometimes **RiskLimit** and **OccLimit** are typically the fields used."
+ "Surplus Share", "SS", "A proportional contract where the proportion ceded varies by risk. The risk level must be consistent with the field used to define the scope. **CededPercent** must be specified for each risk in the reinsurance scope table. **OccLimit** is sometimes also used."
+ "Per Risk Treaty", "PR", "An excess of loss contract applying per-risk to a tranche of exposure defined using the reinsurance scope filter fields. 'RiskLimit, RiskAttachment' and sometimes 'PlacedPercent' and 'OccLimit' are the fields typically used."
+ "Catastrophe Excess of Loss", "CXL", "An excess of loss contract applying per-event to a tranche of exposure defined using the reinsurance scope filter fields. **OccLimit, OccAttachment** and sometimes **PlacedPercent** are the fields typically used."
+ "Aggregate Excess of Loss", "AXL", "An aggregate excess of loss contract applying per-period to a tranche of exposure defined using the reinsurance scope filter fields. **AggLimit, AggAttachment** and sometimes **PlacedPercent** are the fields typically used."
+
+
+The fields used to define reinsurance financial terms are given in the table below. These are all specified in the reinsurance info table, although for surplus treaties note that **CededPercent** must be specified in the reinsurance scope table.
+
+|
+
+.. csv-table::
+ :widths: 18, 60
+ :header: "Field Name", "Description"
+
+ "RiskLevel", "The definition of risk. See below for more information."
+ "RiskLimit", "Limit applicable to the losses from an event at the defined **RiskLevel.**"
+ "RiskAttachment", "Attachment applicable to the losses from an event at the defined **RiskLevel.**"
+ "OccLimit", "Limit applicable to the sum of losses from an event."
+ "OccAttachment", "Attachment applicable to the sum of losses from an event."
+ "OccFranchiseDed", "A per-occurrence deductible that vanishes when it is exceeded."
+ "OccReverseFranchise", "The total event loss is excluded from the treaty if the reverse franchise threshold is exceeded."
+ "AggLimit", "Limit applicable to the sum of losses within an **AggPeriod.**"
+ "AggAttachment", "Attachment applicable to the sum of losses within an **AggPeriod.**"
+ "AggPeriod", "The period within which to sum losses (in days)."
+ "InuringPriority", "Indicates the order in which reinsurance applies. 1 denotes the contract that applies first."
+ "Reinstatement", "The number of reinstatements."
+ "CededPercent", "The percentage applied to the gross loss entering the reinsurance contracts before other reinsurance terms. Predominantly used for surplus treaties. Unlike all the other terms in this table, **CededPercent** is specified in the reinsurance scope table for surplus treaties and in the reinsurance info table for all other treaty types."
+ "PlacedPercent", "The percentage applied to the reinsurance loss after other reinsurance terms. Predominantly used for all contracts other than surplus treaties."
+ "TreatyShare", "The treaty share which is applicable to the individual reinsurer."
+
+
+|
+
+Risk Level
+##########
+
+The term ‘risk level’ in the table above refers to what is defined as a ‘risk’ in the context of the particular reinsurance treaty. The definition of what constitutes a risk is an involved subject, but the reinsured usually defines this. For example, a risk could be one building in a large spread-out site, a number of buildings defined by such a site, a combination of sites close together, or a policy layer or account.
+
+In the context of OED a risk-level is specified in the **RiskLevel** field in the reinsurance info table and can be defined as either location (*LOC*), location-group (*LGR*), policy (*POL* - including individual layers) or account level (ACC). Risk level is only relevant for reinsurance contracts with risk-level terms. However, this can include facultative contracts, quota share and surplus treaties and catastrophe excess of loss contracts as well as per-risk treaties.
+
+|
+
+Reinsurance Percentages and Calculation Order
+#############################################
+
+There are various percentages defined in OED that are applicable to reinsurance, and several kinds of limits and attachments so it is important to be clear about the order in which they work. The main principles are outlined below.
+
+The loss applicable to a reinsurance contract is the gross loss (assuming no inuring reinsurance contracts). In other words the loss to which reinsurance terms are applied is the ground-up loss net of all primary insurance limits, deductibles and shares.
+
+The order of application of reinsurance terms is then as follows:
+
+1. **CededPercent** is applied to the gross loss. This applies before any other reinsurance terms including per risk terms, per occurrence terms or aggregate terms. This is typically used in surplus treaties (in the reinsurance scope table) where event limits within such treaties are always specified in terms of treaty loss (and not in terms of the gross loss). It could also be used within quota share treaties (within the reinsurance info table) if the risk or event limit terms within a quota share treaty are specified in terms of treaty loss rather than gross loss (although this is unusual).
+
+2. Risk terms are applied.
+
+3. Occurrence terms are applied.
+
+4. Aggregate terms are applied.
+
+5. **PlacedPercent** is applied. This applies after all other reinsurance terms. This is the percentage field that is normally used for treaty types other than surplus.
+
+|
+
+Examples of OED Tables Including Reinsurance
+############################################
+
+The examples below demonstrate how the reinsurance info and reinsurance scope tables work and interact with the account and location tables. As with the other examples in this document, not all the required fields are shown in the tables.
+
+**Example 1 - Facultative Reinsurance**
+
+The tables below demonstrate two facultative reinsurance contracts, one at location level and one at policy level.
+
+A 0.5m xs 1m location level facultative contract applies to location 2 in account 1, and a 1.2m xs 2.0m policy level facultative reinsurance contract applies to policy 1 in account 3.
+
+|
+
+OED Account file:
+
+.. csv-table::
+ :widths: 10,10,10,12,12,15,10
+ :header: "PortNumber", "AccNumber", "PolNumber", "PolDedType6All", "PolDed6All", "PolLimitType6All", "PolLimit6All"
+
+ "1", "1", "1", "0", "50,000", "0", "1,500,000"
+ "1", "2", "1", "2", "0.05", "0", "1,500,000"
+ "1", "3", "1", "1", "0.10", "2", "0.80"
+
+|
+
+OED Location file:
+
+.. csv-table::
+ :widths: 8,8,8,8,12,10
+ :header: "PortNumber", "LocNumber", "AccNumber", "BuildingTIV", "LocDedType1Building", "LocDed1Building"
+
+ "1", "1", "1", "1,000,000", "0", "10,000"
+ "1", "2", "1", "1,000,000", "2", "0.01"
+ "1", "1", "2", "1,000,000", "1", "0.05"
+ "1", "2", "2", "2,000,000", "0", "15,000"
+ "1", "1", "3", "2,000,000", "0", "10,000"
+ "1", "2", "3", "2,000,000", "2", "0.10"
+
+|
+
+OED Reinsurance Info file:
+
+.. csv-table::
+ :widths: 10,10,12,10,10,10,10
+ :header: "ReinsNumber", "ReinsType", "RiskAttachment", "RiskLimit", "PlacedPercent", "InuringPriority", "RiskLevel"
+
+ "1", "FAC", "1,000,000", "500,000", "1.0", "1", "LOC"
+ "2", "FAC", "2,000,000", "1,200,000", "1.0", "1", "POL"
+
+|
+
+OED Reinsurance Scope file:
+
+.. csv-table::
+ :header: "ReinsNumber", "PortNumber", "AccNumber", "PolNumber", "LocNumber"
+
+ "1", "1", "1", "", "2"
+ "2", "1", "3", "1", ""
+
+|
+
+The reinsurance info table must contain one row per **ReinsNumber**. **ReinsNumber** must be unique in this table. Although not shown, the reinsurance info table must always contain the **ReinsPeril** field, indicating which perils the reinsurance contract covers.
+
+Facultative contracts are typically 100% placed and so **PlacedPercent** is 1.0. Given that these are contracts on different accounts there is no concept of one contract inuring to the benefit of the other and so the **InuringPriority** is 1.
+
+The reinsurance scope table must contain at least one entry for every **ReinsNumber** in the reinsurance info table. Although not the case in this example, it can contain more than one entry for a given **ReinsNumber**.
+
+Only four of the ten possible filter fields are shown in the example above: **PortNumber, AccNumber, PolNumber** and **LocNumber**.
+
+The combination of the filter fields for **ReinsNumber = 1** means that the facultative contract will apply to the records where the following logical statement is true:
+
+**PortNumber = 1** AND **AccNumber = 1** AND **LocNumber = 2**
+
+i.e. to location 2 in account 1 in portfolio 1.
+
+For **ReinsNumber** 2 the facultative contract will apply to the records where the following logical statement is true:
+
+**PortNumber = 1** AND **AccNumber = 3** AND **PolNumber = 1**
+
+i.e. to policy 1 in account 3 in portfolio 1.
+
+The **RiskLevel** is defined as *LOC* for **ReinsNumber** 1 and *POL* for **ReinsNumber** 2.
+
+The only filter fields that can be used for facultative (and surplus treaties) are **PortNumber, AccNumber, PolNumber, LocNumber** and **LocGroup** – i.e. portfolio plus the filter fields that correspond with the different risk levels: *ACC, POL, LOC* and *LGR*.
+
+|
+
+**Example 2 – Quota Share Reinsurance**
+
+The example shows the OED specification for a 20% quota share reinsurance contract, applying to locations within Great Britain in portfolio 1, with a risk limit of 100,000 and an event limit of 1,000,000. ‘Risk’ is defined as a location, and risk and event limits are specified in terms of gross amount (i.e. the loss before the application of the 20% quota share).
+
+
+OED Account file:
+
+.. csv-table::
+ :widths: 8,8,8,8,8,8,8
+ :header: "PortNumber", "AccNumber", "PolNumber", "PolDedType6All", "PolDed6All", "PolLimitType6All", "PolLimit6All"
+
+
+ "1", "1", "1", "0", "50,000", "0", "1,500,000"
+ "1", "2", "1", "2", "0.05", "0", "1,500,000"
+ "1", "3", "1", "1", "0.10", "2", "0.80"
+
+|
+
+OED Location file:
+
+
+.. csv-table::
+ :widths: 8,8,8,8,8,8,8
+ :header: "PortNumber", "LocNumber", "AccNumber", "CountryCode", "BuildingTIV", "LocDedType1Building", "LocDed1Building"
+
+ "1", "1", "1", "GB", "1,000,000", "0", "10,000"
+ "1", "2", "1", "GB", "1,000,000", "2", "0.01"
+ "1", "1", "2", "GB", "1,000,000", "1", "0.05"
+ "1", "2", "2", "GB", "2,000,000", "0", "15,000"
+ "1", "1", "3", "DE", "2,000,000", "0", "10,000"
+ "1", "2", "3", "DE", "2,000,000", "2", "0.10"
+
+
+
+OED Reinsurance Info file:
+
+.. csv-table::
+ :header: "ReinsNumber", "ReinsType", "RiskLimit", "OccLimit", "PlacedPercent", "InuringPriority", "RiskLevel"
+
+ "1", "QS", "100,000", "1,000,000", "0.20", "1", "LOC"
+
+|
+
+OED Reinsurance Scope file:
+
+.. csv-table::
+ :header: "ReinsNumber", "PortNumber", "AccNumber", "PolNumber", "LocNumber", "CountryCode"
+
+ "1", "1", "","","", "GB"
+
+
+|
+
+In the reinsurance info table in the example above, **PlacedPercent** is used to specify the 20% quota share. This means that the risk and occurrence limits will apply before the application of the 20%. In other words, the risk and occurrence terms apply to the gross figure. This is normally the way quota share treaties are worded (so that it is clear how the risk and occurrence limits relate to the attachments of other per-risk and per-occurrence contracts that the reinsured may have).
+
+However, some quota share treaties are worded with limits applying to the amount ceded to the treaty (i.e. after application of the 20%). If that is the case, then the user can specify 0.2 in the **CededPercent** field instead of **PlacedPercent**: **CededPercent** always applies to the incoming loss before any other terms (**PlacedPercent** always applies to the loss after all other terms). Alternatively, the user could gross up the limits to represent 100% values and continue to use **PlacedPercent**.
+
+The logic in the reinsurance scope table means that only items with **PortNumber = 1** AND **CountryCode = GB** will be covered by the quota share contract. This means that losses from locations in account 3 will not be ceded to this treaty (as the locations in account 3 are in Germany).
+
+|
+
+
+**Example 3 - Surplus share reinsurance**
+
+The example shows how a 3-line surplus treaty with a retention of 500,000 is specified in OED. The surplus treaty has an event limit of 3,000,000 (applicable to the loss ceded to the treaty, not the gross amount), and ‘risk’ is defined as the location.
+
+OED Account file:
+
+.. csv-table::
+ :widths: 10,10,10,12,12,12,10
+ :header: "PortNumber", "AccNumber", "PolNumber", "PolDedType6All", "PolDed6All", "PolLimitType6All", "PolLimit6All"
+
+ "1", "1", "1", "0", "50,000", "0", "1,500,000"
+ "1", "2", "1", "2", "0.05", "0", "1,500,000"
+ "1", "3", "1", "1", "0.10", "2", "0.80"
+
+|
+
+OED Location file:
+
+.. csv-table::
+ :widths: 8,8,8,10,12,12
+ :header: "PortNumber", "LocNumber", "AccNumber", "BuildingTIV", "LocDedType1Building", "LocDed1Building"
+
+ "1", "1", "1", "1,000,000", "0", "10,000"
+ "1", "2", "1", "1,000,000", "2", "0.01"
+ "1", "1", "2", "1,000,000", "1", "0.05"
+ "1", "2", "2", "2,000,000", "0", "15,000"
+ "1", "1", "3", "2,000,000", "0", "10,000"
+ "1", "2", "3", "2,000,000", "2", "0.10"
+
+|
+
+OED Reinsurance Info file:
+
+.. csv-table::
+ :widths: 8,8,8,8,8,8,8
+ :header: "ReinsNumber", "ReinsType", "RiskLimit", "OccLimit", "PlacedPercent", "InuringPriority", "RiskLevel"
+
+ "1", "SS", "0", "3,000,000", "1.0", "1", "LOC"
+
+|
+
+OED Reinsurance Scope file:
+
+.. csv-table::
+ :header: "ReinsNumber", "PortNumber", "AccNumber", "PolNumber", "LocNumber", "CededPercent"
+
+ "1", "1", "1", "", "1", "0.50"
+ "1", "1", "1", "", "2", "0.50"
+ "1", "1", "2", "", "1", "0.50"
+ "1", "1", "2", "", "2", "0.75"
+ "1", "1", "3", "", "1", "0.75"
+ "1", "1", "3", "", "2", "0.75"
+
+|
+
+For surplus treaties, **CededPercent** must be specified for each risk in the reinsurance scope table.
+
+Unlike in the previous quota share example, the 3,000,000 event limit specified in the reinsurance info table applies to losses after the application of the surplus percentage. This is because **CededPercent** is always used for surplus treaties, and **CededPercent** applies before any other terms.
+
+With surplus treaties, the following rule must be followed (they are the same as for facultative treaties):
+
+• Only the filter fields **PortNumber, AccNumber, PolNumber, LocNumber** & **LocGroup** can be used with surplus treaties.
+
+|
+
+**Example 4 - Per-risk and cat XL reinsurance**
+
+The example below shows the specification of two reinsurance treaties – both of which apply to portfolios 1 and 2, with the per-risk contract inuring to the benefit of the cat XL contract.
+
+
+OED Account file:
+
+.. csv-table::
+ :widths: 8,8,8,8,8,8,8
+ :header: "PortNumber", "AccNumber", "PolNumber", "PolDedType6All", "PolDed6All", "PolLimitType6All", "PolLimit6All"
+
+ "1", "1", "1", "0", "50,000", "0", "1,500,000"
+ "1", "2", "1", "2", "0.05", "0", "1,500,000"
+ "2", "1", "1", "1", "0.10", "2", "0.80"
+
+
+|
+
+OED Location file:
+
+.. csv-table::
+ :widths: 5,5,5,5,8,6
+ :header: "PortNumber", "LocNumber", "AccNumber", "BuildingTIV", "LocDedType1Building", "LocDed1Building"
+
+ "1", "1", "1", "1,000,000", "0", "10,000"
+ "1", "2", "1", "1,000,000", "2", "0.01"
+ "1", "1", "2", "1,000,000", "1", "0.05"
+ "1", "2", "2", "2,000,000", "0", "15,000"
+ "2", "1", "1", "2,000,000", "0", "10,000"
+ "2", "2", "1", "2,000,000", "2", "0.10"
+
+|
+
+OED Reinsurance Info file:
+
+.. csv-table::
+ :header: "ReinsNumber", "ReinsType", "RiskAttachment", "RiskLimit", "OccAttachment", "OccLimit", "InuringPriority", "RiskLevel"
+
+ "1", "PR", "500,000", "1,500,000", "0", "0", "1", "LOC"
+ "2", "CXL", "0", "0", "3,000,000", "3,000,000", "2"
+
+|
+
+
+OED Reinsurance Scope file:
+
+.. csv-table::
+ :header: "ReinsNumber", "PortNumber", "AccNumber", "PolNumber", "LocNumber"
+
+ "1", "1", "", "", ""
+ "1", "2", "", "", ""
+ "2", "1", "", "", ""
+ "2", "2", "", "", ""
+
+|
+
+Note that the account and location tables now contain exposures from two portfolios.
+
+The **InuringPriority** field specifies the order in which treaties apply. Here the per-risk contract applies before (i.e. inures to the benefit of) the Cat XL. This means that the losses that enter the Cat XL treaty are net of any recoveries from the Per-risk treaty. The **InuringPriority** values do not need to be consecutive – the treaty with the lowest number will always be applied before the treaty with the higher number.
+
+The reinsurance scope table contains two rows per treaty. This is to indicate that the treaties apply to both portfolio 1 and portfolio 2. The scope of each reinsurance treaty is defined by those records that satisfy the logical statement: **PortNumber** = *1* OR **PortNumber** = *2*. i.e. records either in portfolio 1 or 2.
+
+Essentially, within each **ReinsNumber**, each row of the reinsurance scope table acts as an OR operator and each filtering column acts as an AND operator. Although only four reinsurance scope fields are shown in the table above, all 10 reinsurance scope filtering fields could be used to define the scope of quota share, per-risk, cat XL or aggregate XL treaties.
+
+The **RiskLevel** of the per-risk treaty is defined at location level (*LOC*). For the Cat XL treaty in this example there are no risk terms and so the **RiskLevel** is left blank.
+
+
+
diff --git a/docs/source/index.md b/docs/source/index.md
new file mode 100644
index 00000000..c4674125
--- /dev/null
+++ b/docs/source/index.md
@@ -0,0 +1,39 @@
+# Open Exposure Data (OED)
+
+**OED** is the open standard for catastrophe-model **exposure data** — a common format for
+describing locations, accounts, policy terms and reinsurance, so that exposure can be moved
+between models and tools without bespoke conversion. It is the exposure counterpart to
+[ORD](https://github.com/OasisLMF/ODS_OpenResultsData) (results data), together forming the
+Open Data Standards (ODS) maintained by the ODS Steering Committee.
+
+This site is the reference for the standard. The field and coded-value definitions are
+generated directly from the authoritative `oed.json` in this repository, so they always match
+the released specification.
+
+::::{grid} 1 1 2 2
+:gutter: 3
+
+:::{grid-item-card} 📖 Explanation
+:link: explanation/index
+:link-type: doc
+
+What OED is, the file structure (Location / Account / Reinsurance), the exposure hierarchy,
+and how financial terms and perils are represented.
+:::
+
+:::{grid-item-card} 📋 Reference
+:link: reference/index
+:link-type: doc
+
+The generated field reference for every input file, plus the coded value lists (perils,
+occupancy, construction, country, coverage).
+:::
+::::
+
+```{toctree}
+:hidden:
+:maxdepth: 2
+
+explanation/index
+reference/index
+```
diff --git a/docs/source/reference/fields.md b/docs/source/reference/fields.md
new file mode 100644
index 00000000..ce5d810a
--- /dev/null
+++ b/docs/source/reference/fields.md
@@ -0,0 +1,24 @@
+# OED fields
+
+The input fields for each OED file, grouped by file. **Status** is the field's requirement
+level for property business:
+
+```{list-table}
+:header-rows: 0
+:widths: 10 90
+
+* - `R`
+ - Required
+* - `O`
+ - Optional
+* - `CR`
+ - Conditionally required (required in certain circumstances — see the field description)
+* - `n/a`
+ - Not applicable to this file / line of business
+```
+
+Line-of-business status for Cyber, Liability and Marine Cargo is carried in `oed.json`
+(`Cyber/Liability/Marine Cargo field status`); the table below shows the property status.
+
+```{include} _generated/oed_fields.md
+```
diff --git a/docs/source/reference/index.md b/docs/source/reference/index.md
new file mode 100644
index 00000000..49c7e17a
--- /dev/null
+++ b/docs/source/reference/index.md
@@ -0,0 +1,11 @@
+# Reference
+
+The authoritative OED schema. These pages are generated at build time from `oed.json` in
+this repository — edit the spec (and its source CSVs), not the generated tables.
+
+```{toctree}
+:maxdepth: 2
+
+fields
+values
+```
diff --git a/docs/source/reference/values.md b/docs/source/reference/values.md
new file mode 100644
index 00000000..563de564
--- /dev/null
+++ b/docs/source/reference/values.md
@@ -0,0 +1,8 @@
+# Coded values
+
+The controlled vocabularies used by OED coded fields — perils, occupancy, construction,
+country and coverage. These are the allowed values for the corresponding fields in the
+{doc}`field reference `.
+
+```{include} _generated/oed_values.md
+```