Skip to main content
Pegana turns a continuous spread signal into discrete states because alerts need to be sticky. You can’t act on a continuous number that updates 100 times a minute. You need a state transition that fires once, holds while the underlying condition persists, and clears once when it actually resolves.

The five states

StateMeaningAlert?
PEGGEDSpread inside the calm band for this assetNo
DRIFTSpread crossed the per-asset drift threshold; subscribers notifiedYes
DEPEGSpread crossed depeg threshold; urgent framingYes
CRITICALSpread crossed critical threshold; system tags the asset as actively breakingYes
UNKNOWNSource stale, low-confidence, or decoder mismatch; stickyNo (no alert; consumer should not act)
Plus a terminal state — BLACK_SWAN — for spreads beyond any historically-observed level. Never auto-exits.

What each state implies for a consumer

  • PEGGED — the asset is doing what it promises. Lending protocols can price collateral at par. Insurance has nothing to fire on. Agents can swap freely.
  • DRIFT — early warning. The spread crossed the threshold for “this is no longer normal noise.” Subscribers get a notification. Most DRIFTs resolve back to PEGGED without ever reaching DEPEG. Lending protocols might tighten LTV by a few points; insurance preps payout logic; agents pause discretionary swaps.
  • DEPEG — the spread crossed the threshold for “this is materially broken right now.” Liquidation engines should already have pulled back. Insurance is firing. Agents should hard-pause any action that depends on this asset’s peg.
  • CRITICAL — the spread is large enough that recovery is not assumed. Treat the asset as a different (riskier) asset. Wind down exposure.
  • UNKNOWN — we don’t know. Do not act on stale information. The asset is not necessarily broken; we just can’t tell.

The transitions

   ┌───────────┐
   │  PEGGED   │←──┐
   └────┬──────┘   │
        │ 30s @    │ 60s @
        │ ≥ drift  │ < drift-exit
        ▼          │
   ┌───────────┐   │
   │  DRIFT    │───┘
   └────┬──────┘
        │ 30s @
        │ ≥ depeg

   ┌───────────┐
   │  DEPEG    │
   └────┬──────┘
        │ 30s @
        │ ≥ critical

   ┌───────────┐
   │  CRITICAL │
   └───────────┘

   (UNKNOWN is orthogonal — any state can flip to UNKNOWN
    if source goes stale, and must dwell 60s after recovery
    before re-entering the live ladder)
Each transition is dwell-gated: the smoothed spread must hold the crossed threshold for the specified time. This filters out single-tick spikes. Entry dwell is 30s; exit dwell is 60s — see hysteresis FSM for why.

What gets emitted

Every transition produces:
{
  "alert_id": "9c8e7f3a-...",
  "asset": "USDC",
  "from_state": "PEGGED",
  "to_state": "DRIFT",
  "detected_at": "2026-05-26T14:32:11.482Z",
  "spread_at_trigger": -0.0034,
  "intrinsic_usd": 1.0000,
  "market_usd": 0.9966
}
This payload is what /v1/alerts returns, what /v1/me/webhooks POSTs, and what the Telegram bot formats into a human-readable message.

What does NOT get emitted

  • Sub-state noise. A spread oscillating between 25 and 32 bps with threshold at 30 bps stays in DRIFT — no alert flood.
  • Recovery within the entry dwell window. If the spread crosses 30 bps for 5 seconds and falls back, no transition fires.
  • Counts of “ticks since last alert” or similar accumulator state. Each transition is independent; we don’t publish “USDC has spent 47 minutes in DRIFT today.”
For accumulator metrics, use /v1/me/alerts (per-user delivery history) or /v1/alerts (global feed).

Next

Confidence score

When the signal is sketchy — depth, staleness, decoder drift.

Hysteresis explained

Why entry and exit thresholds differ.