spread = 0→ asset trades at intrinsicspread > 0→ market below intrinsic (under-priced, common stress signal)spread < 0→ market above intrinsic (over-priced, less common)
EWMA smoothing
Raw spread ticks are noisy. We smooth with an exponentially-weighted moving average:α = 0.3 default. That is:
- New tick contributes 30% to the published spread
- Prior smoothed value carries 70%
α (say 0.6) reacts faster but is noisier. A lower α (0.1) is laggy and
misses real depegs. 0.3 is calibrated against 24h p99 noise per asset class — tight
enough to catch a real depeg inside ~15s, loose enough that a single bad Jupiter
quote doesn’t trip the FSM.
Per-asset thresholds
A single fixed threshold across all 22 active assets would produce false positives on noisy LSTs (INF: 24h p99 ~1.12%) and false negatives on tight stables (USDC: 24h p99 ~10 bps). We calibrate per-asset.| Asset class | Drift entry | Depeg entry | Critical entry |
|---|---|---|---|
| Fiat stable | 0.15% | 0.50% | 2.00% |
| SOL-pegged LST | 0.30% | 2.00% | 5.00% |
| Yield-bearing | 1.00% – 2.50% | 2.50% – 4.00% | 5.00% |
| CDP (Hylo hyUSD) | CR < 130% | CR < 115% | CR < 105% |
| Synthetic (xSOL) | leverage-band | wider | terminal |
assets.toml. To inspect:
The 5-state FSM
Asymmetric hysteresis
Entry and exit thresholds are deliberately different, like a thermostat:| Transition | Threshold | Dwell |
|---|---|---|
PEGGED → DRIFT | ≥ drift_entry | 30s |
DRIFT → PEGGED | ≤ drift_exit (≈ 67% of drift_entry) | 60s |
DRIFT → DEPEG | ≥ depeg_entry | 30s |
DEPEG → DRIFT | ≤ depeg_exit | 60s |
DEPEG → CRITICAL | ≥ critical_entry | 30s |
CRITICAL → DEPEG | ≤ critical_exit | 60s |
PEGGED is something they want to trust —
a single tick at 29 bps after a 200 bps spike is not the same as a sustained recovery.
Doubling the exit dwell is a small cost (one extra minute of “alert” state) and a big
honesty win.
See hysteresis-fsm for the deeper read.
What the FSM guarantees
- A transition fires once per real state change. A signal that oscillates inside a threshold band stays in the stressed state until it genuinely recovers.
- Every transition is timestamped server-side with the spread that triggered it.
BLACK_SWAN(spread beyond historical p99.9) never auto-exits — it requires a manual/v1/me/alerts/:id/ackfrom the operator.
What the FSM cannot fix
- A stale input. If Sanctum stops publishing, the smoothed spread will lag — the FSM
has no way to detect that. We mitigate via a staleness gate (30s) at the source
layer: any quote older than 30s flips the asset to
UNKNOWN. - A wrong threshold. We calibrated against 24h p99 over the soak period. If an asset’s
noise profile changes (new venue, new MEV regime), the threshold may need
re-calibration.
CALIBRATION-v1.mddocuments the procedure.
Next
Honesty about limits
What we don’t model. Where the signal can lie. When to mistrust an alert.