Tutorial

How to Build a Reddit Stock Sentiment Scanner

Scan r/wallstreetbets and finance subreddits for stock mentions and sentiment signals using Scavio Reddit API. Python pipeline at $0.005/query.

Reddit finance communities like r/wallstreetbets, r/stocks, and r/investing surface retail sentiment hours before it shows up in price action. This scanner uses the Scavio Reddit search endpoint to pull recent discussions mentioning stock tickers, scores them by sentiment and engagement, and outputs a ranked watchlist. Each subreddit scan costs $0.005.

Prerequisites

  • Python 3.8+
  • requests library
  • A Scavio API key from scavio.dev
  • Target tickers or stock-related keywords

Walkthrough

Step 1: Set up the Reddit stock scanner

Configure the scanner with target subreddits and ticker extraction.

Python
import os, requests, re
from collections import defaultdict

API_KEY = os.environ['SCAVIO_API_KEY']
SH = {'x-api-key': API_KEY, 'Content-Type': 'application/json'}

SUBREDDITS_QUERIES = ['wallstreetbets stock', 'stocks investing', 'investing portfolio']
TICKER_PATTERN = re.compile(r'\b[A-Z]{2,5}\b')
COMMON_WORDS = {'THE', 'AND', 'FOR', 'ARE', 'BUT', 'NOT', 'YOU', 'ALL', 'CAN', 'HER',
                'WAS', 'ONE', 'OUR', 'OUT', 'HAS', 'ITS', 'HIS', 'HOW', 'MAY', 'NEW'}

def extract_tickers(text):
    found = TICKER_PATTERN.findall(text)
    return [t for t in found if t not in COMMON_WORDS and len(t) >= 2]

print('Reddit stock scanner configured.')

Step 2: Scan Reddit for stock discussions

Search Reddit finance communities and extract ticker mentions with context.

Python
def scan_reddit(query):
    data = requests.post('https://api.scavio.dev/api/v1/search',
        headers=SH, json={'query': query, 'platform': 'reddit', 'country_code': 'us'}).json()
    results = data.get('organic_results', [])[:15]
    mentions = defaultdict(list)
    for r in results:
        text = f"{r.get('title', '')} {r.get('snippet', '')}"
        tickers = extract_tickers(text)
        for t in tickers:
            mentions[t].append({'title': r.get('title', '')[:80],
                'snippet': r.get('snippet', '')[:120], 'link': r.get('link', '')})
    return mentions

all_mentions = defaultdict(list)
for q in SUBREDDITS_QUERIES:
    mentions = scan_reddit(q)
    for ticker, posts in mentions.items():
        all_mentions[ticker].extend(posts)
    print(f'  {q}: {len(mentions)} tickers found')
print(f'Total unique tickers: {len(all_mentions)}')

Step 3: Score tickers by sentiment and volume

Assign sentiment scores based on context keywords and rank by mention volume.

Python
BULLISH = ['buy', 'moon', 'calls', 'bullish', 'undervalued', 'squeeze', 'breakout', 'long']
BEARISH = ['sell', 'puts', 'bearish', 'overvalued', 'crash', 'short', 'dump', 'avoid']

def score_ticker(ticker, posts):
    bull = bear = 0
    for p in posts:
        text = f"{p['title']} {p['snippet']}".lower()
        bull += sum(1 for w in BULLISH if w in text)
        bear += sum(1 for w in BEARISH if w in text)
    total = bull + bear or 1
    sentiment = (bull - bear) / total
    return {'ticker': ticker, 'mentions': len(posts), 'bullish': bull,
            'bearish': bear, 'sentiment': round(sentiment, 2)}

scored = [score_ticker(t, p) for t, p in all_mentions.items()]
scored.sort(key=lambda x: x['mentions'], reverse=True)

print(f'\nTop tickers by mention volume:')
for s in scored[:10]:
    signal = 'BULL' if s['sentiment'] > 0.3 else 'BEAR' if s['sentiment'] < -0.3 else 'NEUTRAL'
    print(f'  ${s["ticker"]:5} | {s["mentions"]:3} mentions | sentiment: {s["sentiment"]:+.2f} | {signal}')

Step 4: Generate a daily watchlist

Filter high-signal tickers and output a ranked watchlist.

