How the numbers are made
Every score on Sharpside is a deterministic function of public Polymarket data. This page gives the formulas, weights and thresholds exactly as the backend runs them, with the source file for each, so any number on the site can be checked by hand.
- SharpScore
- 0–100 · v1
- Sharp wallet
- SharpScore ≥ 70
- Insider-pattern flag
- score ≥ 50
- Whale trade
- ≥ $10k or market p99
- Windows
- 30m · 1h · 6h · 12h · 24h
- Trade tape
- polled every 15 s
2Insider-pattern score
source apps/api/src/analytics/insiderScore.ts
The insider-pattern score (0–100) measures how closely one open position matches a pattern often seen before surprising resolutions: a new account, an outsized position, few other markets, a cheap entry, opened shortly before the end. It is the sum of five weighted signals. A signal contributes only once its threshold is met, and contributes more the further past the threshold the position is.
2.1Five signals
| Signal | Weight | Triggered when | Share of weight earned | Measured from |
|---|---|---|---|---|
| New account | 25 | age < 30 d | 1 − age / 30 | wallet’s first Polymarket activity |
| Outsized position | 25 | Z ≥ 3 | min(1, 0.5 + 0.5·(Z − 3) / 3) | position Z-score in the market, §2.2 |
| Few other markets | 20 | markets ≤ 5 | 1 − (n − 1) / 5 | markets the wallet has ever traded |
| Low entry price | 15 | entry < 30¢ | 1 − entry / 0.30 | average entry price of the position |
| Close to resolution | 15 | ≤ 72 h before end, last 25% of life | 1 − hours / 72 | first trade in this market vs. scheduled end |
points_i = weight_i × share_i rounded to 0.1; 0 when not triggered score = min(100, Σ points_i) rounded to 0.1
- The size signal starts at half its weight at Z = 3 and reaches full weight at Z = 6. A wallet that has traded only this market earns the full 20 for focus; five markets earn 4.
- The market-life condition keeps same-day sports and esports markets — where every position opens hours before the end — from tripping the timing signal. When a market’s start date is unknown, only the 72-hour rule applies.
- Missing inputs (age unknown, too few holders for a Z-score) leave that signal at zero points.
- Thresholds and weights are configuration (
INSIDER_*, weights re-normalised to sum to 100). Each flag stores every signal’s weight asmaxPoints, so a breakdown always shows the weights it was scored with.
2.2Z-score
source apps/api/src/analytics/zscore.ts
Z = (x − μ) / σ
x = the holder's position value in USD (shares × current price of that outcome)
μ = mean position value over all visible holders of the market, both outcomes
σ = population standard deviation over the same set
undefined when fewer than 3 holders, or σ = 0Polymarket’s holders endpoint returns at most 500 holders per outcome, so μ and σ are over the visible set. Large holders inflate σ, which makes this a conservative Z: a position has to stand well clear of other large positions, not just of the small ones.
2.3Worked example
A wallet that is 4 days old holds a position 4.5σ above the market mean, has traded 2 markets in total, entered at an average of 12¢, and opened 18 hours before the scheduled end of a market that ran for 30 days.
| Signal | Measured | Share | Points |
|---|---|---|---|
| New account | 4 days < 30 | 1 − 4/30 = 0.867 | 21.7 / 25 |
| Outsized position | Z 4.5 ≥ 3 | 0.5 + 0.5 · 1.5/3 = 0.75 | 18.8 / 25 |
| Few other markets | 2 ≤ 5 | 1 − 1/5 = 0.80 | 16.0 / 20 |
| Low entry price | 12¢ < 30¢ | 1 − 0.12/0.30 = 0.60 | 9.0 / 15 |
| Close to resolution | 18 h, last 2.5% of life | 1 − 18/72 = 0.75 | 11.3 / 15 |
| Insider-pattern score | listed ≥ 50 · alert ≥ 70 | 76.8 |
2.4Scanning and listing
Every 5 minutes the whales-insiders job scans up to 40 open markets: scans requested from market pages first, then markets with whale trades in the last 6 hours, then the largest markets by 24-hour volume. For each market it reads up to 500 holders per outcome, computes every holder’s Z-score, and evaluates the signals for the 15 largest holders with a position worth ≥ $10,000 (WHALE_POSITION_USD; positions under INSIDER_MIN_POSITION_USD = $5,000 or without a known entry price are never scored).
| Threshold | Setting | Default | Effect |
|---|---|---|---|
| Listing | INSIDER_SCORE_MIN | 50 | shown on Insiders, Pulse and market pages |
| Alert | ALERT_INSIDER_SCORE | 70 | a new flag at or above this goes to the alert feed |
Positions are re-scored on every scan, so a listed flag’s numbers move while the position is open. A flag that falls below 50 leaves the list but keeps its record.
2.5Outcome tracking
source apps/api/src/jobs/resolutions.ts
Every 15 minutes the resolutions job re-checks markets that are past their end date or have dropped out of the synced set for 30 minutes. When Polymarket reports a market closed with a winner, every unsettled flag on it is settled: resolvedCorrect = true if the flagged outcome won, false if it lost. Until then the field is null and the flag reads open. The Insiders screen shows Correct / Wrong and can filter to settled flags, so the record of the flags themselves can be checked rather than taken on trust.
2.6What a flag is not
Insider-pattern flags are statistical patterns in public on-chain data (account age, size, focus, entry price, timing) — not accusations of wrongdoing. A flag does not identify a person. Large, late, cheap positions from new wallets are often just confident traders, hedgers or market makers moving to a fresh address.
Statistical pattern, not an accusation.
3Smart Money Flow
source apps/api/src/analytics/smartFlow.ts
Smart Money Flow is the net dollar direction of sharp wallets — SharpScore ≥ 70 (SMART_SCORE_MIN) — in one market over one window. Every trade is signed relative to the market’s primary outcome (outcome 0, usually “Yes”):
| Trade by a sharp wallet | Direction |
|---|---|
| BUY the primary outcome | +1 bullish |
| SELL the other outcome | +1 bullish |
| SELL the primary outcome | −1 bearish |
| BUY the other outcome | −1 bearish |
| outcome unknown | 0 ignored |
bull = Σ USD of bullish trades by sharp wallets
bear = Σ USD of bearish trades by sharp wallets
netUsd = bull − bear
score = 100 × (bull − bear) / (bull + bear) −100 … +100, rounded to 0.1
0 when bull + bear = 0
example: $30,000 bullish, $10,000 bearish → netUsd +$20,000, score +50| Score | As shown | Reads as |
|---|---|---|
| −100 | −$40.0k | $0 bullish vs. $40k bearish — every sharp dollar against the primary outcome |
| −50 | −$20.0k | $10k bullish vs. $30k bearish |
| 0 | $0 | balanced, or no sharp volume at all |
| +50 | +$20.0k | $30k bullish vs. $10k bearish |
| +100 | +$40.0k | $40k bullish vs. $0 bearish — every sharp dollar for the primary outcome |
- Every sharp trade on the tape counts, not only those stored individually: flow is accumulated in the 1-minute bars (§5).
- A wallet counts as sharp once it has been scored and its SharpScore is ≥ 70 at the time of the trade. Sharp buyers and sellers are distinct sharp addresses buying or selling in the window.
- A 1-hour net flow of at least $25,000 with |score| ≥ 50 raises a smart-flow alert.
4Whales
source apps/api/src/analytics/whale.ts
A single fill on the tape is a whale trade when either rule holds:
- its value is ≥
WHALE_TRADE_USD= $10,000; or - its value is ≥
WHALE_MIN_USD= $1,000 and at or above that market’s running 99th-percentile trade size (WHALE_PERCENTILE= 99).
The percentile rule catches trades that are large for a thin market; the $1,000 floor stops illiquid markets producing $40 “whales”. The 99th percentile is estimated per market without storing trades — a streaming quantile in log space (stochastic gradient on the pinball loss), checked before each trade updates it:
x = ln(trade value in USD)
q ← q + η · p if x > q p = 0.99
q ← q − η · (1 − p) otherwise η = 0.1
q₀ = ln($10,000)
whale ⇔ value ≥ $10,000 or (value ≥ $1,000 and value ≥ e^q)On the Whales screen a whale is a position, not a trade: a holder whose position in one market is worth ≥ $10,000 (WHALE_POSITION_USD), from the holder scan in §2.4. A wallet carries the whale tag when its open positions are worth ≥ $100,000 or it holds a whale position.
5Windows and freshness
source apps/api/src/jobs/marketsAggregate.ts
Screener metrics come in five rolling windows: 30m, 1h, 6h, 12h and 24h. Every trade on the tape is rolled into a per-market 1-minute bar — volume, trade count, buy/sell split, whale counts and volume, the set of traders, sharp buyers and sellers, sharp bullish and bearish dollars, and the closing price. A window is the sum of the bars inside it; unique-trader counts are distinct addresses across those bars, not sums. Bars are kept for 26 hours.
Price changes come from a price tick recorded for every market on each market sync (every 2 minutes, kept 8 days); Polymarket’s own 1h/24h change is the fallback until enough ticks exist.
5.1Update cadence
| Job | Schedule | Refreshes |
|---|---|---|
| trades-ingest | every 15 s | trade tape → 1-minute bars, stored trades, whale trades, alerts |
| markets-aggregate | every minute | 30m and 1h windows each run; 6h, 12h, 24h every 5 minutes (short windows act as lower bounds in between) |
| markets-sync | every 2 min | market list, prices, price ticks, categories |
| traders-refresh | every minute | wallet stats and SharpScore, 40 wallets per run: hot wallets every 30 min, others every 6 h, dormant (> 30 d) every 24 h |
| traders-rank | every 10 min | leaderboard rank, SharpScore re-score (recency), tags |
| whales-insiders | every 5 min | whale positions, Z-scores, insider-pattern flags |
| resolutions | every 15 min | closed markets, winners, resolvedCorrect |
| alerts-dispatch | every 30 s | Telegram and X delivery |
| traders-seed | every 6 h | wallet universe from Polymarket leaderboards |
| prices-backfill | daily 04:00 UTC | 24 h of CLOB price history for the top 200 markets |
“Hot” wallets are the top 500 by rank, favourited wallets and wallets that traded in the last 24 hours. The API caches public responses for 15 seconds and Pulse polls every 15 seconds. Every list carries asOf, the last successful run of the job behind it; the status strip switches from LIVE to DELAYED when data is more than 2 minutes old.
5.2Warm-up after deploy
On a fresh deploy the worker runs market sync, trader seed, tape ingest and aggregation once, in that order, then backfills prices if fewer than 5,000 price ticks exist. Because windows are built from Sharpside’s own bars, the 30m and 1h windows are complete after an hour, while 6h, 12h and 24h volume and trader counts fill in over the first day. The first full SharpScore pass over ~3,000 seeded wallets takes 2–3 hours; until wallets are scored, Smart Money Flow and sharp counts read near zero.
5.3Stored trades
The tape runs at roughly 1,500–2,000 trades a minute. Every trade feeds the bars, but only trades ≥ STORE_TRADE_MIN_USD = $100 are stored individually, for 14 days — about 7% of trades and 95% of volume. The Activity feed therefore starts at $100.
6Data sources
source docs/POLYMARKET_DATA.md
| Source | Host | Used for |
|---|---|---|
| Gamma | gamma-api.polymarket.com | markets, outcomes, prices, end dates, tags → categories, resolutions |
| Data API | data-api.polymarket.com | global trade tape, open and closed positions, holders, first activity (account age), portfolio value, markets traded, open interest, leaderboards |
| CLOB | clob.polymarket.com | price history |
| user-pnl | user-pnl-api.polymarket.com | cumulative PnL curve → drawdown, PnL charts |
All four are public endpoints: no API keys, no private data. Requests share one budget of 8 per second across all jobs. Sharpside is independent and not affiliated with Polymarket.
7Limitations
- Hot-set market sync.Polymarket lists ~260,000 “active” markets, most with no volume. Sharpside syncs the top 2,000 by 24-hour volume plus every market that appears on the trade tape — about 2,500 in practice. A market that never trades is not listed.
- Closed positions are sampled.The newest 500 closed positions per wallet are read. Win rate, gains, losses and the sample component are exact for wallets with up to 500 closed positions and “most recent 500” for larger ones.
- No cash balance.A wallet’s USDC balance (
currentBalance) is not available from public APIs and is always empty. Open value is the marked-to-market value of open positions. - Leaderboard PnL is Polymarket’s.All-time, monthly and weekly PnL and volume come from Polymarket’s leaderboard as reported. Sharpside does not recompute them, and inherits any error in them.
- Z-scores use visible holders.At most 500 holders per outcome are visible, so σ is over that set (§2.2).
- The sharp set lags.Smart Money Flow counts a wallet only once it has been scored; a new sharp wallet is invisible until its refresh.
8Not financial advice
Sharpside describes what has happened on Polymarket. Nothing on the site is a recommendation to buy, sell or hold anything. A high SharpScore describes a wallet’s past record, not its next trade, and an insider-pattern flag is not a signal to follow. Prediction-market positions can lose their full stake.
Free. Not financial advice. Not affiliated with Polymarket.