IV Rank Scanner: Find the Highest Implied Volatility Stocks Today | FlashAlpha Research

IV Rank Scanner: Find the Highest Implied Volatility Stocks Today

Build an IV rank scanner in Python to find the highest implied volatility stocks today. Scan 50+ tickers, filter by IV rank, and automate daily alerts to Slack or Discord — all using the FlashAlpha API.


Tomasz Dobrowolski - Quant Engineer

  • #IVRank #ImpliedVolatility #OptionsScreener #Python #PremiumSelling

Why IV Rank Matters More Than Raw IV

AAPL at 30% IV and TSLA at 30% IV are completely different situations. AAPL's 52-week IV range might be 15%-35%, putting 30% near the top. TSLA's range might be 25%-80%, putting 30% near the bottom. Same raw number, opposite conclusions.

IV rank solves this by normalizing: it tells you where current IV sits as a percentage of the annual range (0-100). IV percentile goes further — it tells you what percentage of trading days had lower IV than today. Both give you the context that raw IV lacks.

Selling premium when IV rank is elevated is the most basic statistical edge in options. You're selling insurance when insurance is expensive. The data backs this up — IV tends to mean-revert, so high IV rank today implies IV is likely to contract, benefiting premium sellers.

Key Insight

IV rank > 50 means current IV is in the upper half of its annual range. Many premium sellers use this as their minimum threshold for entering short vol positions.

Build a Scanner in 20 Lines of Python

This scanner pulls volatility data for a 50-ticker watchlist, filters for elevated IV, and sorts by the highest readings. The Volatility Analysis endpoint returns ATM IV, realized vol, and the IV-RV spread for each ticker.

from flashalpha import FlashAlphaClient
import pandas as pd

client = FlashAlphaClient(api_key="your_api_key")

# Define your watchlist — mega caps, popular options names
watchlist = [
    "SPY", "QQQ", "IWM", "TSLA", "NVDA", "AAPL", "MSFT", "AMZN", "GOOGL", "META",
    "AMD", "NFLX", "AVGO", "CRM", "ORCL", "ADBE", "INTC", "MU", "QCOM", "NOW",
    "JPM", "GS", "BAC", "WFC", "V", "MA", "PYPL", "COIN", "SOFI", "PLTR",
    "XOM", "CVX", "COP", "OXY", "SLB", "JNJ", "UNH", "PFE", "LLY", "ABBV",
    "COST", "WMT", "HD", "NKE", "SBUX", "BA", "CAT", "DIS", "UBER", "ABNB"
]

results = []
for ticker in watchlist:
    try:
        vol = client.get_volatility(ticker)
        results.append({
            "ticker": ticker,
            "atm_iv": vol["atm_iv"],
            "rv_20d": vol["realized_vol"]["rv_20d"],
            "vrp": vol["iv_rv_spreads"]["vrp_20d"],
            "assessment": vol["iv_rv_spreads"]["assessment"]
        })
    except Exception:
        continue  # skip if data unavailable

df = pd.DataFrame(results)
df = df.sort_values("atm_iv", ascending=False)

# Show top 20 by ATM IV
print("\n=== Highest IV Stocks Today ===\n")
print(df.head(20).to_string(index=False))

Sample output:

=== Highest IV Stocks Today ===

ticker  atm_iv  rv_20d    vrp         assessment
  TSLA   52.30   45.80   6.50  moderate_premium
  COIN   48.70   41.20   7.50  moderate_premium
  PLTR   45.20   38.90   6.30  moderate_premium
  NVDA   42.80   39.10   3.70     fair_premium
   AMD   39.50   35.20   4.30     fair_premium
  SOFI   38.90   33.40   5.50  moderate_premium
  UBER   36.20   31.80   4.40     fair_premium
  ABNB   35.80   30.50   5.30  moderate_premium
   MU    34.50   29.80   4.70     fair_premium
   OXY   33.90   28.60   5.30  moderate_premium
  NFLX   32.40   27.90   4.50     fair_premium
   NKE   31.80   26.40   5.40  moderate_premium
    BA   31.20   28.70   2.50     fair_premium
   CRM   30.50   25.80   4.70     fair_premium
  INTC   29.80   26.30   3.50     fair_premium
  QCOM   28.90   24.70   4.20     fair_premium
  PYPL   28.40   23.60   4.80     fair_premium
   DIS   27.60   22.90   4.70     fair_premium
   GS    26.80   22.10   4.70     fair_premium
   BAC   25.50   21.30   4.20     fair_premium

