Sentiment & NLP·Sentiment-Based Signals·Intermediate

Influencer Impact Analysis

Quantitatively measure the short-term market price and volume impact of influential cryptocurrency social media accounts by analyzing price movements and trading volume surges in the minutes and hours following high-engagement posts and viral crypto content.

sentimentsentiment-analysis

Influencer Impact Analysis — Sentiment & NLP

Category: Sentiment & NLP | Subcategory: Signals


What This Notebook Does

In crypto markets, a single tweet from a high-follower account can move price by 5–15% within minutes. This notebook quantifies influencer market impact — measuring how specific accounts, post types, and sentiment directions affect short-term price movement.

This notebook:

  1. Loads scraped influencer post data (from Notebook 113/114) and OHLCV price data
  2. Categorizes influencers by tier (mega, macro, micro) based on follower count
  3. Measures price impact in the 1h, 4h, 24h, and 72h windows after each post
  4. Classifies post sentiment (bullish, bearish, neutral) using VADER
  5. Runs event-study analysis — average cumulative abnormal return (CAR) by influencer
  6. Builds an influencer impact score for use in live trading signal generation
  7. Visualizes impact distributions and per-account statistics

The Event Study Framework

Borrowed from academic finance, an event study measures the abnormal return around a specific event:

Abnormal Return(t) = Actual Return(t) - Expected Return(t)
Expected Return   = average return over a 7-day pre-event window
CAR               = cumulative sum of abnormal returns over [0, T] hours

By averaging CAR across many posts by the same influencer, we estimate their true average market impact, filtered from background noise.

Prerequisites

  • Post data CSV from Notebook 113 (reddit_crypto_scraper) or 114 (telegram_channel_monitor)
  • Hourly OHLCV CSV for BTC or relevant asset
  • Or use the synthetic generator in Section 2
