PokeTop10
PokeTop10
HomeGuides › Methodology

How PokeTop10's Signals Work: Trend Score, Breakout Radar, CSIS, and Set Heat Index

PokeTop10 publishes four proprietary signals on every card and sealed product page. This document is the line-by-line methodology for what each one does, what its inputs are, and what its limits are. The math is published openly because a signal that can't be audited is worse than no signal at all.

PokeTop10 Research · Updated April 2026 · ~14 min read

Why publish this

Every signal on PokeTop10 is a function of public market data — eBay listings via the eBay Browse API, JustTCG Near Mint prices, PokémonTCG.io card metadata, plus historical snapshots taken twice daily since the platform launched. None of the signals are AI-generated; none use sentiment-scraping from social media. The math is reproducible given the same data feed. PokeTop10 treats publication of the formulas as a feature, not a tradeoff: if a reader can see exactly what the score is doing, that reader can decide whether to trust it.

The descriptions below match the actual code. The relevant functions are computeTrendScore(), computeBreakoutScores(), extractSealedSignals(), gradeSealedPopulation(), and computeSetHeatIndex() in poketop10-proxy-worker-v3.js. If anything in this guide drifts from the code, the code is the source of truth — please file a bug report at the GitHub issues page.

Trend Score (0-100)

Trend Score is a 0-100 momentum index for individual cards. It starts at a neutral baseline of 50 and adjusts up or down based on five components. Each component reflects a different way to measure "is this card moving."

