The pipeline in one paragraph
Every few hours we read posts and comments from nine stock-market subreddits. Ticker symbols are extracted from the text and validated against the SEC registry. Each (item, ticker) pair is classified by a language model — direction, what the author is doing, and how clear the signal is. Each pair then gets a weight derived from upvotes, and every number on this site is some combination of those weights and directions. Nothing is hand-tuned per ticker; the same arithmetic runs on all of them.
Vocabulary
- Item
- One post or one comment. Posts and comments are scored the same way but normalised differently, because posts collect more upvotes simply by appearing in feeds.
- Mention
- One (item, ticker) pair — a single text saying something about a single stock. A post naming four tickers produces four mentions. Most come from the symbol appearing in the text; the rest are attributed by the full-thread pass below, which reads a whole conversation and can credit a comment that never typed the ticker. Mentions on items with fewer than 2 upvotes are excluded from every metric; they stay in the database and re-enter automatically if they gain votes.
- Window
- 24h, 7d or 30d. Everything on the board is computed within the selected window — including trend and heat, so 24h shows what is hot today and 30d what has been hot this month.
- Kind
- What the author is doing about the ticker, which decides how much the mention counts. Recommending is the real signal; a headline that happens to name a company is weak evidence anyone likes it.
- Conviction
- The model's confidence in its read of one mention, 0–1. Used both as the magnitude of the sentiment value and to split an item's weight between the tickers it names.
- Theater
- An item that exists as a spectacle — a joke, stunt or public wager — so its upvotes measure entertainment rather than agreement. Only applied by the full-thread pass, which reads the replies; a stunt post looks like substance in isolation.
- Full-thread pass
- When a post — or any single comment inside it — reaches 1,000 upvotes, the whole thread goes to the model in conversation order, numbered and with reply depth, and every item in it is judged against the thread's ticker roster. This reads what a comment alone cannot: a reply of "they were the only ones with the facilities" is about the company the thread is about, and a stunt only reveals itself next to the replies. So the pass can attribute a mention to an item that never typed the symbol, and remove one where the symbol turned out to be an ordinary word. A thread is read once, after its comments have been collected: re-reading one as it grows costs a whole transcript again and moves almost nothing.
Weight — the unit everything is built from
A mention's weight is how much evidence it contributes. Upvotes enter under a square root so one viral post cannot drown organic consensus, and the floor means a zero-upvote mention still counts for something.
Neutral items carry no upvotes. A verdict of neutral says the author took no side, so the votes under it measure attention rather than agreement — a 2,400-upvote "priced in, lol" is a room enjoying a joke, not a room taking a view. It still counts as a mention, and it still shows in the ticker's list, but it enters at the floor and its upvotes are left out of the ticker's upvote total.
type_median puts posts and comments on one scale — the median post earns about four times the median comment purely through reach, so scoring them on raw upvotes would count visibility as conviction.
| post | 22 upvotes | median, used as the divisor for posts |
| comment | 5 upvotes | median, and the reference scale everything is expressed in |
kind_weight — what the author was doing:
| recommendation | 1.0 | telling others to buy, sell or hold, or making a forward-looking call |
| analysis | 0.7 | arguing a case about the company or chart, with a view |
| position | 0.3 | describing what they own — exposure, not advice |
| news | 0.3 | reporting a fact with no view of their own |
| question | 0.1 | asking rather than asserting |
| theater_factor | 0.05 | applied on top when the item is a spectacle |
share splits one item's weight across the tickers it names. An author listing fourteen picks is not fourteen separate people, so an item naming n tickers is worth √n items, and that total is divided by conviction squared — so the names singled out with confidence take visibly more than the ones hedged on.
The metrics
- Sentiment −1 bearish … +1 bullish
- The upvote-weighted mean opinion, where each mention's value s is its
direction (+1, −1 or 0) times its conviction.
sentiment = Σ(w · s) ÷ ΣwIt is an average, so more mentions do not push it up. Near zero means divided or factual, not ignored — check Mentions to see how much stands behind it.
- Confidence 0 … 1
- How much evidence stands behind a ticker's sentiment, on a self-scaling curve.
confidence = Σw ÷ (Σw + 40)Not shown as its own column, but it is what stops a single enthusiastic comment from topping the board.
- Popularity quadrant y-axis
- popularity = log₁₀(1 + Σ upvotes)Total attention on a log scale, so a 10,000-upvote day sits one step above a 1,000-upvote one rather than ten times higher.summed over items that took a side — see Weight
- Trend −5 … +5
- How unusual this window's discussion is for this ticker, against the 14
days before it, measured in weight rather than head-count — a surge has to be paid for
in upvotes.
trend = (window_mean_w + 0.3 − baseline_mean) ÷ σ × coverageDirection-blind: a spike can be a crash. It reads 0 when there is no observed history to compare against — judged against unscanned silence, everything would look like a surge.σ floored at 1 · result clipped to ±5 · coverage = observed baseline days ÷ 14
- Heat −1 … +1, a little beyond when surging
- "Loved in this window": sentiment discounted by the evidence behind it, then
boosted if the window is a genuine surge over the ticker's own past.
heat = sentiment × confidence × (1 + ln(1 + max(trend, 0)) × confidence) × consistencyThree dampers, for three different failure modes. Multiplying the boost by confidence stops thin tickers running away with it — a ticker going from nothing to five mentions posts a huge z-score precisely because it has no history. Taking the logarithm of the surge stops it swamping the opinion it is supposed to be modifying: linear in z the multiplier reached 6×, enough for a middling sentiment with a big spike to outrank a genuinely well-liked stock, and since z is clipped at ±5 everything extreme saturated at the same ceiling. Multiplying by consistency stops one loud afternoon crowning a ticker: a single viral thread posts a maxed-out surge and a large weight, while consistency already knows the whole story happened in a few hours. Negative trends cannot flip the sign, so sorting ascending gives you "recently hated".the boost is logarithmic in the z-score, so the multiplier tops out near 2.8× · the consistency term is dropped in the 24h window, where spread across days has no meaning
- Runway the default sort — enthusiasm vs headroom
- Heat, discounted twice: once because large companies are hard to move, once because
a boom that already happened is potential already spent.
runway = ∛( heat × room × cooldown )room = 1 ÷ (1 + max(0, log₁₀(market_cap ÷ $2B)) ÷ 2)cooldown = 1 ÷ (1 + surge ÷ 0.5)The cube root is the geometric mean of the three ingredients: multiplying three fractions crushes everything toward zero, and this restores the spread without changing any ticker's rank. Blank when market data is missing, and withheld entirely below a $50M market cap, where "room to grow" is meaningless and pumping lives. A description of enthusiasm against headroom, not a prediction.surge = the largest age-decayed positive return across 7d, 30d, 90d, 180d, 1y and 3y — each return × 0.5^(days ÷ 365), so a year-old run counts half
- Mentions/day
- The sparkline: how many posts and comments named this ticker on each day of the window. Discussion volume — not price.
- Price move
- The share price across the same window as everything else in the row, so
the market's move sits beside the discussion rather than under a fixed horizon that
would not line up with it. Daily closes, which is why the span is measured in trading
days — roughly six for a 7d window and twenty-three for 30d. A 24h window has too few
closes to draw a line, so it shows the day's change as a number alone.
Nothing here is inferred from this: it is drawn beside the sentiment columns precisely so you can judge for yourself whether the talk led the price, followed it, or had nothing to do with it.
One deliberate inconsistency
The charts plot a different sentiment from the tables. A daily point is pulled toward the level established by the days before it, in proportion to how little backs that day:
A table figure sits beside its own mention count, so you can see for yourself how thin it is. A lone point on a line chart says nothing of the sort, and would be drawn as emphatically as a day standing on twenty comments. Pulling toward the trailing level rather than toward zero matters too: zero would drag the line down whenever chatter thinned, making falling volume look like souring mood. It is strictly backward-looking, so no day is informed by its own future.
Constants in force
| Minimum upvotes | 2 | below this a mention is excluded from every metric |
| Evidence prior (heat) | 40 | weight a ticker needs before its sentiment is taken at face value |
| Evidence prior (daily) | 5 | the same idea for a single day on a chart |
| Theater weight | 0.05 | multiplier for spectacle |
| Trend baseline | 14 days | the period a surge is judged against |
| Market-cap knee | $2B | full room at or below this |
| Market-cap floor | $50M | no runway score below this |
| Surge half-point | +50% | a run this size halves the cooldown factor |
| Surge half-life | 365 days | how fast an old boom stops counting |
| Thread-pass threshold | 1,000 upvotes | a post, or one comment in it, this loud gets the whole thread read once |
| Tracking window | 7 days | how long a post's engagement keeps being re-measured |
What this cannot tell you
It measures talk, not truth. A ticker with glowing sentiment is one that Reddit likes today. Crowds are wrong often, and loudest near tops.
The population is nine subreddits, skewed toward retail, options and speculation. It is not "the market", and it is not a survey.
Classification is automated and gets things wrong — sarcasm, in-jokes, and tickers that collide with ordinary words. Where it matters most, the loudest threads are read whole and in order, which catches some of it, but errors survive in the long tail.
Trend needs history. A ticker we have only just started seeing reads 0, not "no surge".
Every figure links back to the posts and comments underneath it. If a number looks wrong, open the ticker page and read the evidence — that path exists because you should not have to take any of this on faith.