git:20260923.9f2c117 to git:20260923.1182a9c

1 added, 1 removed. Audit A to A.

---
name: gdex-hl-anomaly
description: Scored, time-stamped anomaly events for HyperLiquid perps (oracle divergence, funding extremity, liquidity shock) against per-market learned baselines, with coverage records
---
# GDEX: HyperLiquid Anomaly Events
Detects unusual behaviour on the HyperLiquid perpetual markets that GDEX trades, and emits it as
**events** (NDJSON, one record per event), not alerts. Each event says what was unusual, when it
happened, how unusual it was against that market's own recent history, and where to re-derive it.
Standard library only — no API key, no Gemach infrastructure. Reads the public HyperLiquid
`info` endpoint directly.
## When to Use
- Building a risk feed that needs market anomalies with a timestamp and a score
- Screening HyperLiquid markets for manipulation, oracle stress or liquidity shocks
- Backfilling anomaly history for a window (1h bars reach ~7 months back, 4h ~2 years)
## Run
```bash
python3 scripts/hl_anomaly.py # last 24h, every active core market
python3 scripts/hl_anomaly.py --coins BTC ETH SOL --hours 72
python3 scripts/hl_anomaly.py --start 2025-03-20 --end 2025-03-27 --coins JELLY --interval 1h
```
Output is NDJSON: zero or more `signal_type: "anomaly"` records, then exactly **one**
`signal_type: "anomaly_coverage"` record.
## Categories
| `anomaly_category` | Fires when | Source |
|---|---|---|
| `oracle_divergence` | hourly mark-vs-oracle premium is far from the market's baseline | `fundingHistory` |
| `funding_extremity` | 8h mean funding is far from baseline **and** premium is outside HyperLiquid's clamp band (inside it funding is pinned to the interest rate and carries no information). Always carries the premium fields. | `fundingHistory` |
| `liquidity_shock` | bar volume or bar range spikes far above baseline (spikes only) | `candleSnapshot` |
`large_outflow`, `governance_concentration` and `security_flag_change` are part of the contract
enum but are not produced by this skill (they need on-chain or token-security sources).
## Event record
| Field | Meaning |
|---|---|
| `entity_id` | `hl-<coin>`, same key as the `hl_markets` feed |
| `detected_at` | when the anomaly **happened** (funding hour, or bar close) — not when the job ran |
| `z`, `z_threshold` | robust z against the learned baseline, and the threshold it crossed |
| `score` | 0 at the threshold, rising monotonically toward 1. A ranking, not a probability |
| `model_version` | changes whenever thresholds or features change |
| `evidence_ref` | public endpoint + coin + time + sha256 of the exact baseline used |
| feature fields | premium/funding and their baselines, or volume/range and their baselines |
## Coverage record — read this before trusting an empty result
- Every run states `window_start`, `window_end`, `markets_scored` and `markets_not_scored`
+ Every run states `detector_window_start`, `detector_window_end`, `markets_scored` and `markets_not_scored`
(too little history, delisted, or no data). **No event for a scored market means nothing
crossed a threshold in that window; it does not mean the market was normal.** Markets in
`markets_not_scored` were not evaluated at all.
## Method and evidence
- `APPROACH.md` — the model, why each choice was made, and its known limits
- `backtest/RESULTS.md` — hit rate and false-alarm rate on three real events
- `backtest/calibrate.py`, `backtest/backtest.py` — reproduce both
- `sample/anomaly_sample.ndjson` — records for contract tests