Skip to main content

Add or change a risk matrix

Risk policy in Atlas is data, not code. Adding a dimension, a factor, or a whole matrix is a YAML + reference-data change — no deployment required. Read Risk scoring first.

Matrix schema shape

A matrix schema has dimensions, each with factors; factors use a scoring method and are wired to an ontology field:

schema_id: "my_matrix_v1"
version: 1
name: "My AML Matrix"
dimensions:
jurisdiction_risk:
name: "Jurisdiction risk"
weight: 0.30
factors:
- id: "country_risk"
max_score: 100
scoring_method: "REFERENCE_LOOKUP" # or BOOLEAN, THRESHOLD_RANGES
scoring_config:
reference_dataset: "country_risk_list"
multi_value_strategy: "max"
wire_mapping:
ontology_field_path: "LegalEntity.jurisdiction"
aggregation:
method: "weighted_max" # weighted_average | weighted_max | highest_dimension
dimension_weights: { jurisdiction_risk: 0.30 }
risk_levels:
low: { min: 0, max: 39 }
medium: { min: 40, max: 69 }
high: { min: 70, max: 100 }
escalation_rules:
- id: "sanctioned_hit"
condition: { equals: true }
minimum_tier: "high"
# wired via wire_mappings["escalation.sanctioned_hit"]

Scoring methods

MethodWhat it does
REFERENCE_LOOKUPLooks the entity value up in a frozen reference dataset (e.g. country-risk list, PEP tiers)
BOOLEANMaps true/false/null to configured scores
THRESHOLD_RANGESBuckets a numeric value into score ranges

Aggregation & escalation

  • Aggregation combines dimension scores: weighted_max (the EBA-style default: 0.6×max + 0.4×weighted-avg), weighted_average, or highest_dimension.
  • Escalation rules are a one-way ratchet: if a condition fires and its minimum_tier is higher than the computed score, the final score is raised — never lowered.

Reference datasets

REFERENCE_LOOKUP factors read frozen reference datasets from the reference-data registry. To add one:

  1. Define a type (data_shape: list, scored_table, or config) with column definitions.
  2. Create a dataset version with the data, then activate it.
  3. Reference it from a factor's scoring_config.reference_dataset.

The resolver is tenant-aware: a tenant's own dataset overrides the system default for the same list_key. At publish time, the matrix freezes a snapshot of the exact dataset versions it used, so evaluations stay deterministic even if the lists change later.

Publish, assign, evaluate

  • Draft → published matrices are immutable once published; evaluations cite the version.
  • Determinism & idempotency: the scorer hashes input, overrides, and output; an evaluation with an existing fingerprint returns the cached result instead of re-scoring.
  • Batch evaluation re-scores a whole portfolio sequentially (a Temporal workflow), with a queryable progress state and a per-company failure list.

No code, mostly

Adding a dimension or matrix is purely YAML + reference data + publish — the scorer, mapper, and persistence are generic. You only touch code if you need a new scoring method (add a function to the SCORING_METHODS registry in src/risk_matrix/scorer.py). See Risk scoring and ADR-019.