MarketTrace
M1PositioningM2FootprintM3LiquidationsM4FundingM5Volume ProfileM6Book Depth
Methodology · v1.1.0 · published 2026-05-21 · updated 2026-09-02

Perpetuals Heat Index

How the per-asset percentile and the equal-weight global score are computed, what the breadth counters mean, and where the data does not yet reach.

See the live widget at /perpetuals/positioning.

Data sources

The Heat Index reads one upstream file: data/research/heat_index.json, written by the PPI shadow-log cron at every hourly :05 UTC firing. That cron also maintains the per-asset ppi_log.jsonlfiles. So the index inherits PPI's settlement cadence at the data level, one new datum per Binance funding settle. That is every 8 hours for the original six assets and every 4 hours for HYPE, even though the FE polls every five minutes.

PPI itself is a rolling 180-settlement z-score of Binance USDT-margined funding rates per asset. At 3 settlements a day that is about 60 days of context; HYPE settles twice as often on Binance, so its 180 settlements cover about 30 days. The shadow logger has captured every Binance settlement since 2024-07-07 for the original six, 3 a day, which puts each of those logs around 2,360 samples as of September 2026. HYPE's log starts in mid-2025, once its own Binance history filled the 180-settlement window, and holds about 2,580 samples at the denser cadence. Those per-asset logs are the historical distribution the percentile maps against.

Per-asset percentile

For each tracked asset the index ranks the current PPI value against that asset's own log, which starts 2024-07-07 for the original six and mid-2025 for HYPE. The formula is straight bisect_right: count how many historical PPI samples are less than or equal to the current value, divide by the total count, multiply by 100.

percentile_pct = bisect_right(sorted(history), current_ppi)
                  / len(history) × 100

A BTC score of 92 means today's BTC funding-z sits higher than 92% of every BTC funding-z observed since 2024-07-07. Each asset is graded on its own curve, so a BTC 92 and a DOGE 12 on the same day is a statement about position-within-history per asset, not absolute funding rates being equal.

Global aggregate

The market-wide score is the equal-weight average of the seven per-asset current PPI values, mapped to the percentile of the same equal-weight aggregate computed historically over every timestamp where all seven assets have a value. An asset joins the aggregate only if it has both a current PPI and a log; there is no per-timestamp substitution for a missing one, and the historical series is a strict intersection.

HYPE costs that shared window twice over. Its log starts in mid-2025, which truncates the intersection to that start, and Binance settles it every 4 hours against the others' 8, so only its 00:00 / 08:00 / 16:00 settlements line up with the rest. The shared window holds about 1,290 timestamps as of September 2026, against roughly 2,360 per asset for the original six. The payload discloses both figures: n_history for the shared window, n_history_per_asset for the per-asset depth.

current_agg     = mean([ppi.btc, ppi.eth, ppi.sol, ppi.bnb,
                        ppi.xrp, ppi.doge, ppi.hype])
historical_agg  = [mean(per_asset_ppi(t)) for t in shared_timestamps]
global_pct      = bisect_right(sorted(historical_agg), current_agg)
                  / len(historical_agg) × 100

Equal weight, not OI weight. BTC dominates open interest at around 60% of total perp OI, so an OI-weighted composite would track BTC closely. Equal weight surfaces breadth instead. When five of seven assets run hot together the score climbs, even if BTC alone hasn't broken out.

Breadth counters

Alongside the global percentile, the payload exposes two counters: how many of the seven assets currently sit in Hot or Euphoric bands, and how many sit in Cold or Panic. The widget renders these as “1 of 7 perps in hot zone”.

Breadth separates a broad regime shift from a single-asset blowout. Global score 75 with breadth_hot=5 means most of the market is warm at once. Global score 75 with breadth_hot=1 means one asset is at an extreme high and is pulling the average up by itself. Same headline number, very different microstructure.

Caching and freshness

The endpoint reads heat_index.json on every request and returns 503 if the file is older than two hours. Beyond that something is wrong upstream (timer dead, PPI cron failing, disk full) and serving stale heat values would mislead the FE more than an honest error.

Cache-Control sets 5-minute max-age plus 10-minute stale-while-revalidate, so a CDN can absorb most traffic without ever stale-serving past the file's actual age. FE polling matches: SWR refresh every five minutes. Since the file updates hourly, 11 of every 12 client requests return identical bytes from the CDN.

Limitations

Versioning

Methodology version v1.1.0, published 2026-05-21, updated 2026-09-02. Material changes to the compute path (new weighting, threshold tweaks, additional inputs) bump the version and update dateModified in the structured data above. Wording fixes do not.

v1.1.0 (2026-09-02): HYPE joined the aggregate on 2026-07-20 as a seventh input. Its PPI log is shorter than the original six and Binance settles it twice as often, so the shared window behind the global percentile is now well below the per-asset depth. The aggregate section spells out what that costs.

v1.0.0 (2026-05-21): initial release, six assets.