Python
def generate_watchlist(scored, min_mentions=2):
    watchlist = [s for s in scored if s['mentions'] >= min_mentions]
    watchlist.sort(key=lambda x: abs(x['sentiment']) * x['mentions'], reverse=True)
    cost = len(SUBREDDITS_QUERIES) * 0.005
    print(f'\n=== Reddit Stock Watchlist ({len(watchlist)} tickers) ===')
    print(f'Cost: ${cost:.3f} ({len(SUBREDDITS_QUERIES)} queries)')
    for i, s in enumerate(watchlist[:15], 1):
        signal = 'BULL' if s['sentiment'] > 0.3 else 'BEAR' if s['sentiment'] < -0.3 else 'MIXED'
        print(f'  {i:2}. ${s["ticker"]:5} | {s["mentions"]:3}x | {signal:7} | score: {s["sentiment"]:+.2f}')
    return watchlist

watchlist = generate_watchlist(scored)

Python Example

Python
import os, requests, re
from collections import defaultdict
SH = {'x-api-key': os.environ['SCAVIO_API_KEY'], 'Content-Type': 'application/json'}
TICKER_RE = re.compile(r'\b[A-Z]{2,5}\b')
SKIP = {'THE','AND','FOR','ARE','NOT','YOU','ALL','CAN','HAS','NEW'}

def scan(query):
    data = requests.post('https://api.scavio.dev/api/v1/search',
        headers=SH, json={'query': query, 'platform': 'reddit', 'country_code': 'us'}).json()
    tickers = defaultdict(int)
    for r in data.get('organic_results', [])[:10]:
        for t in TICKER_RE.findall(f"{r.get('title','')} {r.get('snippet','')}"):
            if t not in SKIP: tickers[t] += 1
    for t, c in sorted(tickers.items(), key=lambda x: -x[1])[:5]:
        print(f'  ${t}: {c} mentions')

scan('wallstreetbets stock picks')

JavaScript Example

JavaScript
const SH = { 'x-api-key': process.env.SCAVIO_API_KEY, 'Content-Type': 'application/json' };
async function scan(query) {
  const data = await fetch('https://api.scavio.dev/api/v1/search', {
    method: 'POST', headers: SH,
    body: JSON.stringify({ query, platform: 'reddit', country_code: 'us' })
  }).then(r => r.json());
  const tickers = {};
  const skip = new Set(['THE','AND','FOR','ARE','NOT','YOU','ALL','CAN','HAS','NEW']);
  for (const r of (data.organic_results || []).slice(0, 10)) {
    const text = `${r.title || ''} ${r.snippet || ''}`;
    for (const m of text.matchAll(/\b[A-Z]{2,5}\b/g)) {
      if (!skip.has(m[0])) tickers[m[0]] = (tickers[m[0]] || 0) + 1;
    }
  }
  Object.entries(tickers).sort((a,b) => b[1]-a[1]).slice(0,5)
    .forEach(([t,c]) => console.log(`  $${t}: ${c} mentions`));
}
scan('wallstreetbets stock picks').catch(console.error);

Expected Output

JSON
  wallstreetbets stock: 8 tickers found
  stocks investing: 6 tickers found
  investing portfolio: 5 tickers found
Total unique tickers: 14

Top tickers by mention volume:
  $NVDA  |  7 mentions | sentiment: +0.65 | BULL
  $TSLA  |  5 mentions | sentiment: -0.40 | BEAR
  $AAPL  |  4 mentions | sentiment: +0.33 | BULL
  $AMD   |  3 mentions | sentiment: +0.50 | BULL
  $SPY   |  3 mentions | sentiment: +0.20 | NEUTRAL

=== Reddit Stock Watchlist (8 tickers) ===
Cost: $0.015 (3 queries)

Related Tutorials

Frequently Asked Questions

Most developers complete this tutorial in 15 to 30 minutes. You will need a Scavio API key (free tier works) and a working Python or JavaScript environment.

Python 3.8+. requests library. A Scavio API key from scavio.dev. Target tickers or stock-related keywords. A Scavio API key gives you 250 free credits per month.

Yes. The free tier includes 250 credits per month, which is more than enough to complete this tutorial and prototype a working solution.

Scavio has a native LangChain package (langchain-scavio), an MCP server, and a plain REST API that works with any HTTP client. This tutorial uses the raw REST API, but you can adapt to your framework of choice.

Start Building

Scan r/wallstreetbets and finance subreddits for stock mentions and sentiment signals using Scavio Reddit API. Python pipeline at $0.005/query.