open-lec · v0.2 · apache-2.0 · zero dependencies

Every risk engine ends at the same picture.
Make it portable.

FAIR Monte Carlo simulators, GRC platforms, actuarial models, a numpy notebook — they all finish at the probability that annual loss meets or exceeds a given amount. open-lec is the missing interchange layer: one small JSON spec, so any engine can emit a Loss Exceedance Curve and any surface can render it.


$npm install open-lec
01  The curve

One document, board-ready

Everything below — two scenarios, 90% uncertainty bands, a risk-tolerance line, derived statistics — is a single open-lec document, rendered live by the zero-dependency renderer. Hover for exceedance probabilities and return periods.

Ransomware & BEC exposure — FY2026
eal · baseline
eal · treated
after controls
1-in-100 yr · baseline
risk reduction
expected annual loss
✓ tip

This exact document ships with the repository as examples/baseline-vs-treatment.json. Open it in the playground to edit, re-validate, and export it.

02  The instrument

How to read a loss exceedance curve

The LEC is the standard visual instrument for communicating quantified cyber and operational risk. Each point answers one question.

P(loss ≥ x)
Exceedance probability

Pick a loss on the x-axis; the curve gives the probability that annual loss meets or exceeds it. Losses ascend strictly; exceedance never rises — both are conformance requirements, not conventions.

1 / p
Return period

An exceedance probability of 1% is a 1-in-100-year loss. The renderer surfaces return periods in the hover tooltip; the library derives them from any point on the curve.

∫ P(X ≥ x) dx
Expected annual loss

The area under the curve is the expected annual loss — computed exactly under the declared interpolation profile, and flagged as a lower bound when the tail is truncated.

03  The format

Small enough to hand-write

A conforming document is ~15 lines: version, currency, and at least one curve. Everything else — roles, bands, reference lines, annotations, statistics — is additive.

my-first.lec.json

      
    
§4
Semantics are part of the spec

Monotone exceedance, strictly ascending losses, band coherence — the reference validator enforces the rules JSON Schema alone cannot express, with exact paths in every error.

x-
Forward compatible by rule

Readers ignore unknown keys, extensions live under x- namespaces, and 0.x minors are additive — a 0.1 document validates against every later 0.x validator.

Results, not models

No methodology is imposed and no simulation inputs are captured. If it plots as P(annual loss ≥ x), it fits — FAIR, actuarial, or a notebook.

04  The toolchain

Spec, validator, renderer, CLI

One package, zero dependencies. Each layer is separately importable and everything composes over stdin/stdout.

validate & inspect
$npx openlec validate my-lec.json
$npx openlec stats my-lec.json --json
✓ my-lec.json is a conforming open-lec 0.2 document (2 scenarios)

CI-friendly exit codes; validation errors state the path, the rule, and the fix — never an apology.

render anywhere
$npx openlec render my-lec.json -o chart.svg

The browser renderer and the headless SVG exporter share all drawing code — the chart in your dashboard and the chart in your board deck are the same chart. React ships as open-lec/react.

v0.2.0 apache-2.0 zero deps json schema typescript types
05  Adoption

Emit it from what you already have

Adapters convert common CRQ outputs into conforming documents — and the universal path is raw Monte Carlo samples from any engine.

riskquant
Netflix riskquant CSV

openlec from riskquant scenarios.csv re-runs its Poisson × lognormal model with a seeded Monte Carlo and emits per-scenario curves, bands, and an optional portfolio aggregate.

samples
Raw iterations, any engine

One annual loss per iteration — JSON array or one-column CSV — becomes a curve with a Wilson sampling band and statistics. A new adapter is typically under 50 lines.

numpy
Python notebooks

Emitting from numpy is a dozen lines with no library at all — the format is just JSON. See the integrations guide for the full recipe.