[1]
!pip install pandas numpy matplotlib seaborn scipy vaderSentiment --quiet
[?25l   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 0.0/126.0 kB ? eta -:--:--
   ━━━━━━━━━━━━━━━━━━━━━━━━━━╺━━━━━━━━━━━━━ 81.9/126.0 kB 2.3 MB/s eta 0:00:01
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 126.0/126.0 kB 2.0 MB/s eta 0:00:00
[?25h
[2]
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy import stats
from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
from datetime import datetime, timedelta, timezone
import warnings

warnings.filterwarnings('ignore')
%matplotlib inline
plt.rcParams['figure.figsize'] = (13, 5)
plt.rcParams['axes.spines.top'] = False
plt.rcParams['axes.spines.right'] = False
sns.set_palette('husl')

VADER = SentimentIntensityAnalyzer()
print('Imports ready.')
Imports ready.

Section 2 — Configuration & Data Loading

[3]
# ── CONFIGURATION ─────────────────────────────────────────────────────────────
IMPACT_WINDOWS_HOURS = [1, 4, 24, 72]   # hours after post to measure price impact
PRE_EVENT_WINDOW     = 7 * 24           # hours before post for expected return baseline
MIN_POSTS_FOR_ANALYSIS = 5             # minimum posts per influencer to include

INFLUENCER_TIERS = {
    'mega':  1_000_000,   # followers >= 1M
    'macro':   100_000,   # followers >= 100K
    'micro':    10_000,   # followers >= 10K
    'nano':          0,   # all others
}
# ─────────────────────────────────────────────────────────────────────────────


def generate_synthetic_posts(n_influencers: int = 8, posts_per: int = 20, seed: int = 42) -> pd.DataFrame:
    """
    Generate synthetic influencer post data for pipeline testing.

    Parameters
    ----------
    n_influencers : int
        Number of unique influencer accounts to simulate.
    posts_per : int
        Average posts per influencer (Poisson-distributed).
    seed : int
        Random seed.

    Returns
    -------
    pd.DataFrame
        Columns: author, followers, timestamp, text, platform.
        Timestamps span the last 90 days.
    """
    np.random.seed(seed)
    accounts = [
        {'author': f'influencer_{i}',
         'followers': int(np.random.choice([5_000_000, 800_000, 200_000, 50_000, 15_000], p=[0.1, 0.15, 0.25, 0.25, 0.25])),
         'platform': np.random.choice(['twitter', 'telegram', 'reddit'])}
        for i in range(n_influencers)
    ]

    bullish_texts = [
        'BTC breaking out — accumulate now',
        'ETH to new ATH this cycle, no doubt',
        'Massive buy signal just triggered',
        'This is the dip to buy, trust the process',
    ]
    bearish_texts = [
        'Crypto market looking very weak, reduce exposure',
        'BTC rejection at resistance — could see 30% drop',
        'SEC crackdown coming, sell the news',
        'Bearish divergence on daily — be careful',
    ]
    neutral_texts = [
        'Interesting on-chain data this week',
        'Market consolidating — patience is key',
        'Long thread on Layer 2 scaling solutions',
    ]

    records = []
    now = datetime.now(tz=timezone.utc)
    for acc in accounts:
        n_posts = max(MIN_POSTS_FOR_ANALYSIS, np.random.poisson(posts_per))
        for _ in range(n_posts):
            hours_ago = np.random.uniform(0, 90 * 24)
            sentiment_choice = np.random.choice(['bullish', 'bearish', 'neutral'], p=[0.45, 0.35, 0.20])
            text = np.random.choice(
                bullish_texts if sentiment_choice == 'bullish'
                else (bearish_texts if sentiment_choice == 'bearish' else neutral_texts)
            )
            records.append({
                'author':    acc['author'],
                'followers': acc['followers'],
                'platform':  acc['platform'],
                'timestamp': now - timedelta(hours=hours_ago),
                'text':      text,
            })

    df = pd.DataFrame(records).sort_values('timestamp').reset_index(drop=True)
    print(f'Generated {len(df)} posts from {n_influencers} influencers.')
    return df


def generate_synthetic_ohlcv_hourly(n_hours: int = 90 * 24, seed: int = 42) -> pd.DataFrame:
    """
    Generate synthetic hourly BTC-like OHLCV data.

    Parameters
    ----------
    n_hours : int
        Number of hourly candles to generate.
    seed : int
        Random seed.

    Returns
    -------
    pd.DataFrame
        Hourly OHLCV DataFrame with DatetimeIndex.
    """
    np.random.seed(seed)
    end = datetime.now(tz=timezone.utc).replace(minute=0, second=0, microsecond=0)
    idx = pd.date_range(end=end, periods=n_hours, freq='1H')
    log_ret = np.random.randn(n_hours) * 0.005
    close   = 40000 * np.exp(np.cumsum(log_ret))
    return pd.DataFrame({
        'open':   close * (1 + np.random.randn(n_hours) * 0.001),
        'high':   close * (1 + np.abs(np.random.randn(n_hours) * 0.003)),
        'low':    close * (1 - np.abs(np.random.randn(n_hours) * 0.003)),
        'close':  close,
        'volume': np.random.exponential(1e8, n_hours),
    }, index=idx)


# ── Load or generate ──────────────────────────────────────────────────────────
USE_SYNTHETIC = True
if USE_SYNTHETIC:
    posts_df = generate_synthetic_posts(n_influencers=8, posts_per=25)
    ohlcv_df = generate_synthetic_ohlcv_hourly(n_hours=90 * 24)
else:
    posts_df = pd.read_csv('influencer_posts.csv', parse_dates=['timestamp'])
    ohlcv_df = pd.read_csv('ohlcv_hourly.csv', parse_dates=[0], index_col=0)

print(posts_df[['author', 'followers', 'platform', 'timestamp']].head())
Generated 190 posts from 8 influencers.
         author  followers  platform                        timestamp
0  influencer_5      50000    reddit 2026-03-15 03:47:50.985422+00:00
1  influencer_2      50000  telegram 2026-03-15 14:17:01.038455+00:00
2  influencer_2      50000  telegram 2026-03-15 19:05:40.626021+00:00
3  influencer_0     200000   twitter 2026-03-15 19:30:35.601585+00:00
4  influencer_3     800000    reddit 2026-03-16 01:46:20.574643+00:00

Section 3 — Post Sentiment Scoring & Influencer Tiering

[4]
def score_post_sentiment(posts_df: pd.DataFrame) -> pd.DataFrame:
    """
    Score each post's sentiment using VADER and classify as bullish/bearish/neutral.

    Parameters
    ----------
    posts_df : pd.DataFrame
        Post DataFrame with a 'text' column.

    Returns
    -------
    pd.DataFrame
        posts_df with added columns: vader_compound, post_sentiment.
        post_sentiment: 'bullish' (compound > 0.05), 'bearish' (< -0.05), 'neutral'.
    """
    df = posts_df.copy()
    df['vader_compound'] = df['text'].apply(lambda t: VADER.polarity_scores(str(t))['compound'])
    conditions = [df['vader_compound'] > 0.05, df['vader_compound'] < -0.05]
    df['post_sentiment'] = np.select(conditions, ['bullish', 'bearish'], default='neutral')
    dist = df['post_sentiment'].value_counts()
    print(f'Post sentiment: {dict(dist)}')
    return df


def assign_influencer_tiers(posts_df: pd.DataFrame, tier_thresholds: dict) -> pd.DataFrame:
    """
    Assign each influencer to a tier based on follower count.

    Parameters
    ----------
    posts_df : pd.DataFrame
        Post DataFrame with 'followers' column.
    tier_thresholds : dict
        {tier_name: minimum_followers} sorted descending by threshold.
        Example: {'mega': 1_000_000, 'macro': 100_000, 'micro': 10_000, 'nano': 0}

    Returns
    -------
    pd.DataFrame
        posts_df with added 'tier' column.
    """
    sorted_tiers = sorted(tier_thresholds.items(), key=lambda x: x[1], reverse=True)

    def get_tier(followers):
        for tier, threshold in sorted_tiers:
            if followers >= threshold:
                return tier
        return 'nano'

    df = posts_df.copy()
    df['tier'] = df['followers'].apply(get_tier)
    print(df.groupby('tier')['author'].nunique().rename('unique_accounts').to_string())
    return df


posts_df = score_post_sentiment(posts_df)
posts_df = assign_influencer_tiers(posts_df, INFLUENCER_TIERS)
Post sentiment: {'bullish': np.int64(93), 'neutral': np.int64(70), 'bearish': np.int64(27)}
tier
macro    4
mega     1
micro    3

Section 4 — Event Study: Price Impact Measurement

[5]
def compute_abnormal_return(
    post_time: pd.Timestamp,
    ohlcv_df: pd.DataFrame,
    hours_forward: int,
    pre_event_hours: int = 168
) -> float:
    """
    Compute the abnormal return for a given number of hours after a post.

    Parameters
    ----------
    post_time : pd.Timestamp
        Timestamp of the influencer post (timezone-aware).
    ohlcv_df : pd.DataFrame
        Hourly OHLCV DataFrame with a timezone-aware DatetimeIndex.
    hours_forward : int
        Hours ahead to measure price return.
    pre_event_hours : int
        Hours before the event to compute the expected (baseline) return.

    Returns
    -------
    float
        Abnormal return = actual_return - expected_return. NaN if price data unavailable.

    Notes
    -----
    Expected return is the mean hourly return over the pre-event window,
    scaled to `hours_forward` hours. This removes the baseline drift so
    that only the event-attributable price move is measured.
    """
    try:
        post_time = pd.Timestamp(post_time).tz_localize('UTC') if post_time.tzinfo is None else post_time
        target_time = post_time + timedelta(hours=hours_forward)

        pre_start = post_time - timedelta(hours=pre_event_hours)
        pre_prices = ohlcv_df.loc[pre_start:post_time, 'close']
        if len(pre_prices) < 10:
            return np.nan

        pre_returns    = pre_prices.pct_change().dropna()
        expected_return = pre_returns.mean() * hours_forward

        entry_price = ohlcv_df['close'].asof(post_time)
        exit_price  = ohlcv_df['close'].asof(target_time)
        if pd.isna(entry_price) or pd.isna(exit_price) or entry_price == 0:
            return np.nan

        actual_return   = (exit_price - entry_price) / entry_price
        return actual_return - expected_return
    except Exception:
        return np.nan


def run_event_study(
    posts_df: pd.DataFrame,
    ohlcv_df: pd.DataFrame,
    impact_windows: list
) -> pd.DataFrame:
    """
    Compute abnormal returns for each post across all impact windows.

    Parameters
    ----------
    posts_df : pd.DataFrame
        Post DataFrame with 'timestamp', 'author', 'tier', 'post_sentiment', 'followers'.
    ohlcv_df : pd.DataFrame
        Hourly OHLCV DataFrame.
    impact_windows : list of int
        Hours ahead to measure (e.g., [1, 4, 24, 72]).

    Returns
    -------
    pd.DataFrame
        posts_df with additional columns: abnormal_return_{h}h for each window.

    Notes
    -----
    This can be slow for large post counts. For 500+ posts, batch compute
    using vectorized OHLCV lookups rather than row-by-row.
    """
    df = posts_df.copy()
    print(f'Computing abnormal returns for {len(df)} posts across {len(impact_windows)} windows...')
    for h in impact_windows:
        col = f'abnormal_return_{h}h'
        df[col] = df['timestamp'].apply(
            lambda ts: compute_abnormal_return(ts, ohlcv_df, h)
        )
        valid = df[col].notna().sum()
        print(f'  {h}h window: {valid}/{len(df)} valid data points')
    return df


# ── Run event study ───────────────────────────────────────────────────────────
results_df = run_event_study(posts_df, ohlcv_df, IMPACT_WINDOWS_HOURS)
Computing abnormal returns for 190 posts across 4 windows...
  1h window: 190/190 valid data points
  4h window: 190/190 valid data points
  24h window: 190/190 valid data points
  72h window: 190/190 valid data points

Section 5 — Influencer Impact Scoring

[6]
def compute_influencer_impact_scores(
    results_df: pd.DataFrame,
    primary_window: int = 24,
    min_posts: int = 5
) -> pd.DataFrame:
    """
    Aggregate per-influencer impact statistics across all their posts.

    Parameters
    ----------
    results_df : pd.DataFrame
        Output of run_event_study() with abnormal return columns.
    primary_window : int
        The window (in hours) used as the primary impact metric for scoring.
    min_posts : int
        Minimum number of valid posts required to include an influencer.

    Returns
    -------
    pd.DataFrame
        Per-influencer summary with columns: author, tier, followers, n_posts,
        mean_impact, std_impact, t_stat, p_value, impact_score.
        impact_score is a composite metric combining effect size and statistical significance.
    """
    col = f'abnormal_return_{primary_window}h'
    groups = results_df.groupby('author')
    rows = []
    for author, grp in groups:
        valid = grp[col].dropna()
        if len(valid) < min_posts:
            continue
        mean_impact = valid.mean()
        std_impact  = valid.std()
        t_stat, p_val = stats.ttest_1samp(valid, 0)

        # Impact score = effect magnitude weighted by statistical confidence
        confidence  = 1 - min(p_val, 1.0)
        impact_score = abs(mean_impact) * confidence * np.sign(mean_impact)

        rows.append({
            'author':       author,
            'tier':         grp['tier'].iloc[0],
            'followers':    grp['followers'].iloc[0],
            'n_posts':      len(valid),
            'mean_impact':  round(mean_impact * 100, 3),
            'std_impact':   round(std_impact  * 100, 3),
            't_stat':       round(t_stat, 3),
            'p_value':      round(p_val, 4),
            'impact_score': round(impact_score * 100, 4),
        })

    score_df = pd.DataFrame(rows).sort_values('impact_score', ascending=False).reset_index(drop=True)
    print(f'Scored {len(score_df)} influencers (minimum {min_posts} posts each)')
    print(score_df.to_string(index=False))
    return score_df


def plot_impact_by_tier(
    results_df: pd.DataFrame,
    window_hours: int = 24
) -> None:
    """
    Box plot showing price impact distribution by influencer tier and sentiment direction.

    Parameters
    ----------
    results_df : pd.DataFrame
        Output of run_event_study().
    window_hours : int
        Impact window to visualize.
    """
    col = f'abnormal_return_{window_hours}h'
    plot_df = results_df.dropna(subset=[col]).copy()
    plot_df[col] = plot_df[col] * 100  # convert to percent

    fig, axes = plt.subplots(1, 2, figsize=(14, 5))

    sns.boxplot(data=plot_df, x='tier', y=col, order=['mega', 'macro', 'micro', 'nano'],
                palette='husl', ax=axes[0])
    axes[0].axhline(0, color='black', linewidth=0.8, linestyle='--')
    axes[0].set_title(f'Abnormal Return ({window_hours}h) by Influencer Tier')
    axes[0].set_ylabel('Abnormal Return (%)')

    sns.boxplot(data=plot_df, x='post_sentiment', y=col,
                order=['bullish', 'neutral', 'bearish'],
                palette=['green', 'grey', 'red'], ax=axes[1])
    axes[1].axhline(0, color='black', linewidth=0.8, linestyle='--')
    axes[1].set_title(f'Abnormal Return ({window_hours}h) by Post Sentiment')
    axes[1].set_ylabel('Abnormal Return (%)')

    plt.tight_layout()
    plt.show()


def plot_cumulative_impact(
    results_df: pd.DataFrame,
    windows: list,
    filter_tier: str = None
) -> None:
    """
    Plot average cumulative abnormal return over increasing time windows.

    Parameters
    ----------
    results_df : pd.DataFrame
        Output of run_event_study().
    windows : list of int
        Impact windows to plot (x-axis).
    filter_tier : str, optional
        Restrict to a specific tier: 'mega', 'macro', 'micro', 'nano'. None = all.
    """
    df = results_df if filter_tier is None else results_df[results_df['tier'] == filter_tier]
    means = {}
    for sent in ['bullish', 'bearish', 'neutral']:
        sub = df[df['post_sentiment'] == sent]
        means[sent] = [sub[f'abnormal_return_{h}h'].mean() * 100 for h in windows]

    fig, ax = plt.subplots(figsize=(10, 5))
    colors = {'bullish': 'green', 'bearish': 'red', 'neutral': 'grey'}
    for sent, vals in means.items():
        ax.plot(windows, vals, marker='o', linewidth=2, color=colors[sent], label=sent.capitalize())
    ax.axhline(0, color='black', linewidth=0.8, linestyle='--')
    title = f'Avg Cumulative Abnormal Return by Sentiment'
    if filter_tier:
        title += f' ({filter_tier.capitalize()} tier)'
    ax.set_title(title)
    ax.set_xlabel('Hours After Post')
    ax.set_ylabel('Avg Abnormal Return (%)')
    ax.legend()
    plt.tight_layout()
    plt.show()


# ── Score influencers ─────────────────────────────────────────────────────────
impact_scores = compute_influencer_impact_scores(results_df, primary_window=24, min_posts=MIN_POSTS_FOR_ANALYSIS)
plot_impact_by_tier(results_df, window_hours=24)
plot_cumulative_impact(results_df, IMPACT_WINDOWS_HOURS)
Scored 8 influencers (minimum 5 posts each)
      author  tier  followers  n_posts  mean_impact  std_impact  t_stat  p_value  impact_score
influencer_2 micro      50000       30        0.626       2.787   1.229   0.2288        0.4825
influencer_6  mega    5000000       21        0.384       2.095   0.841   0.4103        0.2267
influencer_7 micro      50000       26        0.169       2.398   0.360   0.7217        0.0471
influencer_0 macro     200000       20        0.024       2.488   0.043   0.9664        0.0008
influencer_5 micro      50000       27       -0.020       2.871  -0.036   0.9712       -0.0006
influencer_1 macro     800000       19       -0.224       2.322  -0.421   0.6789       -0.0720
influencer_4 macro     200000       23       -0.437       3.324  -0.630   0.5353       -0.2029
influencer_3 macro     800000       24       -0.428       2.680  -0.783   0.4417       -0.2391
cell output
cell output

Section 6 — Live Signal: Influencer-Triggered Alert

[7]
def build_influencer_watchlist(
    impact_scores: pd.DataFrame,
    min_impact_score: float = 0.01,
    p_value_cutoff: float = 0.10
) -> pd.DataFrame:
    """
    Build a curated watchlist of high-impact influencers for live signal generation.

    Parameters
    ----------
    impact_scores : pd.DataFrame
        Output of compute_influencer_impact_scores().
    min_impact_score : float
        Minimum absolute impact_score to include (filters noise).
    p_value_cutoff : float
        Maximum p-value allowed (ensures statistical significance).

    Returns
    -------
    pd.DataFrame
        Filtered and ranked watchlist of high-impact accounts.

    Notes
    -----
    In a live system, this watchlist is checked each time a new post
    arrives. If the author is on the watchlist, a signal is generated
    proportional to their impact score and the post's VADER sentiment.
    """
    watchlist = impact_scores[
        (impact_scores['p_value'] <= p_value_cutoff) &
        (impact_scores['impact_score'].abs() >= min_impact_score)
    ].copy()
    watchlist = watchlist.sort_values('impact_score', ascending=False)
    print(f'Watchlist: {len(watchlist)} accounts qualify (p < {p_value_cutoff}, |impact| > {min_impact_score}%)')
    return watchlist


def generate_live_influencer_signal(
    new_post: dict,
    watchlist: pd.DataFrame
) -> dict:
    """
    Generate a trading signal when a new post arrives from a watchlisted influencer.

    Parameters
    ----------
    new_post : dict
        Post record with keys: author, text, timestamp.
    watchlist : pd.DataFrame
        Output of build_influencer_watchlist().

    Returns
    -------
    dict
        Signal record with: author, signal_direction (+1/-1/0), signal_strength,
        post_sentiment, impact_score_historical, timestamp.
        Returns None if author not in watchlist.
    """
    match = watchlist[watchlist['author'] == new_post['author']]
    if match.empty:
        return None

    hist_impact = match.iloc[0]['impact_score']
    vader_score = VADER.polarity_scores(str(new_post['text']))['compound']

    if vader_score > 0.05:
        direction, sentiment = 1, 'bullish'
    elif vader_score < -0.05:
        direction, sentiment = -1, 'bearish'
    else:
        direction, sentiment = 0, 'neutral'

    return {
        'author':                  new_post['author'],
        'signal_direction':        direction,
        'signal_strength':         round(abs(hist_impact) * abs(vader_score), 4),
        'post_sentiment':          sentiment,
        'impact_score_historical': round(hist_impact, 4),
        'timestamp':               new_post['timestamp'],
    }


# ── Build watchlist and demonstrate live signal ───────────────────────────────
watchlist = build_influencer_watchlist(impact_scores, min_impact_score=0.0, p_value_cutoff=0.5)
print(watchlist[['author', 'tier', 'followers', 'mean_impact', 'p_value', 'impact_score']].to_string(index=False))

if len(watchlist) > 0:
    demo_post = {
        'author':    watchlist.iloc[0]['author'],
        'text':      'BTC is going to absolutely moon — biggest opportunity of the decade',
        'timestamp': datetime.now(tz=timezone.utc),
    }
    demo_signal = generate_live_influencer_signal(demo_post, watchlist)
    print('\nLive signal generated:')
    for k, v in demo_signal.items():
        print(f'  {k}: {v}')
Watchlist: 3 accounts qualify (p < 0.5, |impact| > 0.0%)
      author  tier  followers  mean_impact  p_value  impact_score
influencer_2 micro      50000        0.626   0.2288        0.4825
influencer_6  mega    5000000        0.384   0.4103        0.2267
influencer_3 macro     800000       -0.428   0.4417       -0.2391

Live signal generated:
  author: influencer_2
  signal_direction: 1
  signal_strength: 0.2034
  post_sentiment: bullish
  impact_score_historical: 0.4825
  timestamp: 2026-06-12 07:17:20.825439+00:00

Section 7 — Export

[8]
def export_influencer_analysis(
    results_df: pd.DataFrame,
    impact_scores: pd.DataFrame,
    watchlist: pd.DataFrame
) -> None:
    """
    Export event study results, impact scores, and watchlist to CSV files.

    Parameters
    ----------
    results_df : pd.DataFrame
        Full event study DataFrame with abnormal returns.
    impact_scores : pd.DataFrame
        Per-influencer impact score summary.
    watchlist : pd.DataFrame
        Curated high-impact influencer watchlist.
    """
    results_df.to_csv('influencer_event_study.csv', index=False)
    impact_scores.to_csv('influencer_impact_scores.csv', index=False)
    watchlist.to_csv('influencer_watchlist.csv', index=False)
    print('Exported: influencer_event_study.csv')
    print('Exported: influencer_impact_scores.csv')
    print('Exported: influencer_watchlist.csv')


export_influencer_analysis(results_df, impact_scores, watchlist)
Exported: influencer_event_study.csv
Exported: influencer_impact_scores.csv
Exported: influencer_watchlist.csv

Summary & Next Steps

What We Built

StepOutput
Post sentiment scoringVADER labels per post
Influencer tieringmega / macro / micro / nano
Event studyAbnormal returns at 1h, 4h, 24h, 72h
Impact scoringStatistical significance + effect size
WatchlistCurated high-impact accounts
Live signalReal-time signal generation on new posts