Skip to content

Latest commit

 

History

History
201 lines (124 loc) · 7.5 KB

File metadata and controls

201 lines (124 loc) · 7.5 KB

Quantarded - WSB Scoring Algorithm (v1)

This document describes the WSB (WallStreetBets) signal algorithm.

It focuses on short-term attention and sentiment dynamics and is optimized for intraweek signals. It intentionally ignores fundamentals, price action, and longer-term positioning.

What's new in v1

v0 worked well, but it could feel "jumpy" when checking the endpoint throughout the day. Two small changes make the results noticeably more stable without changing the core logic:

  1. Mixed recency decay: instead of a single half-life, we mix a fast and a slow exponential decay. The fast component keeps the list reactive to fresh chatter, while the slow component adds inertia so weekly leaders do not get replaced by short bursts.

  2. Deterministic confidence: the public-facing confidence value is now a deterministic normalization of the score. In v0, it included a small time-based jitter, which made results appear to change every few minutes even when the underlying ranking did not.

Everything else (weekly structure, imbalance, direction separation, volume hygiene) stays the same.

Data we start from

All signals come from r/wallstreetbets events that we ingest at creation time. Each event represents either:

  • a Reddit submission, or
  • a Reddit comment

Upstream, we extract tickers and classify sentiment (buy, sell, neutral) per event. By the time data reaches this pipe, we deliberately do not care about:

  • Reddit upvotes
  • edits
  • author metadata
  • LLM confidence scores

Those signals are either incomplete, gameable, or misleading at ingestion time. What we keep is simple:

  • timestamp
  • event type (submission or comment)
  • ticker
  • sentiment

This simplicity is a feature, not a limitation.

Weekly structure

All scoring is done inside ISO weeks. A week starts on Monday and ends on Sunday, ISO-style. Each event is bucketed into the week it was created in.

This gives us:

  • clean weekly snapshots
  • predictable resets
  • the ability to talk about “this week’s picks” without hand-waving

Scores are recomputed continuously as the week progresses. Early-week signals fade naturally as new data comes in.

How individual events are weighted

Not all mentions are equal, and not all mentions should age the same way.

Recency comes first

The most important assumption in the system is that what people said in the last few hours matters more than what they said two days ago.

In v1 we still use exponential decay, but we mix two time-scales:

  • a fast half-life (default: 12h) to stay reactive
  • a slow half-life (default: 72h) to add inertia during the week
  • a mixing factor (default: 0.75) that controls how much weight goes to the fast component

Concretely, each event gets:

recency_w = fast_weight * exp(-ln(2) * age_hours / fast_half_life_hours) + (1 - fast_weight) * exp(-ln(2) * age_hours / slow_half_life_hours)

This keeps the feed responsive to real shifts on WSB, but reduces the chance that a short burst of fresh comments completely rewrites the top 5 every hour. It also makes the Sunday snapshot read more like "how the week went" instead of "what happened in the last few minutes".

Submissions vs comments

Submissions get a small boost over comments, not because they are “better”, but because:

  • they require more intent and effort
  • they usually anchor discussion rather than react to it

The multiplier is intentionally small. Comments still matter a lot.

Final per-event weight

At the end of the day, each (event, ticker) pair contributes a single number:

event_weight = recency_weight × event_type_multiplier

No hidden adjustments. No magic.

Aggregation at the ticker level

Once all events are weighted, we aggregate per ticker inside the week. At this stage we compute:

  • total weighted volume
  • number of distinct events
  • weighted volume split by sentiment (buy, sell, neutral)

Neutral mentions count toward attention, but not toward direction.

This distinction matters later.

Absolute volume vs relative attention

Absolute counts alone are misleading. A ticker with 50 mentions might be dominant in a quiet week, or irrelevant in a noisy one. For that reason, we explicitly compute relative attention share:

“Out of all WSB attention this week, what fraction belongs to this ticker?”

This allows us to compare signals within the same week, which is all we actually care about. Cross-week comparisons are intentionally not the goal of this algorithm.

Buy vs sell imbalance

This is one of the most important parts of the model. We do not reward raw bullishness or bearishness, we reward imbalance.

If a ticker is:

  • 50% buy / 50% sell → weak signal
  • 90% buy / 10% sell → strong signal
  • 95% sell with real volume → very strong (negative) signal

Mathematically, we compute an imbalance ratio that goes from 0 to 1. A small floor is applied so that ties do not completely zero out the score, but they are heavily penalized. This avoids:

  • overreacting to polarized discussions
  • treating divided sentiment as conviction

Direction is separate from strength

Direction is simple:

  • buy volume > sell volume → buy
  • sell volume > buy volume → sell
  • tie → no signal

Strength is everything else, this separation is intentional: it allows us to talk about “strong sell signals” and “weak buy signals” without confusion.

Putting it all together: the score

The final score is built from three components:

  1. Relative attention share
  2. Absolute activity (log-scaled to avoid domination by spammy volume)
  3. Recency-weighted volume

These are combined into a base magnitude, then:

  • scaled by the buy/sell imbalance
  • signed by direction

The result is a single signed number:

  • positive = buy
  • negative = sell
  • magnitude = conviction

Internally, this is what we rank on.

What we expose publicly (and why)

We do not expose the raw score directly. Instead, the final node exposes:

  • sentiment: buy or sell (derived from the buy vs sell imbalance)
  • confidence: a 0..1-ish number that is simply the score normalized within the current week

Normalization is done relative to the strongest absolute score in the result set for that week, with a conservative cap (so the UI does not show false precision).

In v1, confidence is fully deterministic. v0 added a tiny time-based jitter to reduce "tie-looking" outputs, but in practice it made the endpoint feel unstable when checking it repeatedly. Removing the jitter makes the list move only when the underlying data and weighted totals actually move.

What this algorithm is not trying to be

It is not:

  • a price model
  • a trading strategy
  • an optimized backtest engine
  • a claim of alpha

It is a structured way to answer:

“What is dominating attention and intent right now?”

Nothing more.

Intentional omissions

Some things are missing on purpose:

  • No Reddit upvotes
    (they are incomplete and laggy at ingestion time)

  • No LLM confidence
    (not a real signal, just model self-assessment)

  • No user weighting
    (opaque, gameable, and hard to defend)

  • No market or price data
    (keeps the signal orthogonal and interpretable)

If we ever add these, it will be because we can clearly justify the trade-off.

Final note

This algorithm is deliberately conservative. It is easier to add complexity later than to remove it once the system starts lying to you. If you change something here, the right question to ask is not:

“Does this improve performance?”

but:

“Does this make the signal more honest?”

That question should always win.