Cryptolean
// Methodology · resrisk

Resolution risk as a metric module — the locked contract, plus the evidence.

Current definition resrisk-v2. Charts stamped with it were computed by src/resolution/risk_score.py, and every value plotted for a past date could have been computed on that date.

Definition and failure modes

compute(df, **params) -> pd.Series      # 0-1 per market, indexed venue:market_id
evidence(df, **params) -> pd.DataFrame  # one row per raised flag, with its clause

SPEC.md § 7 makes the second function binding, not optional:

Never publish a resolution-risk score without the clause that produced it. An
unexplained score about someone else's contract is an accusation, not analysis.

So the score and its evidence are one module and one version. compute does not invent a second scoring rule — it delegates the arithmetic to flags.py, which owns the five-flag taxonomy and DEFAULT_WEIGHTS. This module adds the part flags.py never had: where in the rules text each flag came from.

The five flags, and what evidence each can produce:

subjective      PRESENT in the text  -> the sentence containing the term
no_named_source ABSENT from the text -> no clause; the absence is the finding
no_edge_cases   ABSENT from the text -> no clause; the absence is the finding
no_timezone     ABSENT from the text -> no clause; the absence is the finding
prior_dispute   from the RECORD      -> the UMA status sequence, not the rules

Three of the five fire on absence. There is no sentence to quote for "this contract never says what happens if the event is postponed" — the honest rendering is the absence itself, stated with the length of text it is absent from, which is why every evidence row carries basis and rules_chars. A UI that only knows how to show quotes will silently drop three flags out of five.

This is a ranking device, not a probability. It has never been calibrated against realised disputes: the observable dispute sample is 758 markets on one venue over 17 months, and fitting weights to it would fit noise. A high score means "read this one first".

Version history

Newest first. Each entry says what changed and whether values that had already been published moved with it, followed by the sentence from the module that decided the verdict.

  1. resrisk-v22026-08-05RestatedCurrent

    follows flags-v2's word-boundary matching. SCORES MOVE, but narrowly: 4.2% of the corpus changes, mean 0.3263 -> 0.3289, rank correlation 0.995. The change is a matching fix — flags-v1's "tie" matched "parties" and credited 2,434 markets with edge-case coverage they never had. Weights unchanged. PHASE4_THRESHOLDS.md records the before/after and which flags survive a volume control. Evidence spans now come from flags.find(), the same matcher that scores, so a quoted clause cannot disagree with the number.

    At least one value that had already been published is different now. Charts drawn before this version do not match charts drawn after it.

    • values movedSCORES MOVE, but narrowly: 4.2% of the corpus changes, mean 0.3263 -> 0.3289, rank correlation 0.995.
    • unchangedWeights unchanged.
  2. resrisk-v12026-08-05Initial

    wraps flags-v1's taxonomy and weights; adds clause extraction, absence basis, and the record basis for dispute history. Score values identical to flags-v1 — this version adds evidence, it does not re-tune.

    The first version of this metric. There is no earlier definition to restate.

Charts drawn with it

3 charts name this metric in their readout line.

Current version
resrisk-v2
Versions on record
2
First dated
2026-08-05
Restatement policy
Restated
Has restated. At least one bump changed values that were already published; the history below says which.
Charts
3
Source
src/resolution/risk_score.py
Public functions
components, compute, evidence, explain, key
Machine-readable
catalog.json · llms.txt