How Alpha scoring works
§1
Principles
Alpha is a screen, not a recommendation. Each tab answers one narrow question with a weighted composite of disclosed, objective signals, and every card shows its full component breakdown so you can see why it ranked where it did. Thresholds exist to filter noise (dust volume, near-zero caps, spam duplicates), not to imply quality.
The underlying question every screen is really asking is “is this worth a closer look, or is it more likely to be a dead-cat bounce, a rug in progress, or an abandoned shell?”, never “will this go up.” No formula can answer that; markets this young and this thin are dominated by noise. What the signals below can do is separate real, broadly-held, currently-active trading from common look-alikes: a finished pump-and-dump (impressive totals, no present: caught by last-hour volume and momentum) and a wash-traded mint (volume with no distinct buyers: caught by holders paid and on-chain distribution).
§2
Shared math
logScore(value, floor, ceiling)
Maps a raw number onto 0–100 on a logarithmic scale: floor → 0, ceiling → 100, clamped beyond either end. Log scaling means going from $1k to $10k of volume is worth as much as $10k to $100k, the right shape for quantities that span orders of magnitude.
Weighted average
Every component is 0–100; the score is the weight-normalised average, so adding an optional component (like “Graduation pace” for bonding-curve tokens) never inflates or deflates a score by itself.
momentumScore(recentRate, olderRate)
Compares one window's per-hour volume with the token's own earlier per-hour rate over that same window. 50 means steady; above 50 is accelerating; below is fading. Symmetric on a log scale, clamped to a 4× band either way, so 4× faster and 4× slower sit the same distance from centre. If there is no earlier volume at all, any recent volume scores 100.
computeMomentum(activity, hours): the blend
Every screen that scores momentum runs this same function on two independent windows: the hourly trend (the last hour vs. the rest of the lookback the token has actually existed for) and the 15-minute pulse (the last completed 15-minute candle vs. the one before it). The hourly window needs at least 15 minutes of “before” to compare against (so effectively age ≳ 1h15m); the 15-minute window only needs the token to be at least 30 minutes old, independent of the hourly one. When both exist, the score used for ranking is the average weighted 2:1 toward the hourly read, steadier, but slower to notice a turn than the immediate pulse. When only one exists, that one is used directly. When neither does (a token under 30 minutes old), there is no Momentum component at all: not a guessed 50.
The reason text is built from the same two windows, not the blended number: when they agree, the sentence quotes whichever window's ratio is more extreme (“Accelerating: 3.2x its earlier pace”); when they disagree (the hourly trend still looks fine but the last 15 minutes have gone quiet, or the reverse), that disagreement is treated as the more decision-relevant fact and leads instead (“Cooling in just the last 15 minutes, after a strong hour overall”). A token that's steady on every timeframe gets no momentum line at all: nothing worth saying isn't forced into a sentence.
distributionScore(top10Pct): on-chain concentration
This reads live from chain (not from StonkFun's snapshot) via the same holder scan the token page's Holders panel uses. It is piecewise-linear through the exact thresholds that panel colours amber and red at, so the score and holder view cannot disagree about what counts as concentrated. Higher means the top 10 real wallets hold less supply.
An unreadable scan (RPC unavailable, refused, or simply hasn't run for that mint yet) scores 50, a neutral middle, never a penalty. A token this screen hasn't checked at all (the first, free-signals pass) gets no Distribution component whatsoever, the same “didn't check” vs. “checked, unknown” distinction used everywhere else on this page.
§3
New launches gaining traction
Question: among tokens created in the last 6 / 24 hours, which ones are actually being traded right now, by real people, and still holding what they built?
Candidate pool
The newest-sorted StonkFun list, 10 pages for 6h, 25 pages for 24h (100 tokens per page). StonkFun launches ~100 tokens per 50 minutes, so the pool has to scale with the window or every setting would see the same few dozen mints. Duplicate name+symbol launches (spam clusters) collapse to their best-scoring instance.
Hard exclusions
- 24h volume under $5,000 or market cap under $15,000: a mint nobody but the deployer has touched.
- After the chart check: no trade in the last 120 minutes, or under $250 of volume in the last hour. The second rule is what removes a launch that did $150k early and $40 since.
- More than 75% below its own peak market cap. A dump prints a lot of volume; that volume is not traction, and a weight can't outvote it: only a gate can.
Components (total weight 23)
| Component | Weight | Share | Signal | 0 → 100 scaling |
|---|---|---|---|---|
| Last hour volumesecond pass only | 1 | 4% | Dollar volume in the trailing 60 minutes (Jupiter candles) | logScore(v, 250, 50,000) |
| Holders paid | 5 | 22% | Distinct wallets paid a reward so far (reward ledger) | logScore(n, 5, 500); 35 if no ledger row yet |
| Distributionsecond pass only | 2 | 9% | Top-10 real-wallet share of supply, read live from chain | distributionScore(pct), see below; 50 if the scan hasn't run yet |
| Market cap | 1 | 4% | Current market cap | logScore(mc, 5,000, 5,000,000) |
| Holding its peakwhen a peak is known | 3 | 13% | Current market cap ÷ peak market cap | round(ratio × 100), clamped 0–100 |
| Still tradingsecond pass only | 5 | 22% | Minutes since the last candle with volume | 100 × (1 − minutes / 120) |
| Momentumsecond pass only | 1 | 4% | Blend of the hourly trend and the 15-minute pulse; see below | computeMomentum(...).value |
| 24h volume | 1 | 4% | StonkFun trailing-24h dollar volume | logScore(v, 1,000, 500,000) |
| Graduation pacebonding-curve tokens only | 2 | 9% | Bonding-curve progress ÷ age in hours | logScore(pace, 0.02, 1) |
| Turnover | 2 | 9% | 24h volume ÷ market cap | logScore(x, 0.05, 15) |
Table 1: New Launches component weights
Why these weights: holders paid and still trading are weighted heaviest: real distinct wallets, and a live trade within the exclusion window, are what “gaining traction” actually verifies, and neither can be inflated by a mint that's already finished its run. Holding its peak carries the next-most weight: still near its own high is a real anti-dump signal, though a moderate rather than a maximal one on its own. Turnover, graduation pace, and distribution sit in the middle. Last-hour volume and momentum are deliberately light despite sounding like the obvious “traction right now” signals, and market cap and 24h volume are light for the original reason (both reward cumulative size, which a token can only have once it's already grown): re-weighted 2026-09-16 once StonkScout's own continuous learning had 200+ real 24h outcomes per factor to check against, and last-hour volume and momentum were the two factors most correlated with a worse outcome, not a better one — a volume or momentum spike at the moment a token is scored is as often the top of a pump as it is real accumulation. See “Continuous learning” below for the exact correlations behind this and every other screen's weights.
§4
Overlooked, seeing renewed interest
Question: which tokens has the market priced as dead (far below their own peak) that are nonetheless trading live today, and picking up rather than fading?
Candidate pool
The top 300 projects by 24h volume, minus the top 25. The busiest markets on the platform are the opposite of overlooked, whatever their drawdown: a coin at #4 by volume was showing up here before this cut.
Hard exclusions
- Younger than 7 days: a same-day launch shows a 90% “drawdown” from ordinary first-day volatility.
- Less than 50% below its peak market cap, or under $500 of 24h volume.
- After the chart check: no trade in the last 120 minutes.
- After the chart check: momentum under 50, the last hour slower than the token's own earlier pace. “Picking up, not fading” is the screen's question, so fading is an exclusion, not a low score.
Components (total weight 11)
| Component | Weight | Share | Signal | 0 → 100 scaling |
|---|---|---|---|---|
| Still tradingsecond pass only | 3 | 27% | Minutes since the last candle with volume | 100 × (1 − minutes / 120) |
| Momentumsecond pass only; also the momentum gate | 3 | 27% | Blend of the hourly trend (last hour vs. the previous 11) and the 15-minute pulse; see Shared math | computeMomentum(...).value |
| Below peak | 2 | 18% | Drawdown from all-time-peak market cap | 100 × (drawdown − 0.5) / (1 − 0.5) |
| Current turnover | 2 | 18% | 24h volume ÷ market cap | logScore(x, 0.05, 10) |
| Track record | 1 | 9% | Lifetime reward payout count (reward ledger) | logScore(n, 10, 20,000); 0 if no ledger row |
Table 2: Overlooked component weights
Deliberately no market-cap-size component: a $9k comeback with real accelerating volume is exactly what this screen exists to surface and must not be outranked by a $500k one for being larger. A unit test enforces this. Also deliberately no on-chain distribution component, unlike New Launches: these candidates are already established (≥7 days old, traded at real scale), so a live holder scan is both less informative and (for a pool of hundreds of sometimes large-holder-count tokens) meaningfully more expensive to run than on a pool of brand-new, small-holder-count mints.
§5
DEGEN MODE
Question: among launches under an hour old, which ones show no confirmed rug mechanism? This is deliberately not the same question the other three screens ask. For most of this screen's population, none of their proven signals exist yet: New Launches' own volume and market-cap gates ($5,000 / $15,000) are essentially unclearable in the first few minutes, and computeMomentum (see “Shared math”) returns nothing at all under roughly 30 minutes of age — and this screen never leans on momentum even for the older end of its window, close to the one-hour mark, where it could technically be computed. Rather than guess at “potential” from data that mostly doesn't exist yet, this screen is elimination-first: drop anything showing a real, permanent rug mechanism, then score what survives on how clean its remaining on-chain signals are.
Candidate pool
Every StonkFun launch created within the last 60 minutes: the newest-sorted list is fetched fresh every 30 seconds, so a launch enters and leaves this screen entirely based on age, not on how it's performing.
Hard exclusions: only on confirmed-true data
- Top 10 wallets hold 60% or more of supply, confirmed, but only once at least 15 holders exist. Below that, “top 10 hold X%” is an artifact of being new (top 10 of 8 holders is ~100% by construction), not a real concentration signal, so the gate, and the score component below, simply don't apply yet.
- Mint or freeze authority confirmed still active: verified on-chain per token, kept as a defensive check, but see the callout below for why this should never actually be what excludes a real StonkFun launch.
true. A field the RPC hasn't answered yet (common in the first minute or two of a token's life) leaves that gate un-tripped and its score component at a neutral default: never treated as a pass or a fail it can't actually support.The whale signal
StonkScout already maintains a registry of wallets holding real size (10M+ tokens) in the platform's 30 largest tokens: see How holder data works. DEGEN MODE cross-references a brand-new launch's current top holders against that same registry: no new infrastructure, just the holder scan this screen already runs for the concentration gate, checked against data already being fetched for every token page. This is deliberately weighted alongside the safety gates rather than left as a footnote: unlike raw volume or holder count, it's genuinely hard to fake: reproducing it requires an existing wallet with a real, costly prior position in an established token, not a few dollars of self-directed buying.
Components (total weight 65)
Every candidate that remains in Degen Mode receives a Degen Mode Scout Score, including candidates whose newest on-chain checks are still unavailable. Unread signals use the documented neutral value and lower the separate data-confidence label. Top New and Overlooked each calculate their own Scout Score from their own components and gates; scores only compare candidates within the same mode.
| Component | Weight | Share | Signal | 0 → 100 scaling |
|---|---|---|---|---|
| Known whale bought in | 35 | 54% | Is any current top holder a known whale of an established platform token? | 100 found · 40 checked, none found · 50 couldn't check |
| Curve pacepre-graduation only | 8 | 12% | Bonding-curve progress ÷ age in minutes. Slower measured progress scores higher; zero progress is unverified. | 100 − logScore(pace, 0.002, 0.15); zero progress is neutral/unknown |
| Distinct holders | 10 | 15% | How many separate wallets already hold it, read live from chain | logScore(n, 2, 100); 50 if unknown |
| Holder concentrationonly once 15+ holders exist | 12 | 18% | Top-10 real-wallet share of supply, read live from chain | linear, 20%→100, 60%→0 |
Table 3: DEGEN MODE component weights
Feeds the same learning loop as every other screen (see “Continuous learning”, below): once enough sighted coins have closed paper-trade returns, each component's weight adjusts based on what actually happened to tokens that showed it.
§6
The two-pass pipeline
Real-time recency and momentum need one Jupiter chart fetch per token (48 fifteen-minute candles, a 12-hour lookback); on New Launches, the on-chain components need one holder scan per token on top of that (Overlooked is the one screen that reads neither; see its own section for why). Both are cheap individually but not for a pool that can run to thousands, so every tab runs the same shape:
- Score every candidate on the free signals only (no chart data, no holder scan) and rank.
- Take the top 40, fetch their recent-activity candles and (where applicable) their holder scans in parallel.
- Re-score those with the real-time and on-chain components added, drop anything that turned out stale, rank again.
- Show the top 12.
Only the active tab's pipeline runs per request; the other tabs cost nothing until you open them.
§7
Continuous learning
Alpha records each coin's first score and component values. Its learning target is the average return from that coin's fully closed simulated positions under the strategies' entry and exit rules, net of modelled trading costs. Each closed position has equal weight in that average. Open positions, dip-entry strategies and holder rewards are excluded. The return is joined by coin to its first Alpha sighting; a coin contributes one paired sample, not one sample per strategy. It can contribute before every strategy has closed.
Each screen compares recorded scores and factor values with those returns separately. Only coins taken by the simulation are represented; this is historical calibration, not evidence of out-of-sample predictive power. Current correlations, sample sizes and stored adjustments are on /alpha/learning. Its totals include retired screens, while its factor tables cover live screens.
Since 2026-09-21, the 24h market-cap multiple is context only and never changes a weight. A recovery after a strategy exits is not that strategy's return. Older simulated exits may include stale-price errors fixed on that date. Trend comparisons use only snapshots with the same trade-return target.
- 1
Score
Record each coin's first Alpha score and factor values.
- 2
Simulate
Eligible strategies paper-trade calls using their entry and exit rules.
- 3
Measure
Average closed, non-dip position returns per coin, net of modelled costs.
- 4
Reweight
Compare factors with returns across the sample, then nudge eligible weights.
Spearman rank correlation
A few extreme returns can dominate a raw value-based correlation. Spearman correlation instead compares ranks: do higher recorded factor values tend to accompany better average paper-trade returns? It measures association, not the size of the profit or a guarantee that the factor will predict future returns. We write it ρ:
Three guardrails
lib/alpha/scoring.ts, which stay authoritative.The Learning page shows how many more paired coins a factor needs, without predicting when trades will close. A constant factor or return also has no measurable correlation. Previously stored multipliers remain in force when evidence is insufficient. A positive correlation can reduce a multiplier already above its target; colours describe the correlation, not the last weight movement. Effective weight is base weight × multiplier.
When this runs
The running server's research maintenance worker checks for learning cycles independently of page traffic, unless that worker is disabled. Portfolio-strength requests can also trigger the same gate. A cycle runs at most once per 3 hours in the running process: it attempts a bounded batch of 24h outcomes for context, then recomputes weights from available closed paper-trade returns. Alpha ranking reads the stored weights; opening an Alpha screen does not wait for retraining. Reports are cached briefly, and current correlations may differ from the evidence behind the last stored adjustment.
§8
Data sources & caveats
- StonkFun public API: market snapshot (price, market cap, peak, 24h volume, 24h change), the platform reward ledger (payout counts, holders paid), pairs, and launch timestamps. Its only server-side sorts are market cap, volume, and newest, which is why candidate pools are bounded rather than exhaustive.
- Jupiter chart data (datapi.jup.ag): per-candle volume for recency and momentum. It aggregates every venue a token trades on and runs well above StonkFun's own 24h figure, so last-hour dollar amounts are comparable between launches, not with StonkFun's totals. It is an unofficial endpoint and could change without notice.
- Holders paid only exists for reward-mode tokens that have completed at least one distribution. Standard launches and pre-first-payout tokens get the neutral default, not zero.
- On-chain holder scan (Distribution on New Launches; Holder concentration and Known whale bought in on DEGEN MODE): the same live `getProgramAccounts` read used by the token page's Holders panel, not part of the StonkFun snapshot. Not run on Overlooked (see its section for why). Cached 2 minutes per mint, so a token shown on more than one screen, or reloaded within the window, costs nothing extra. A refused or failed scan scores neutral, never a penalty; see “Shared math” above.
- Mint/freeze authority (DEGEN MODE only): read from the same on-chain mint account StonkScout already fetches for a token's decimals, cached 24 hours since it's immutable once renounced. A defensive gate only, not a scored or displayed signal; see “Why mint/freeze authority isn't scored” above.
- Scores are recomputed on every request from live data; the same token can move between screens minute to minute as its activity changes. That's the intended behaviour.
Source: src/lib/alpha/scoring.ts and its unit tests, which pin the regression cases each rule was added for.