Every number on VARIABLE is derived from on-chain reads. No partner APIs, no aggregator black boxes, no marketing-deck math. This page documents the formula behind every metric so you can audit our numbers.
We index four platforms directly against their canonical chains. Every metric on the site flows from one of these primitives:
Every index we publish belongs to the The Variable Index family (the V). Each has a ticker V-<CODE> and a name of the form The Variable <X> Index — e.g. V-MKT is The Variable Market Index, and V-PKMis the Pokémon index. Codes are derived from the IP catalog's short codes, so the registry extends itself as coverage grows (no hand-maintained list). The public API echoes each index's ticker, making it the canonical registry.
Every index we publish belongs to one family: The Variable Index(nickname "the V"). Each is a constant-quality price index — the trade-weighted stratified-median sale price within set×grade cells, rebased to 100 at inception — and carries a V-ticker derived from the entity's short code, so the scheme never drifts as the catalog grows. The whole market is V-MKT; each category and named IP has its own.
V-MKTThe Variable Market IndexV-TCGThe Variable TCG IndexV-SPTThe Variable Sports IndexV-PKMThe Variable Pokémon IndexV-OPThe Variable One Piece IndexV-YGOThe Variable Yu-Gi-Oh! IndexV-MTGThe Variable Magic: The Gathering IndexV-DSNThe Variable Disney / Lorcana IndexV-DBZThe Variable Dragon Ball IndexV-VFRThe Variable VeeFriends IndexV-RFTThe Variable Riftbound (LoL) IndexV-AZKThe Variable Azuki TCG IndexV-MOONThe Variable Moonbirds IndexV-PPGThe Variable Pudgy Penguins IndexV-WAXThe Variable Sealed Wax IndexV-NBAThe Variable Basketball IndexV-MLBThe Variable Baseball IndexV-NFLThe Variable Football (NFL) IndexV-SOCThe Variable Soccer IndexV-NHLThe Variable Hockey IndexV-F1The Variable F1 / Racing IndexV-SNKThe Variable Sneakers IndexV-CMXThe Variable Comics IndexPer-token value is the cheapest active USD listing on the platform's order book. For Collector Crypt we use the Insured Valuetrait (PWCC vault appraisal) since most CC tokens aren't actively listed.
[$1, $5M] are dropped.— to avoid surfacing meaningless aggregates from sparse data.Sum of qualifying secondary-market sales in the last rolling 24h. For Beezie + Courtyard sourced from Rarible; for Collector Crypt from a USDC + NFT same-transaction heuristic against the CC marketplace program. The native Courtyard marketplace event parser is on the roadmap and will replace the Rarible signal once shipped.
Active 24h = the union of unique buyer + seller wallets (set union, not sum). Same wallet on both sides counts once.
For each platform with a primary-market mechanic we maintain a disk cache populated by npm run warm-primary-revenue:
primary_revenue = Σ ( USDC inflow into platform.gacha_receivers
from senders NOT in platform.internal_exclusions )
For CC: filter to canonical pull prices [$25, $50, $75, $80, $100, $250, $1000]
For Phygitals/Courtyard: count every inbound USDC transfer.Internal exclusions are addresses we've identified as treasury / rarity-bucket / house wallets — transfers from them to a receiver represent internal moves, not user revenue.
Per-IP holders count = unique on-chain owners holding at least one card in that IP. Per-platform holders count = unique owners holding any card on that platform.
Caveat: total cross-platform holder count is currently a sum, not a strict union. A wallet holding cards on both Beezie and CC is double-counted in the homepage hero number. Per-IP rows do use the true union.
A pull is a USDC payment into a platform's gacha-receiver wallet. We bucket pulls by exact amount: for platforms with a published price ladder we filter to that ladder; for others we round to the nearest dollar.
EV (coming soon) = average appraised value of the NFT pulled in the same transaction, divided by the pack price. EV > 1 means the platform's house edge is currently negative for that pack. Requires NFT-output matching, in progress.
Warmers run on cron (target hourly). Server-rendered pages read from disk via unstable_cachewith a 1h revalidate window. The "Updated Xm ago" badge in each hero reflects the oldest underlying snapshot, not render time.
If a number looks wrong, tell us. Most discrepancies are invalidation lag (cache hasn't turned over) or scope gaps (off-chain activity we can't see). We add data sources, we don't hand-edit numbers.