The five components

  1. Price velocity (±20 pts). Compares the 7-day percentage change to a normalized 7-day equivalent of the 30-day rate. Formula: velocity = pct7d − (pct30d / 4.28). The result is multiplied by 2 and clamped to a ±20 range. A card up 10% over 7 days while up 20% over 30 days has nearly zero velocity (it's tracking its 30-day pace). A card up 10% over 7 days while flat over 30 days has strong positive velocity (the move is recent and accelerating).
  2. Moving average crossover (±15 pts). Bullish if both price > 7-day average AND 7-day average > 30-day average (classic short-over-long crossover). Awards +15 if true; -15 if the inverse is true (price below both moving averages with the 7-day below the 30-day). Otherwise zero — a "mixed" pattern doesn't contribute.
  3. Breakout detection (±15 pts). +15 if price is at or near its 30-day high (≥98% of max30d). -15 if price is at or near its 30-day low (≤102% of min30d). Captures the simple intuition that a card pressing the ceiling is more interesting than one drifting in the middle of the range.
  4. Slope consistency (±10 pts). Both 7-day and 30-day price-trend slopes positive → +10 (a sustained, multi-window uptrend). Both negative → -10. Mixed → zero.
  5. All-time range position (±10 pts). Where is the current price within its all-time range? Formula: position = (price − allTimeLow) / (allTimeHigh − allTimeLow). The score adjustment is (position − 0.5) × 20: at the all-time midpoint zero contribution, at the ATH a full +10, at the ATL a full -10.

Final score is the sum of all five components, rounded, and clamped to 0-100.

Trend label thresholds

The numerical score is mapped to a human-readable label:

LabelScoreSpecial override
Breakout≥80Plus: price at or above 98% of 30-day high AND 7-day change >5%
Trending Up≥65
Stable≥40
Declining≥20
Falling<20

The "Breakout" label is reserved — a high Trend Score alone isn't enough; the card has to also be testing its 30-day high with positive recent momentum. That filter prevents cards that simply ratcheted up months ago from being labeled "breaking out" today.

What Trend Score doesn't measure

It doesn't account for upcoming set releases, tournament results, social-media spikes, or any signal beyond the price series itself. A card breaking out the day before a major reprint announcement has a high Trend Score and is a terrible buy. The score is decision support, not gospel.

Breakout Radar

Breakout Radar is the daily top-20 list of cards most likely to continue moving — not just rising, but exhibiting the structural pattern of a developing breakout. It's computed from seven signals and only the top 20 highest-scoring candidates are published. Cards under $5 are filtered out as noise.

The seven signals

  1. Volatility compression → expansion (0-15 pts). Compares 7-day volatility to 30-day volatility. When the ratio is below 0.6 (recent volatility is much lower than historical) AND the 7-day percentage change is positive, the score awards up to 15 points. Compressed volatility followed by upward movement is the classic "tight coil before a breakout" pattern from technical analysis.
  2. 7-day acceleration vs 30-day baseline (0-15 pts). If the 7-day percentage change exceeds the implied 7-day rate from the 30-day average (acceleration is positive), points are awarded proportionally to the acceleration magnitude. A card recently moving faster than its longer-term pace is a leading indicator of momentum.
  3. Price near 30-day resistance (0-15 pts). Computes price position within the 30-day range as a fraction (0 at min, 1 at max). Position ≥0.90 awards proportional points up to 15. Logic: a card pressing the 30-day ceiling is far more likely to break out than one drifting near the floor.
  4. Consecutive positive timeframes (0-15 pts). Counts how many of {24h, 7d, 30d} are positive — multiplies by 5. A card up across all three timeframes scores 15 here; up across two scores 10; one scores 5. Sustained buying across multiple windows is conviction, not coincidence.
  5. Coiled spring near all-time low (0-10 pts). When current price is within 30% of the all-time low (price/allTimeLow < 1.3) AND either the 7-day or 30-day price slope is positive, points are awarded up to 10. Captures the "beaten-down with signs of life" pattern. Bonus +3 if both 7-day AND 30-day slopes are positive.
  6. Cross-set correlation (0-10 pts). Pre-pass groups all cards by set; any set with 3+ cards trending up over 7 days is flagged as a "hot set." Member cards of hot sets earn proportional points (up to 10) based on how many cards in the set are moving up. Logic: when one chase from a set pops, set-mates often follow.
  7. Google Trends signal (0-10 pts). Defaults to zero. When the SERP_API_KEY environment variable is configured, the system fetches Google Trends data via SerpAPI for each candidate and adds a contribution. This is optional and may be zero in production depending on key availability.

Cards with total scores below 15 are dropped. The remaining candidates are sorted descending by score, and the top 20 are published as the daily Breakout Radar.

Validation

Every Breakout Radar prediction is recorded to a D1 database table (breakout_predictions) with the predicted card, the price at prediction time, and the breakout score. A separate validateBreakoutPredictions() function runs in the daily cron and compares predicted prices against actual subsequent prices at 7-day and 30-day windows. Aggregate hit rate, expected value, and "vs random baseline" calculations are stored in the prediction_accuracy D1 table for ongoing audit.

The system was built to make hit-rate measurable, not to make claims about hit rate. PokeTop10 deliberately avoids publishing a specific accuracy figure ("we hit 60% of the time") in marketing copy because the rate varies by market regime — when the broader Pokémon market is in an uptrend, the rate is higher; in a correction, lower. The rate that matters is the one rolling over the most recent 90 days, and that number lives in the database where it can't be cherry-picked.

CSIS — Composite Sealed Investment Score

CSIS is a percentile-rank composite for sealed products. Booster boxes are graded against booster boxes, ETBs against ETBs, UPCs against UPCs — each product type ranked independently. The output is a letter grade (A through F) plus a 0-100 percentile score. The whole point of CSIS is that comparing a Crown Zenith ETB against an Evolving Skies booster box requires normalization; raw price comparisons are meaningless.

The seven input signals

SignalWeightDirectionMeaning
rangePosition0.15Lower is better(price − ATL) / (ATH − ATL). Closer to all-time low = better value.
pctInRange0.10Lower is better30-day relative position from JustTCG (0 at 30d low, 1 at 30d high). Functionally Bollinger %B.
momentum0.15Higher is betterWeighted blend: 0.6 × pct7d + 0.4 × pct30d.
trendStrength0.10Higher is better30-day price slope from JustTCG.
supplyScore0.20Higher is better4 = going-OOP, 3 = OOP, 2 = vintage, 0 = in-print.
volatility0.15Lower is betterJustTCG-reported 30-day standard deviation; lower = safer.
dollarMove0.15Higher is betterAbsolute dollar change: |pct30d / 100 × price|. Captures significance, not just percentage.

The seven signals are organized into five conceptual dimensions: Value (rangePosition + pctInRange = 25%), Momentum (momentum + trendStrength = 25%), Supply (supplyScore = 20%), Risk (volatility = 15%), and Significance (dollarMove = 15%). Total weights sum to 1.00.

How the score is computed

For each product type (booster boxes, ETBs, UPCs, etc.), the algorithm:

  1. Extracts all seven signals for every product in the type.
  2. For each signal, ranks the product by percentile within that signal's distribution. (Direction = -1 inverts the rank, so "lower is better" signals correctly reward low values.)
  3. Computes a weighted average of the percentile ranks using the weights above. Result is a composite score 0-1.
  4. Sorts all products by composite, then assigns letter grades based on the product's percentile rank within the population.

Letter grade thresholds

GradePercentile rank in product type
ATop ≥92%
B≥75%
C≥40%
D≥15%
FBottom <15%

There is no A+ grade — the highest grade in the system is A, awarded to the top 8% of products in their type. The grades are also relative to the population at the time of grading: a "C-grade booster box" today might be a "B-grade booster box" a month later if the population shifts. This is by design — CSIS is a relative ranking, not an absolute score.

Minimum population

The function returns no grades if a product type has fewer than 5 products. Each individual signal needs at least 2 values in the population to be computed. New product types ship without grades until enough data accumulates.

What CSIS doesn't tell you

CSIS doesn't account for upcoming reprint risk, sentiment, or news flow. A booster box can carry an A grade right up until TPCi announces a reprint — at which point the supply signal that was driving the grade evaporates overnight. CSIS is a snapshot of where the data sits today; it isn't predictive of future events that aren't in the data yet.

Set Heat Index (SHI)

Set Heat Index is a single ratio that captures the relationship between a set's chase chart and its sealed product price. It is intentionally simple. The formula is:

SHI formula

SHI = sum(top 10 most expensive cards in the set) / sealed product price

That's it. There's no weighting, no trend component, no listing-volume signal. SHI is one number that answers one question: "if you opened a booster box of this set today, would the value of the average top-10 chase chart be more or less than the cost of the box?"

Interpretation

SHI valueSignalLabel
SHI > 3.0"hot"Chase-Heavy — top 10 chases worth 3× or more than the box price
1.5 < SHI ≤ 3.0"neutral"Balanced — chase chart roughly proportional to box price
SHI ≤ 1.5"cold"Box-Favored — buyers are paying more for the box than the top chases collectively

Typical SHI values across the modern Pokémon TCG market are between 0.5 and 5.0. SHI is a ratio, not a 0-100 score. The numbers are not percentile ranks; they are direct value-to-price ratios with the thresholds above marking the meaningful breakpoints.

Why SHI doesn't equal "rip your boxes"

An important caveat lives in the code comment: a high SHI does NOT mean opening boxes is profitable. SHI ignores pull rates. A set with three $5,000 cards and a 1-in-1,000 chase rate could have a 3× SHI and still be a terrible open in expectation. The signal measures top-10-card-value-density relative to box price — interpret accordingly. SHI is most useful for comparing relative sealed value across sets, not for deciding whether to open versus hold.

How the data flows

All four signals are recomputed on a regular cadence by Cloudflare Workers cron triggers. As of April 2026, the architecture runs eleven separate cron triggers across each 24-hour cycle:

Splitting the work across multiple cron invocations is deliberate: each Cloudflare Worker invocation has a ~1,000-subrequest budget. Bundling all the work into a single twice-daily cron blew the budget and silently failed for thirteen days in April 2026. The eleven-cron architecture gives each step its own budget and isolated failure mode.

Honest limits

The signals capture pattern, not prophecy. They tell you where a card or product sits relative to its own history and to its market peers. They do not tell you what tomorrow's news will be, when TPCi will announce a reprint, whether a YouTuber's pull video will pump a particular card next week, or whether the broader market will catch a flu in three months. Treat them like an MRI: a high-resolution snapshot of structure, useful for diagnosing what is, not for predicting what will be.

Use Trend Score and Breakout Radar to surface candidates faster than scrolling through 4,000 cards manually. Use CSIS to compare sealed products across product types and eras on a normalized basis. Use Set Heat Index to compare set-level sealed-vs-singles value density. Then make the call yourself based on what you know about timing, sentiment, and your own conviction. The platform handles the math; you handle the judgment.

← Back to All Guides