Funding & Positioning
How the funding rate percentile, streak counter, and term-structure widgets are computed: sources, formulas, edge cases, limits.
See the live widgets at /perpetuals/funding.
Data sources
MarketTrace funding analytics combine three inputs: Binance's public funding-rate history, the per-asset snapshot daemon, and the tracked-asset roster.
- Historical funding rates. Binance USDS-margined perpetuals, public endpoint
fapi/v1/fundingRate. Pulled per asset on an 8-hour cycle, paginated 1000 rows at a time. Local ingest script keeps ~2 years of rolling history per asset (≈2,190 cycles × 6 assets ≈ 13k rows total, ~1.3 MB on disk). - Current funding rate. Read from
data/<asset>/market_snapshot.json, written by the snapshot daemon every ~5 minutes. The widget surfaces the value as percent (raw API field is a fraction; we multiply by 100 at the boundary). - Tracked assets. BTC, ETH, SOL, BNB, XRP, DOGE. Cross-exchange feeds (Bybit, OKX) are out of scope for this version and arrive in Phase 3.
Percentile rank: how it's computed
A funding rate percentile of N means N% of 8-hour cycles in the last two years printed at or below the current rate. We split ties evenly so identical observations rank between strict-less-than and less-or-equal counts.
Concretely, given a sorted list of historical percent values S:
left = count of elements in S strictly less than current right = count of elements in S less than or equal to current rank = (left + right) / 2 percentile = (rank / |S|) × 100
The result is bounded [0, 100]. A 0th percentile means the current rate is the most negative reading in the window; 100th means it is the most positive.
Percentile rank: edge cases
- Insufficient history. When the on-disk window spans fewer than
90 days, the API returnspartial: trueand a null percentile. The FE renders an “insufficient history” cell rather than a misleading number from a thin sample. - Missing current rate. When the snapshot has no
funding_rate(cold start, daemon down), the percentile is null and the FE shows —. - Sample size disclosure. The actual number of contributing cycles (
sample_n) is shown alongside every percentile so the reader can judge how robust the rank is.
Streak: how it's computed
A funding streak is the run of consecutive 8-hour cycles that share the same sign as the latest cycle. Streak length, in days, is the elapsed time between the first cycle in the run and the latest cycle. A neutral cycle (rate exactly 0) ends any streak.
direction = sign(latest.rate) // "neg" | "pos" | "neutral" walk back through history while sign matches streak.days = (latest.ts - first_in_streak.ts) / 86_400_000
Direction labels: "neg" (shorts pay longs), "pos" (longs pay shorts), "neutral" (latest cycle is zero or no history).
Streak: rarity flag
The rare flag fires when the current streak length is in the top 10% of historical same-direction streak lengths for that asset. We also require at least 10 prior completed streaks before publishing a rarity claim. Without that floor the threshold can come from a tiny sample and overfire.
Term structure
Funding term structure is a table that shows current funding rate, 2-year percentile, and active streak length for all six tracked perpetual pairs at once. The endpoint returns one row per asset; embeds can override the asset list via ?assets=btc&assets=eth.
Distribution histogram
The funding rate distribution histogram is a 30-bucket frequency chart of every 8-hour cycle in the asset’s 2-year history. Bin width is dynamic per asset across the observed [min, max] range; fixed [-0.1%, +0.1%]would clip DOGE/SOL outlier tails and waste resolution on the BTC body. Each bin reports the timestamp of the most recent cycle that fell in it, so the tooltip can show “last seen YYYY-MM-DD”.
L/S ratio
The Long/Short positioning ratio is intentionally not shipped in this version. The Binance globalLongShortAccountRatioendpoint exposes a single venue’s ratio, but a meaningful divergence read requires Bybit and OKX feeds alongside it. The cross-exchange L/S widget arrives in Phase 3 with the rest of the multi-venue infrastructure, instead of shipping a Binance-only sparkline that misframes the metric.
Caching
- Percentile.
Cache-Control: max-age=3600(1h). The 2-year rank shifts negligibly within an hour. - Streak.
Cache-Control: max-age=60(1m). Streak length ticks every 8h cycle but the FE may want a tighter heartbeat for nearby flips. - Term structure.
max-age=60, matching the streak component (its freshest dependency). - Distribution.
max-age=86400(24h). One new cycle per day adds ~1 row to a 2k-row histogram; shape barely shifts.
Limitations
- Single-exchange (Binance) until Phase 3. Funding rates differ between venues; one-venue percentiles can mislead when venues diverge sharply.
- 8-hour granularity. Funding settles at 00:00 / 08:00 / 16:00 UTC. Intra-cycle direction shifts (rare) are invisible to this widget.
- Account composition is opaque. Funding rate is a market-clearing price between long and short OI; it does not decompose into who is positioned where.
- History depth is rolling 2 years. Comparisons to older regimes (e.g. 2020 spikes) are not represented in the percentile.
Versioning
Methodology version v1.0.0 · published 2026-05-07. Material changes (new sources, formula tweaks, threshold changes) bump the version and update dateModified in the structured data above.