diff --git a/benchmarks/perp-funding-stability.yml b/benchmarks/perp-funding-stability.yml
index 709b7c00..ee15d5fb 100644
--- a/benchmarks/perp-funding-stability.yml
+++ b/benchmarks/perp-funding-stability.yml
@@ -3,8 +3,8 @@
slug: perp-funding-stability
number: "043"
title: Perp DEX funding stability, 24h stddev of ETH funding ranked
-seo_title: "Perp funding stability 2026: ETH funding stddev across 7 venues ranked"
-seo_description: "Live 24h standard deviation of ETH perpetual futures funding rate in bps across Hyperliquid, Bybit, dYdX v4, Binance, OKX, Paradex and Aster. Lower means more stable funding for carry traders and basis arbitrageurs."
+seo_title: "Perp funding stability 2026: ETH funding stddev across 15 venues ranked"
+seo_description: "Live 24h standard deviation of ETH perpetual futures funding rate in bps across 15 major venues: Hyperliquid, Bybit, dYdX v4, Binance, OKX, Paradex, Aster, Bitget, Coinbase, Deribit, Gate, Kraken, KuCoin, Lighter, MEXC. Lower means more stable funding for carry traders and basis arbitrageurs."
subtitle: 24h standard deviation of ETH funding rate, in basis points per 24h, across the perp-funding cohort. Lower means funding stays in a tight band, the carry trader's preferred signal.
category: Trading
status: live
@@ -24,10 +24,11 @@ seo_intro: |
same number. The bench reads the same normalized series as
perp-funding (per-venue hold cost in bps per 24h) and exposes
stddev_over_time of that series on a 24 hour window for ETH.
- Cohort is the 7 venues currently publishing the normalized
- hold-24h gauge with the freshness signal: Hyperliquid (onchain),
- Bybit, dYdX v4 (Cosmos appchain), Binance, OKX, Paradex (Starknet
- L2), Aster (BNB Chain). Lower is better.
+ Cohort is 15 venues across two sources: 7 polled directly by the
+ harness (Hyperliquid onchain, Bybit, dYdX v4 Cosmos appchain,
+ Binance, OKX, Paradex Starknet L2, Aster BNB Chain) and 8 sourced
+ through Mobula's CEFI funding aggregator (Bitget, Coinbase,
+ Deribit, Gate, Kraken, KuCoin, Lighter, MEXC). Lower is better.
abstract: |
The bench reuses the normalized 24h ETH funding series from
@@ -43,7 +44,7 @@ methodology:
- "Source. Same upstream as perp-funding: each venue's public funding endpoint polled every 60 seconds, normalized to bps per hour and per 24h hold, sign preserved."
- "Metric. stddev_over_time(perp_funding_hold_24h_bps{asset=\"ETH\"}[24h]) per venue. The 7d window smooths intraday noise but reacts to regime shifts within a week."
- "Sign handling. The underlying series is signed (positive means longs pay). Stability measures the swing, so the ranking uses the unsigned stddev. Average direction and level are the perp-funding bench."
- - "Cohort. 7 venues from the perp-funding bench publishing the normalized hold-24h gauge with the freshness signal: Hyperliquid (onchain), Bybit, dYdX v4 (Cosmos appchain), Binance, OKX, Paradex (Starknet L2), Aster (BNB Chain)."
+ - "Cohort. 15 venues across two sources. 7 polled directly (perp_funding_hold_24h_bps): Hyperliquid, Bybit, dYdX v4, Binance, OKX, Paradex, Aster. 8 via Mobula CEFI aggregator (perp_venue_funding_24h_bps): Bitget, Coinbase, Deribit, Gate, Kraken, KuCoin, Lighter, MEXC. Both normalize to bps per 24h hold, sign preserved, so the unsigned stddev compares cleanly across the full cohort."
- "Success. Same freshness signal as perp-funding: perp_funding_venue_ok_unix advancing within the last 5 minutes. A venue whose scrape stalls is tagged stale on the row."
- "Cadence. The upstream funding harness polls every 60 seconds; Prometheus scrapes every 30 seconds. The 7 day stddev refreshes on every scrape."
- "Failures. A venue whose upstream funding feed errors keeps its last gauge value; the leaderboard tags the row stale once the success gauge drops to 0."
@@ -166,3 +167,112 @@ providers:
success: (perp_funding_venue_ok_unix{venue="aster"} > bool (time() - 300))
sample_size: count_over_time(perp_funding_hold_24h_bps{venue="aster",asset="ETH"}[24h])
series: stddev_over_time(perp_funding_hold_24h_bps{venue="aster",asset="ETH"}[24h])
+
+ # ── Mobula-sourced cohort (perp_venue_funding_24h_bps from perp-cohort-stats) ──
+ # Same metric semantics as perp_funding_hold_24h_bps but normalized
+ # via Mobula's CEFI funding-rate aggregator instead of direct venue
+ # polls. Freshness gauge is perp_venue_last_refresh_unix.
+
+ - slug: bitget
+ name: Bitget
+ tag: CEX, USDT perpetuals via Mobula aggregator, 8h funding
+ formula: "stddev_over_time of perp_venue_funding_24h_bps{venue=\"bitget\",asset=\"ETH\"} over a 24h window. Source: Mobula CEFI funding-rate aggregator."
+ queries:
+ p50: stddev_over_time(perp_venue_funding_24h_bps{venue="bitget",asset="ETH"}[24h])
+ p90: stddev_over_time(perp_venue_funding_24h_bps{venue="bitget",asset="BTC"}[24h])
+ p99: stddev_over_time(perp_venue_funding_24h_bps{venue="bitget",asset="SOL"}[24h])
+ mean: stddev_over_time(perp_venue_funding_24h_bps{venue="bitget",asset="ETH"}[24h])
+ success: (perp_venue_last_refresh_unix{venue="bitget"} > bool (time() - 300))
+ sample_size: count_over_time(perp_venue_funding_24h_bps{venue="bitget",asset="ETH"}[24h])
+ series: stddev_over_time(perp_venue_funding_24h_bps{venue="bitget",asset="ETH"}[24h])
+
+ - slug: coinbase
+ name: Coinbase
+ tag: Regulated US CEX, perpetuals via Mobula aggregator
+ formula: "stddev_over_time of perp_venue_funding_24h_bps{venue=\"coinbase\",asset=\"ETH\"} over a 24h window. Source: Mobula CEFI funding-rate aggregator."
+ queries:
+ p50: stddev_over_time(perp_venue_funding_24h_bps{venue="coinbase",asset="ETH"}[24h])
+ p90: stddev_over_time(perp_venue_funding_24h_bps{venue="coinbase",asset="BTC"}[24h])
+ p99: stddev_over_time(perp_venue_funding_24h_bps{venue="coinbase",asset="SOL"}[24h])
+ mean: stddev_over_time(perp_venue_funding_24h_bps{venue="coinbase",asset="ETH"}[24h])
+ success: (perp_venue_last_refresh_unix{venue="coinbase"} > bool (time() - 300))
+ sample_size: count_over_time(perp_venue_funding_24h_bps{venue="coinbase",asset="ETH"}[24h])
+ series: stddev_over_time(perp_venue_funding_24h_bps{venue="coinbase",asset="ETH"}[24h])
+
+ - slug: deribit
+ name: Deribit
+ tag: Options-focused CEX, ETH/BTC perpetuals via Mobula aggregator
+ formula: "stddev_over_time of perp_venue_funding_24h_bps{venue=\"deribit\",asset=\"ETH\"} over a 24h window. Source: Mobula CEFI funding-rate aggregator."
+ queries:
+ p50: stddev_over_time(perp_venue_funding_24h_bps{venue="deribit",asset="ETH"}[24h])
+ p90: stddev_over_time(perp_venue_funding_24h_bps{venue="deribit",asset="BTC"}[24h])
+ p99: stddev_over_time(perp_venue_funding_24h_bps{venue="deribit",asset="SOL"}[24h])
+ mean: stddev_over_time(perp_venue_funding_24h_bps{venue="deribit",asset="ETH"}[24h])
+ success: (perp_venue_last_refresh_unix{venue="deribit"} > bool (time() - 300))
+ sample_size: count_over_time(perp_venue_funding_24h_bps{venue="deribit",asset="ETH"}[24h])
+ series: stddev_over_time(perp_venue_funding_24h_bps{venue="deribit",asset="ETH"}[24h])
+
+ - slug: gate
+ name: Gate
+ tag: CEX, USDT perpetuals via Mobula aggregator, 8h funding
+ formula: "stddev_over_time of perp_venue_funding_24h_bps{venue=\"gate\",asset=\"ETH\"} over a 24h window. Source: Mobula CEFI funding-rate aggregator."
+ queries:
+ p50: stddev_over_time(perp_venue_funding_24h_bps{venue="gate",asset="ETH"}[24h])
+ p90: stddev_over_time(perp_venue_funding_24h_bps{venue="gate",asset="BTC"}[24h])
+ p99: stddev_over_time(perp_venue_funding_24h_bps{venue="gate",asset="SOL"}[24h])
+ mean: stddev_over_time(perp_venue_funding_24h_bps{venue="gate",asset="ETH"}[24h])
+ success: (perp_venue_last_refresh_unix{venue="gate"} > bool (time() - 300))
+ sample_size: count_over_time(perp_venue_funding_24h_bps{venue="gate",asset="ETH"}[24h])
+ series: stddev_over_time(perp_venue_funding_24h_bps{venue="gate",asset="ETH"}[24h])
+
+ - slug: kraken
+ name: Kraken
+ tag: Regulated CEX, perpetuals via Mobula aggregator
+ formula: "stddev_over_time of perp_venue_funding_24h_bps{venue=\"kraken\",asset=\"ETH\"} over a 24h window. Source: Mobula CEFI funding-rate aggregator."
+ queries:
+ p50: stddev_over_time(perp_venue_funding_24h_bps{venue="kraken",asset="ETH"}[24h])
+ p90: stddev_over_time(perp_venue_funding_24h_bps{venue="kraken",asset="BTC"}[24h])
+ p99: stddev_over_time(perp_venue_funding_24h_bps{venue="kraken",asset="SOL"}[24h])
+ mean: stddev_over_time(perp_venue_funding_24h_bps{venue="kraken",asset="ETH"}[24h])
+ success: (perp_venue_last_refresh_unix{venue="kraken"} > bool (time() - 300))
+ sample_size: count_over_time(perp_venue_funding_24h_bps{venue="kraken",asset="ETH"}[24h])
+ series: stddev_over_time(perp_venue_funding_24h_bps{venue="kraken",asset="ETH"}[24h])
+
+ - slug: kucoin
+ name: KuCoin
+ tag: CEX, USDT perpetuals via Mobula aggregator, 8h funding
+ formula: "stddev_over_time of perp_venue_funding_24h_bps{venue=\"kucoin\",asset=\"ETH\"} over a 24h window. Source: Mobula CEFI funding-rate aggregator."
+ queries:
+ p50: stddev_over_time(perp_venue_funding_24h_bps{venue="kucoin",asset="ETH"}[24h])
+ p90: stddev_over_time(perp_venue_funding_24h_bps{venue="kucoin",asset="BTC"}[24h])
+ p99: stddev_over_time(perp_venue_funding_24h_bps{venue="kucoin",asset="SOL"}[24h])
+ mean: stddev_over_time(perp_venue_funding_24h_bps{venue="kucoin",asset="ETH"}[24h])
+ success: (perp_venue_last_refresh_unix{venue="kucoin"} > bool (time() - 300))
+ sample_size: count_over_time(perp_venue_funding_24h_bps{venue="kucoin",asset="ETH"}[24h])
+ series: stddev_over_time(perp_venue_funding_24h_bps{venue="kucoin",asset="ETH"}[24h])
+
+ - slug: lighter
+ name: Lighter
+ tag: zkSync L2 perps DEX, native funding via Mobula aggregator
+ formula: "stddev_over_time of perp_venue_funding_24h_bps{venue=\"lighter\",asset=\"ETH\"} over a 24h window. Source: Mobula CEFI funding-rate aggregator."
+ queries:
+ p50: stddev_over_time(perp_venue_funding_24h_bps{venue="lighter",asset="ETH"}[24h])
+ p90: stddev_over_time(perp_venue_funding_24h_bps{venue="lighter",asset="BTC"}[24h])
+ p99: stddev_over_time(perp_venue_funding_24h_bps{venue="lighter",asset="SOL"}[24h])
+ mean: stddev_over_time(perp_venue_funding_24h_bps{venue="lighter",asset="ETH"}[24h])
+ success: (perp_venue_last_refresh_unix{venue="lighter"} > bool (time() - 300))
+ sample_size: count_over_time(perp_venue_funding_24h_bps{venue="lighter",asset="ETH"}[24h])
+ series: stddev_over_time(perp_venue_funding_24h_bps{venue="lighter",asset="ETH"}[24h])
+
+ - slug: mexc
+ name: MEXC
+ tag: CEX, USDT perpetuals via Mobula aggregator, 8h funding
+ formula: "stddev_over_time of perp_venue_funding_24h_bps{venue=\"mexc\",asset=\"ETH\"} over a 24h window. Source: Mobula CEFI funding-rate aggregator."
+ queries:
+ p50: stddev_over_time(perp_venue_funding_24h_bps{venue="mexc",asset="ETH"}[24h])
+ p90: stddev_over_time(perp_venue_funding_24h_bps{venue="mexc",asset="BTC"}[24h])
+ p99: stddev_over_time(perp_venue_funding_24h_bps{venue="mexc",asset="SOL"}[24h])
+ mean: stddev_over_time(perp_venue_funding_24h_bps{venue="mexc",asset="ETH"}[24h])
+ success: (perp_venue_last_refresh_unix{venue="mexc"} > bool (time() - 300))
+ sample_size: count_over_time(perp_venue_funding_24h_bps{venue="mexc",asset="ETH"}[24h])
+ series: stddev_over_time(perp_venue_funding_24h_bps{venue="mexc",asset="ETH"}[24h])
diff --git a/public/logos/binance.svg b/public/logos/binance.svg
new file mode 100644
index 00000000..ecaa7fb4
--- /dev/null
+++ b/public/logos/binance.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/logos/bitget.png b/public/logos/bitget.png
new file mode 100644
index 00000000..0290612b
Binary files /dev/null and b/public/logos/bitget.png differ
diff --git a/public/logos/coinbase.svg b/public/logos/coinbase.svg
new file mode 100644
index 00000000..c3ed947a
--- /dev/null
+++ b/public/logos/coinbase.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/logos/deribit.png b/public/logos/deribit.png
new file mode 100644
index 00000000..f7be01be
Binary files /dev/null and b/public/logos/deribit.png differ
diff --git a/public/logos/gate.png b/public/logos/gate.png
new file mode 100644
index 00000000..9e5900f4
Binary files /dev/null and b/public/logos/gate.png differ
diff --git a/public/logos/kraken.png b/public/logos/kraken.png
new file mode 100644
index 00000000..8ebd5099
Binary files /dev/null and b/public/logos/kraken.png differ
diff --git a/public/logos/kucoin.svg b/public/logos/kucoin.svg
new file mode 100644
index 00000000..68462f47
--- /dev/null
+++ b/public/logos/kucoin.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/logos/mexc.png b/public/logos/mexc.png
new file mode 100644
index 00000000..3f783c7e
Binary files /dev/null and b/public/logos/mexc.png differ
diff --git a/src/lib/logo-manifest.ts b/src/lib/logo-manifest.ts
index 68765d06..25cc7214 100644
--- a/src/lib/logo-manifest.ts
+++ b/src/lib/logo-manifest.ts
@@ -100,7 +100,7 @@ const RAW: Record = {
"1rpc": "/logos/1rpc.svg",
cloudflare: "/logos/cloudflare.svg",
"base-official": "/logos/base.jpeg",
- binance: "/logos/bnb.png",
+ binance: "/logos/binance.svg",
lava: "/logos/lava.webp",
nodies: "/logos/nodies.png",
tenderly: "/logos/tenderly.svg",
@@ -187,6 +187,16 @@ const RAW: Record = {
paradex: "/logos/paradex.svg",
aster: "/logos/aster.svg",
+ // ─── Perp funding stability cohort additions (bench № 043) ───
+ // Sourced via Mobula CEFI funding-rate aggregator.
+ bitget: "/logos/bitget.png",
+ coinbase: "/logos/coinbase.svg",
+ deribit: "/logos/deribit.png",
+ gate: "/logos/gate.png",
+ kraken: "/logos/kraken.png",
+ kucoin: "/logos/kucoin.svg",
+ mexc: "/logos/mexc.png",
+
// ─── Hyperliquid HIP-3 deployers (bench № 035) ───
xyz: "/logos/xyz.png",
vntl: "/logos/vntl.png",
diff --git a/src/lib/materialize/load.ts b/src/lib/materialize/load.ts
index dd77a6b4..370e4b97 100644
--- a/src/lib/materialize/load.ts
+++ b/src/lib/materialize/load.ts
@@ -42,6 +42,7 @@ export type BenchmarkFilters = {
chain?: string;
region?: string;
kind?: string;
+ venue?: string;
};
export function filterSig(f: BenchmarkFilters): string {
@@ -58,8 +59,8 @@ export function parseFilterSig(sig: string): BenchmarkFilters {
if (!sig) return out;
for (const kv of sig.split("&")) {
const [k, v] = kv.split("=");
- if (k && v && (k === "chain" || k === "region" || k === "kind")) {
- out[k as "chain" | "region" | "kind"] = v;
+ if (k && v && (k === "chain" || k === "region" || k === "kind" || k === "venue")) {
+ out[k as "chain" | "region" | "kind" | "venue"] = v;
}
}
return out;
diff --git a/src/lib/spec-schema.ts b/src/lib/spec-schema.ts
index ab57dac6..d57e8694 100644
--- a/src/lib/spec-schema.ts
+++ b/src/lib/spec-schema.ts
@@ -344,6 +344,14 @@ export const SpecSchema = z
})
)
.optional(),
+ venue: z
+ .array(
+ z.object({
+ value: z.string().regex(/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/),
+ label: z.string().min(1).max(64),
+ })
+ )
+ .optional(),
})
.optional(),