Skip to content
Straits

← Methodology

Hormuz Index changelog.

Every methodology change is logged here with the reasoning. Live-published values (the number that was on the page at the time) are preserved alongside retro-computed values (what the current methodology would have produced for the same inputs). Both are available at the audit endpoint.

Current version · v0.3.3

  1. v0.3.3

    31 May 2026

    patch release

    Renamed the Escalation Probability index to Escalation Forecast. Display-only; no input, weight, or math change.

    • Every reader-facing surface that displayed the index by name now reads "Escalation Forecast": the homepage hero, the standalone Hormuz Index block, the OG image, the /embed/index widget, the public disclaimer string (lib/methodology.ts INDEX_DISCLAIMER), the /api page JSON-LD PropertyValue, the dataHealth provenance label, and the dailyBrief prompt. Internal identifiers are untouched — the Firestore collection (escalationProbabilityIndex/{ts} + /latest), the API component object (escalationProbability), ESCALATION_PROBABILITY_KEYS/WEIGHTS/META, and the API schema id all keep their names, so no integrator or stored series breaks.
    • No change to inputs, weights (Polymarket 0.47 / Brent–WTI spread 0.24 / Manifold 0.29), normalization, decay, rails, or the low-confidence liquidity floor. Published values are identical to what v0.3.2 would have produced.

    ReasonThe composite blends prediction-market odds with a Brent–WTI price spread and play-money Manifold contracts. "Probability" invited readers — especially journalists quoting the number — to read "Escalation Probability 58" as "markets price a 58% chance of escalation," which the inputs do not support: roughly a quarter of the number is a price-spread mapping with no probabilistic meaning and nearly a third is fake-money betting. "Forecast" keeps the forward-looking claim the inputs do support while dropping the false precision. Renaming rather than re-architecting preserves the time series.

  2. v0.3.2

    27 May 2026

    patch release

    Kalshi dropped from the Escalation Probability composite; weights redistributed pro-rata across the surviving three components.

    • A full audit on 2026-05-27 paginated all 20,000 currently-open Kalshi markets via /trade-api/v2/markets and found zero actively-traded Iran/Hormuz forecast contracts. The Mideast-adjacent listings that do exist (KXABRAHAMSY, KXABRAHAMSA, KXABRAHAMQ for Israel-Syria/Saudi/Qatar normalization; KXNEXTISRAELPM for Israel next PM) all carry volume:null, open_interest:null, no last_price, no bid/ask — structurally listed in the catalogue but unused by traders.
    • Escalation Probability weights restructured: Polymarket 0.40 → 0.47, Brent term structure 0.20 → 0.24, Manifold 0.25 → 0.29 (pro-rata redistribution of Kalshi's 0.15 across the surviving three components, preserving the v0.3.0 design intent). Sum still 1.0.
    • Removed: functions/src/inputs/kalshi.ts; readKalshiForwardContracts import in computeHormuzIndex.ts; the kalshi entry from ESCALATION_PROBABILITY_WEIGHTS in both methodologyConfig.ts (functions) and methodology.ts (lib); the kalshiForwardContracts key from ESCALATION_PROBABILITY_META; the Kalshi totalVolumeUsd contribution to the combined-liquidity floor (now Polymarket + Manifold only).
    • fetchMarkets.ts still pulls Kalshi opportunistically into predictionMarkets/ — if Kalshi ever lists Iran/Hormuz markets with real volume, they'll surface in /api/v1/markets and on the homepage prediction-markets panel. They simply no longer feed the Escalation Probability composite.
    • The v0.2.1 "weight reactivates automatically when Kalshi volume returns" mechanism is removed. v0.2.1 had this on the theory the catalogue would refill; six weeks later it has not, and the redistribution math was load-bearing for nothing.
    • No changes to Crisis Pressure Index. API schema unchanged at hormuz-index-v0.2; the escalationProbability.components object simply no longer carries a kalshiForwardContracts key.

    ReasonThe v0.2.1 promise — keep Kalshi present in the methodology with the assumption that markets would eventually be listed — has not held over six weeks. Every published Escalation Probability value since v0.2.1 has had kalshiForwardContracts at health:missing with weight:0, the redistribution math silently doing the work. Dropping Kalshi formally aligns what the methodology page claims with what the function actually computes. Time series from v0.3.1 forward are unaffected; the redistribution math was already producing the v0.3.2 weights via the missing-input pathway.

  3. v0.3.1

    27 May 2026

    patch release

    Brent term-structure input substituted with the Brent–WTI front-month spread; v0.3.0 source path returned no data.

    • v0.3.0 spec called for a Brent forward-curve slope from Stooq numbered contracts (cb1.f, cb2.f, cb3.f). Empirical check on deploy day: Stooq returns N/D for every numbered Brent contract — only the continuous front-month (cb.f) carries data. The input adapter was returning missingReading on every cycle and the 0.20 weight was redistributing to the three prediction-market venues, defeating the v0.3 thesis.
    • Substituted: Brent–WTI front-month spread = cb.f close − cl.f close. Both symbols are already in use by fetchOilPrices, both are quoted continuously by deeply liquid markets. The spread is the price gap between waterborne Mideast crude (Brent) and US/Cushing crude (WTI) — a widening Brent premium is real money pricing Brent-specific access risk over US supply, which is a Hormuz signal by construction.
    • New anchor calibration: spread $0 → score 0, $2 → 15, $4 → 35, $7 → 70, $10 → 90, $15+ → 100. Linear interpolation. Calibrated empirically against the 2011 Arab Spring / Libya disruption (sustained $15+), the 2022 Russia-Ukraine acute phase ($5–10), and normal pre-crisis bands ($2–4). Negative spreads (WTI premium) clamp to 0 — those reflect Cushing logistics, not Hormuz.
    • Doc shape changes (Firestore brentTermStructure/latest): brentClose + wtiClose + brentPremium replace the prior frontMonth + threeMonth + slopePct fields. The component key in the API stays at brentTermStructureSlope for backward compatibility with v0.3.0 integrators; the methodology page renames the displayed label to "Brent–WTI spread."
    • Weights and the rest of the index unchanged. No changes to Crisis Pressure. No changes to API schema (still hormuz-index-v0.2). The data semantics of the Brent component changed; the structure did not.

    Reasonv0.3.0 was the right idea but built on a free-data assumption that did not hold. The intent — give Escalation Probability a non-market, deeply liquid forward signal independent of the prediction-market crowd — is preserved. The Brent–WTI spread is arguably a tighter Hormuz-specific signal than the absolute Brent curve would have been: it isolates the regional premium directly rather than inferring it from term-structure shape. v0.3.0 ran for less than two hours in production; no historical values were published with the broken input contributing signal (every v0.3.0 cycle had brentTermStructureSlope at health:missing, so the weight redistributed to peers).

  4. v0.3.0

    26 May 2026

    major release

    Brent forward-curve slope added as a fourth Escalation Probability input — the first non-market forward signal in the composite.

    • New input: Brent forward-curve slope, weight 0.20. Computed as (front-month close − ~3-month close) / front-month × 100 from Stooq numbered Brent contracts (cb.f vs cb3.f). Positive slope (backwardation) maps to a high score; flat curves score near 30; deep contango scores near zero. Anchors at slope = -3% → 0, 0% → 30, +3% → 60, +6% → 85, +10% → 100, linearly interpolated.
    • Escalation Probability weights restructured: Polymarket 0.50 → 0.40, Manifold 0.30 → 0.25, Kalshi 0.20 → 0.15, new Brent term-structure 0.20. Sum still 1.0. Relative ranking among prediction-market venues is preserved.
    • New Cloud Function: fetchBrentTermStructure (every 30 min). Writes brentTermStructure/latest with frontMonth, threeMonth, slopePct, source, sourceName, sourceUrl, updatedAt, lastAttemptAt, lastAttemptOk. Failure-path stamps lastAttemptOk:false without touching the prior reading, mirroring the silent-fail mitigation introduced for oil prices in the same window.
    • New input reader: functions/src/inputs/brentTermStructure.ts. Returns missingReading when the doc is absent or the slopePct is non-finite; returns a staleReading when lastAttemptOk is false (prior slope kept, health flagged degraded). Weight redistributes pro-rata if the input is missing — Polymarket / Manifold / Kalshi absorb the 0.20 in proportion to their existing weights.
    • The low-confidence volume floor (combined prediction-market 7-day volume below $15k) is unchanged in logic but now applies only to the three prediction-market venues. Brent futures volume is enormous and not comparable to prediction-market liquidity; the term-structure component is excluded from the floor accordingly.
    • No changes to Crisis Pressure Index. Bands, decay, rails unchanged. API schema unchanged at hormuz-index-v0.2 except that escalationProbability.components now carries a fourth entry, brentTermStructureSlope, with totalVolumeUsd:null (Brent futures volume is not meaningfully tracked at this layer).

    ReasonA reviewer reading the v0.2.2 Escalation Probability Index could fairly observe that all three inputs are prediction-market venues sampling broadly the same population — a poll, not a forecast in the sense an oil-market trader would recognize. The Brent forward curve is the deepest, most liquid forward signal in oil markets: when backwardation steepens, money is pricing near-term scarcity, independent of what Polymarket traders think. Adding it as a 20% weight gives the composite an independent forecast pillar without overwhelming the prediction-market signal it was originally built on. In calm regimes the term-structure input scores near zero (modest backwardation is normal for Brent and our anchors reflect that); during a developing crisis it should rise alongside the prediction-market venues and provide confirmatory or divergent evidence. Time series before 0.3.0 should not be compared on a like-for-like basis with values from 0.3.0 onward; v0.2.x docs are not retro-computed.

  5. v0.2.2

    26 May 2026

    minor release

    Escalation Probability now distinguishes YES=bad-outcome contracts from YES=de-escalation contracts before aggregation.

    • New per-contract orientation tagger (functions/src/inputs/orientation.ts). Each matched Polymarket / Manifold / Kalshi market is classified yes-bad or yes-good using regex heuristics on the title; yes-good markets have their YES probability inverted before entering the dollar-weighted average so the signal flows toward the forecast target (bad outcome within 30 days).
    • Audit on 2026-05-26 found that the largest-volume Manifold and Polymarket contracts in our catalogue frame YES as de-escalation: "Strait of Hormuz traffic returns to normal by end of May" ($27M, p=0.02), "US x Iran permanent peace deal by May 31" ($54M, p=0.255), "US-Iran ceasefire holds through June". Without inversion, those contracts dragged the published escalation reading sharply down — a low YES probability on "returns to normal" reads as the situation being bad, but pre-v0.2.2 the aggregation interpreted it as the situation being calm.
    • Manifold input adapter (functions/src/inputs/manifold.ts) widens its keyword set to capture peace / ceasefire / invade / uranium / nuclear / sanctions / lifted / reopen / resume framings that Manifold uses heavily. The orientation tagger handles the YES=good ones; the rest contribute as direct readings.
    • No changes to Crisis Pressure Index inputs or weights. The Escalation Probability weights stay at Polymarket 0.5 / Manifold 0.3 / Kalshi 0.2; only the aggregation step inside each input changed.

    ReasonThe published Escalation Probability reading on 2026-05-26 was 37 with confidence 2 — Manifold was contributing nothing (its title-keyword filter missed the bulk of relevant contracts) and Polymarket alone was being pulled DOWN by de-escalation-framed contracts that an honest aggregator should invert. The forecast index is supposed to read "what markets price for the bad outcome." A high-volume contract that markets price at 0.02 for "Hormuz traffic returns to normal" is markets saying the bad outcome is overwhelmingly likely; the v0.2.2 aggregation makes that visible in the headline number. Time series before 0.2.2 should not be compared on a like-for-like basis with values from 0.2.2 onward; the v0.1/v0.2 currentValue fields are NOT retro-computed because the orientation classification was never recorded on historical input docs.

  6. v0.2.1

    26 May 2026

    minor release

    Added Manifold Markets as a third Escalation Probability venue; reduced Kalshi weight to reflect its empty open catalogue.

    • New venue: Manifold Markets (api.manifold.markets). Pulled via the same fetchMarkets ingestion path as Polymarket and Kalshi, deduped across seed terms (hormuz, iran, israel, oil price, tanker, middle east), filtered through the same relevance keyword + exclude lists, written to predictionMarkets with venue: "manifold".
    • Manifold volume is denominated in mana and converted to USD-equivalent at the conservative 100 mana ≈ $1 USD rate Manifold itself uses for charity redemption and subsidy budgets. The methodology page calls this out explicitly so readers can discount accordingly; the combined Polymarket + Manifold + Kalshi liquidity floor uses the converted figure.
    • Escalation Probability weights restructured: Polymarket 0.6 → 0.5; Kalshi 0.4 → 0.2; new Manifold weight 0.3. Sum still 1.0. Kalshi weight halved because an empirical audit of its open catalogue on 2026-05-26 surfaced no matching forward contracts (the KXUSAIRANAGREEMENT, KXNEXTIRANLEADER, KXIRANVISITUSA series exist but list no open markets); the new weight assignment reflects which venue is actually carrying signal.
    • Relevance keyword list in fetchMarkets.ts widened from 16 strict phrases to a broader Iran/Israel/oil/conflict surface, paired with a new EXCLUDE_KEYWORDS list that filters substring collisions from sports and entertainment markets (player names containing "iran", awards containing "war", etc.). Top-N retained per cycle raised from 20 to 30 to accommodate the three-venue catalogue.
    • No changes to Crisis Pressure Index inputs or weights. Bands, decay, and rails unchanged. API schema unchanged at hormuz-index-v0.2 — only the per-component breakdown in the escalationProbability.components object now carries a manifoldForwardContracts entry alongside polymarketAggregate and kalshiForwardContracts.

    ReasonLive audit of the Escalation Probability Index on 2026-05-26 returned confidence=2 (effectively meaningless) because Kalshi was flagged missing — meaning the 0.4 Kalshi weight redistributed pro-rata to Polymarket, leaving Polymarket as the only signal. Investigation showed Kalshi's relevant event tickers (US-Iran agreement, next Iran leader, Iran-visits-USA) carry zero open markets at the moment; the catalogue exists structurally but the contracts have not been listed. Manifold, by contrast, was running 20+ active Hormuz-specific binary markets with real trading interest. Folding Manifold in restores the cross-venue diversification the methodology requires while keeping Kalshi available for automatic reactivation when its catalogue refills.

  7. v0.2.0

    21 May 2026

    major release

    Split the index into two — Crisis Pressure (state) and Escalation Probability (30-day forecast).

    • The single 0–100 Hormuz Index becomes two parallel indices, each backed only by inputs that match its claim. Both ship in lockstep and share the same bands, decay, and rails.
    • Crisis Pressure Index (state) carries the four current-state inputs: AIS transit deviation (30%), war-risk insurance multiple (25%), GDELT event pressure (25%), Brent options dread / OVX (20%). Override rule (max × 0.9 when any score ≥ 75) is carried over — the physical-strait override is load-bearing for crisis severity.
    • Escalation Probability Index (30-day forecast) launches with two inputs: Polymarket aggregate (60%) and Kalshi forward contracts (40%). Dollar-weighted aggregation by 7-day volume. No override rule — a forecast should be a smooth probabilistic number, not a threshold flipper.
    • Polymarket binary liquidity gate ($25k floor, 5% gated weight) replaced by a continuous low-confidence reporting floor at $15k combined Polymarket + Kalshi 7-day volume. Under the floor the Escalation Probability Index reports indexHealth: "low-confidence" and the hero shows a muted treatment; weights are unchanged.
    • New Firestore collections: crisisPressureIndex/{ts} + /latest and escalationProbabilityIndex/{ts} + /latest. The legacy hormuzIndex/ collection is frozen — no further writes go there from v0.2 onward; reads stay open so prior published values remain citeable.
    • API schema bumped to hormuz-index-v0.2. Top-level shape: { indices: { crisisPressure: {...}, escalationProbability: {...} } }. CORS unchanged.
    • OG image, embed widget, and homepage hero restructured to a dual-number layout (side-by-side on desktop, stacked on mobile). Daily brief weaves both numbers into prose when either is in high or extreme.
    • currentValue on existing v0.1.x historical docs is NOT recomputed in this bump. The v0.2 structure is incompatible with the v0.1.x single-value shape, and silently rewriting historical currentValue to the new Crisis Pressure value would change what the field means for those docs. v0.1.x docs are frozen entirely; the v0.1.2 methodology page is archived at /methodology/v0.1 for historical reference.

    Reasonv0.1.2 was an honest reframing of the band language but left the structural problem unresolved: the headline was a state composite marketed as a forecast. Four of the five v0.1 inputs measured what just happened; only Polymarket was genuinely forward-looking. With the headline at 90 and Polymarket reading ~18%, the gap was load-bearing. Splitting the brand into two parallel indices lets each carry only the claims its inputs support: Crisis Pressure for what is happening, Escalation Probability for what markets price in the next 30 days. The two-number presentation also makes the state-vs-forecast divergence visible directly, which is itself editorially useful — readers can see when markets disagree with the present.

  8. v0.1.2

    20 May 2026

    patch release

    Honest reframing — index describes measured state, not forecast.

    • Band framings updated to describe the current measured state rather than claim forecasting power. The previous "all signals point to imminent escalation" framing for the extreme band conflated current crisis severity with forward probability.
    • Methodology page intro rewritten to position the index as a composite of current crisis pressure across measured signals, not "the probability of severe escalation in the next 30 days." Added a "What the index is not" section calling out that four of the five inputs measure current state; only Polymarket is genuinely forward-looking.
    • No weight, threshold, decay, rail, or output changes — the index value at any given moment is exactly what v0.1.1 would have produced. Only rendered framing changed.

    ReasonA reader pointed out that "all signals point to imminent escalation" claims more than the inputs actually support. The current AIS, insurance, and event-pressure components measure existing crisis severity; the Polymarket component (the one true forecast input) reads only 18% probability of closure even as the headline sits at 90. Honest disclosure is methodology's most-important property; this corrects the overclaim. A v0.2 will likely restructure the inputs to genuinely forecast (e.g., heavier Polymarket weighting, term-structure inputs, separating current-state and forward-probability into two distinct numbers).

  9. v0.1.1

    20 May 2026

    patch release

    CBOE OVX integration lights up the Brent options vol input.

    • New ingestion Function fetchVolatilityIndex pulls CBOE OVX every 15 minutes. Primary source: FRED daily-close series OVXCLS (St. Louis Fed). Fallbacks: Stooq, Yahoo Finance.
    • Writes volatilityIndex/latest with { ovx, skew, source, sourceUrl, updatedAt }; brentOptionsDread adapter now returns fresh data instead of "missing".
    • No weight or threshold changes — the 25% target weight that was previously redistributed pro-rata is now actually applied.
    • Methodology page updated to reflect the new upstream and remove the "pending integration" disclosure.

    ReasonOVX is the input most likely to give the index intraday motion during sustained-closure periods (when AIS/insurance read steady). With v0.1.0 publishing the headline as 90 every 5 minutes because the override fires on AIS, the page felt static. OVX moves continuously during US/EU trading hours and restores the breathing the chart needs.

  10. v0.1.0

    19 May 2026

    major release

    Initial public release.

    • Five-component composite: Polymarket+Kalshi (25%), Brent options vol (25%), GDELT event pressure (20%), AIS transit deviation (15%), war-risk insurance multiple (15%).
    • Weighted-average composition with single-component override above score 75.
    • Polymarket liquidity gate at $25k 7d volume; gated weight 5%.
    • Asymmetric decay: instant rises, 36h half-life falls.
    • GDELT event decay 72h half-life.
    • 24h rails: +25 ceiling / -10 floor; ceiling overridable on flagged crisis events.
    • Dual-value Firestore structure: liveValue immutable, currentValue retro-computable on methodology bumps.
    • Brent options vol input ships in stub state (returns missing); upstream CBOE OVX integration is pending and weight is redistributed pro-rata in the interim.

    ReasonFirst publishable version. Calibration expected to evolve across the next 4–8 weeks as we observe how the index reads across more market and event regimes.

← Back to methodology