The vrp column is the volatility risk premium — the spread between implied and realized vol. Positive VRP means options are pricing in more volatility than is actually occurring. When VRP is high and IV is elevated, that's the sweet spot for premium selling.

Filter for Premium Selling Opportunities

Not every high-IV stock is a good short vol trade. You want elevated IV and positive VRP — confirmation that options are overpriced relative to actual movement:

# Filter: ATM IV > 30% AND positive VRP > 3%
opportunities = df[(df["atm_iv"] > 30) & (df["vrp"] > 3.0)]
print(f"\n=== Premium Selling Candidates ({len(opportunities)} found) ===\n")
print(opportunities.to_string(index=False))

This filters your scan down to the actionable names — stocks where IV is elevated and the market is overpricing vol relative to what's being realized.

How to Use This for Trading

Selling Premium

High IV + positive VRP is the classic setup for credit spreads, iron condors, and strangles. You're selling expensive insurance — collecting premium inflated by fear or uncertainty, betting that actual movement will be less than what's priced in.

The scanner identifies where premium is richest. Your job is to decide how to structure the trade — defined risk (credit spreads, iron condors) or undefined risk (strangles, straddles) — based on your risk tolerance and account size.

Avoiding IV Crush

If you're buying options, the scanner serves as a warning system. Buying calls on a stock with ATM IV at 50% when its normal range is 25-35% means you're paying a massive premium that will erode even if the stock moves your direction. Check IV context before entering any long options position.

This is especially critical around earnings — see our IV Crush guide for how to track and exploit earnings vol collapse.

Relative Value

Compare IV across correlated names. If AMD's IV is at a historic high while NVDA's is at a historic low — same sector, same macro exposure — there may be a relative value opportunity. Sell AMD vol, buy NVDA vol. The scanner helps you spot these divergences.

Automate It: Daily IV Alert to Discord

Run the scanner automatically every morning and push results to a Discord channel. Set it up once, never manually scan again:

import requests
from flashalpha import FlashAlphaClient

DISCORD_WEBHOOK = "https://discord.com/api/webhooks/your_webhook_url"

client = FlashAlphaClient(api_key="your_api_key")

watchlist = [
    "SPY", "QQQ", "TSLA", "NVDA", "AAPL", "MSFT", "AMZN", "META", "AMD", "NFLX",
    "COIN", "PLTR", "SOFI", "UBER", "ABNB", "BA", "NKE", "CRM", "MU", "GS",
    "JPM", "XOM", "OXY", "LLY", "JNJ", "GOOGL", "AVGO", "INTC", "PYPL", "DIS"
]

results = []
for ticker in watchlist:
    try:
        vol = client.get_volatility(ticker)
        if vol["atm_iv"] > 30 and vol["iv_rv_spreads"]["vrp_20d"] > 3.0:
            results.append(f"**{ticker}** — IV: {vol['atm_iv']}% | VRP: {vol['iv_rv_spreads']['vrp_20d']}%")
    except Exception:
        continue

if results:
    message = "## Daily IV Scanner — Premium Selling Candidates\n" + "\n".join(results[:10])
    requests.post(DISCORD_WEBHOOK, json={"content": message})
    print(f"Sent {len(results)} results to Discord")
else:
    requests.post(DISCORD_WEBHOOK, json={"content": "## Daily IV Scanner\nNo elevated IV stocks found today."})
    print("No candidates today")

Schedule this with cron (Linux) or Task Scheduler (Windows) to run at 9:15am ET every trading day. 30 API calls — well within the Growth plan's 2,500/day limit.

Tip: Add Slack support by replacing the Discord webhook with a Slack incoming webhook URL. The payload format is nearly identical — just change "content" to "text".

Get the Data

The Volatility Analysis endpoint requires the Growth plan ($299/mo, 2,500 requests/day). For a 50-ticker watchlist scanned once daily, that's 50 calls — 2% of your daily quota.

Start Scanning for High IV

Build your own IV scanner and find the richest premium every morning.

Get API Key → Try the Playground

Related Reading


Live Market Pulse

Get tick-by-tick visibility into market shifts with full-chain analytics streaming in real time.

Intelligent Screening

Screen millions of option pairs per second using your custom EV rules, filters, and setups.

Execution-Ready

Instantly send structured orders to Interactive Brokers right from your scan results.

Join the Community

Discord

Engage in real time conversations with us!

Twitter / X

Follow us for real-time updates and insights!

GitHub

Explore our open-source SDK, examples, and analytics resources!