Build an IV Rank Scanner with an API: Implied Volatility Screener for Developers | FlashAlpha

Build an IV Rank Scanner with an API: Implied Volatility Screener for Developers

How to build an IV rank and IV percentile scanner using the FlashAlpha API. Scan 6,000+ US stocks for elevated implied volatility, find premium-selling opportunities, and build automated IV alerts. One API call per ticker returns IV rank, IV percentile, ATM IV, historical vol, and VRP.

T
Tomasz Dobrowolski Quant Engineer
Mar 29, 2026
35 min read
IVRank IVPercentile ImpliedVolatility Scanner API Python DeveloperGuide

This guide walks through building a complete IV rank scanner from scratch: single-ticker lookups, batch scanning across a watchlist, high-IV alert systems, sector-based screening, and automated daily notifications. Every code sample runs against the live API.


IV Rank vs IV Percentile: Quick Refresher

Before building the scanner, make sure you're clear on the two metrics you'll be scanning for. They answer related but different questions.

IV Rank measures where current implied volatility sits within its 52-week range:

IV Rank = (Current IV - 52-Week Low IV) / (52-Week High IV - 52-Week Low IV) * 100

An IV rank of 80 means current IV is 80% of the way between its annual low and annual high. It tells you how elevated IV is relative to its own extremes.

IV Percentile measures what percentage of trading days over the past year had lower IV than today:

IV Percentile = (Number of days with IV below current IV) / (Total trading days in lookback) * 100

An IV percentile of 87 means IV was lower than today on 87% of trading days in the past year. It tells you how unusual the current IV level is.

Why both matter: A stock that had one spike to 200% IV and otherwise traded at 20% will show a low IV rank even at 40% IV (because the range is huge), but a high IV percentile (because 40% is above the typical level). IV percentile is generally more robust for screening because it's less sensitive to outlier spikes. Most professional scanners use both.


The API Approach

The primary endpoint for IV scanning is GET /v1/stock/{symbol}/summary, available on the Free tier (5 req/day) and above. One call returns everything you need for IV screening:

  • ATM IV - current at-the-money implied volatility
  • IV Rank - 52-week IV rank (0-100)
  • IV Percentile - 52-week IV percentile (0-100)
  • Historical Volatility - realized vol for context
  • VRP Assessment - whether IV is rich or cheap vs realized vol
  • Skew - put/call skew context
  • Regime - gamma exposure regime (positive/negative/transitional)
  • Key Exposure Levels - gamma flip, call wall, put wall

For deeper volatility analysis, GET /v1/volatility/{symbol} (Growth+ plan) provides realized vol across multiple windows (5d-60d), IV-RV spreads with assessments, skew profiles (25-delta risk reversal, butterfly), term structure, and OI concentration data.

To build a scanner that covers your full universe, GET /v1/tickers (Free) returns all available tickers - currently 6,000+ US equities and ETFs.

$ pip install flashalpha
>>> fa.stock_summary("TSLA")
{"iv_rank": 82, "iv_percentile": 87, "atm_iv": 48.2, ...}

Quick Start: Single Ticker IV Rank Lookup

from flashalpha import FlashAlpha

fa = FlashAlpha("YOUR_KEY")
summary = fa.stock_summary("TSLA")

print(f"IV Rank:       {summary.iv_rank}")
print(f"IV Percentile: {summary.iv_percentile}")
print(f"ATM IV:        {summary.atm_iv}%")
print(f"Hist Vol:      {summary.historical_vol}%")
print(f"VRP:           {summary.vrp_assessment}")
import { FlashAlpha } from 'flashalpha';

const fa = new FlashAlpha("YOUR_KEY");
const summary = await fa.stockSummary("TSLA");

console.log(`IV Rank:       ${summary.ivRank}`);
console.log(`IV Percentile: ${summary.ivPercentile}`);
console.log(`ATM IV:        ${summary.atmIv}%`);
using FlashAlpha;

var fa = new FlashAlphaClient("YOUR_KEY");
var summary = await fa.StockSummaryAsync("TSLA");

Console.WriteLine($"IV Rank:       {summary.IvRank}");
Console.WriteLine($"IV Percentile: {summary.IvPercentile}");
Console.WriteLine($"ATM IV:        {summary.AtmIv}%");
package main

import (
    "context"
    "fmt"
    flashalpha "github.com/FlashAlpha-lab/flashalpha-go"
)

func main() {
    fa := flashalpha.NewClient("YOUR_KEY")
    summary, _ := fa.StockSummary(context.Background(), "TSLA")

    fmt.Printf("IV Rank:       %d\n", summary.IvRank)
    fmt.Printf("IV Percentile: %d\n", summary.IvPercentile)
    fmt.Printf("ATM IV:        %.1f%%\n", summary.AtmIv)
}
import com.flashalpha.FlashAlphaClient;
import com.google.gson.JsonObject;

FlashAlphaClient fa = new FlashAlphaClient("YOUR_KEY");
JsonObject summary = fa.stockSummary("TSLA");

System.out.println("IV Rank: " + summary.get("iv_rank").getAsInt());
System.out.println("IV Percentile: " + summary.get("iv_percentile").getAsInt());
System.out.println("ATM IV: " + summary.get("atm_iv").getAsDouble() + "%");
curl -s -H "X-Api-Key: YOUR_KEY" \
  https://lab.flashalpha.com/v1/stock/TSLA/summary | jq '{
    iv_rank: .iv_rank,
    iv_percentile: .iv_percentile,
    atm_iv: .atm_iv,
    historical_vol: .historical_vol,
    vrp_assessment: .vrp_assessment
  }'
$ pip install flashalpha  |  npm install flashalpha  |  dotnet add package FlashAlpha  |  go get github.com/FlashAlpha-lab/flashalpha-go

Building the Scanner

1. Basic IV Rank Scanner

Loop through a watchlist and sort by IV rank descending. This is the simplest scanner: find which stocks in your universe currently have the most elevated implied volatility.

from flashalpha import FlashAlpha
import time

fa = FlashAlpha("YOUR_KEY")

watchlist = [
    "AAPL", "MSFT", "GOOGL", "AMZN", "TSLA", "NVDA", "META", "AMD",
    "NFLX", "CRM", "COIN", "SHOP", "SQ", "ROKU", "SNAP", "UBER",
    "SPY", "QQQ", "IWM", "XLF", "XLE", "XLK", "XLV", "XBI"
]

results = []
for ticker in watchlist:
    try:
        s = fa.stock_summary(ticker)
        results.append({
            "ticker": ticker,
            "iv_rank": s.iv_rank,
            "iv_percentile": s.iv_percentile,
            "atm_iv": s.atm_iv,
            "vrp": s.vrp_assessment
        })
    except Exception as e:
        print(f"  Skipped {ticker}: {e}")
    time.sleep(0.5)  # respect rate limits

# Sort by IV rank descending
results.sort(key=lambda x: x["iv_rank"], reverse=True)

print(f"\n{'Ticker':<8} {'IV Rank':>8} {'IV Pctl':>8} {'ATM IV':>8} {'VRP':>12}")
print("-" * 48)
for r in results:
    print(f"{r['ticker']:<8} {r['iv_rank']:>7.1f}% {r['iv_percentile']:>7.1f}% {r['atm_iv']:>7.1f}% {r['vrp']:>12}")

2. High IV Alert System

Flag tickers with IV rank above a threshold. This is the core of any premium-selling screening workflow: find options that are expensive relative to their historical range.

def scan_high_iv(watchlist, threshold=80):
    """Return tickers with IV rank above threshold."""
    alerts = []
    for ticker in watchlist:
        try:
            s = fa.stock_summary(ticker)
            if s.iv_rank >= threshold:
                alerts.append({
                    "ticker": ticker,
                    "iv_rank": s.iv_rank,
                    "iv_percentile": s.iv_percentile,
                    "atm_iv": s.atm_iv,
                    "vrp": s.vrp_assessment,
                    "regime": s.regime
                })
        except Exception:
            continue
        time.sleep(0.5)

    alerts.sort(key=lambda x: x["iv_rank"], reverse=True)
    return alerts

# Find stocks with IV rank > 80
high_iv = scan_high_iv(watchlist, threshold=80)
for a in high_iv:
    print(f"  {a['ticker']}: IV Rank {a['iv_rank']:.0f}%, "
          f"ATM IV {a['atm_iv']:.1f}%, VRP: {a['vrp']}")

3. Low IV Scanner: Cheap Options for Long Vol

The opposite play: find tickers where IV is historically low. These are candidates for buying options (straddles, strangles, calendar spreads) when IV is likely to revert higher.

def scan_low_iv(watchlist, ceiling=20):
    """Return tickers with IV rank below ceiling."""
    candidates = []
    for ticker in watchlist:
        try:
            s = fa.stock_summary(ticker)
            if s.iv_rank <= ceiling:
                candidates.append({
                    "ticker": ticker,
                    "iv_rank": s.iv_rank,
                    "iv_percentile": s.iv_percentile,
                    "atm_iv": s.atm_iv,
                    "vrp": s.vrp_assessment
                })
        except Exception:
            continue
        time.sleep(0.5)

    candidates.sort(key=lambda x: x["iv_rank"])
    return candidates

low_iv = scan_low_iv(watchlist, ceiling=20)
print(f"\nLow IV candidates ({len(low_iv)} found):")
for c in low_iv:
    print(f"  {c['ticker']}: IV Rank {c['iv_rank']:.0f}%, ATM IV {c['atm_iv']:.1f}%")

4. IV Rank + GEX Regime: The Premium-Selling Sweet Spot

High IV alone doesn't mean it's safe to sell premium. Pairing IV rank with the gamma exposure regime adds a crucial layer of context. Positive gamma regime means dealers are long gamma, creating a natural dampening effect on price moves - the ideal environment for premium sellers.

def scan_premium_selling(watchlist):
    """Find high IV + positive gamma regime = premium selling candidates."""
    candidates = []
    for ticker in watchlist:
        try:
            s = fa.stock_summary(ticker)
            if s.iv_rank >= 70 and s.regime == "positive":
                candidates.append({
                    "ticker": ticker,
                    "iv_rank": s.iv_rank,
                    "iv_percentile": s.iv_percentile,
                    "atm_iv": s.atm_iv,
                    "regime": s.regime,
                    "vrp": s.vrp_assessment,
                    "gamma_flip": s.gamma_flip
                })
        except Exception:
            continue
        time.sleep(0.5)

    candidates.sort(key=lambda x: x["iv_rank"], reverse=True)
    return candidates

sweet_spots = scan_premium_selling(watchlist)
print(f"\nPremium-selling sweet spots ({len(sweet_spots)} found):")
for c in sweet_spots:
    print(f"  {c['ticker']}: IV Rank {c['iv_rank']:.0f}%, "
          f"Regime: {c['regime']}, VRP: {c['vrp']}")

IV Rank + GEX Regime in one call

The /v1/stock/{symbol}/summary endpoint returns both IV rank and gamma regime. No need to query two endpoints.

Get API Access

5. Sector-Based IV Scanning

Group tickers by sector ETF and scan each group. This surfaces sector-level IV trends: is tech IV elevated while energy IV is depressed? Useful for relative value vol trades and sector rotation strategies.

sectors = {
    "Tech":       ["AAPL", "MSFT", "GOOGL", "NVDA", "AMD", "CRM", "ADBE"],
    "Financials": ["JPM", "GS", "BAC", "WFC", "MS", "C", "BLK"],
    "Energy":     ["XOM", "CVX", "COP", "SLB", "EOG", "MPC", "OXY"],
    "Healthcare": ["JNJ", "UNH", "PFE", "ABBV", "MRK", "LLY", "BMY"],
    "Consumer":   ["AMZN", "TSLA", "HD", "NKE", "SBUX", "MCD", "TGT"],
    "ETFs":       ["SPY", "QQQ", "IWM", "XLF", "XLE", "XLK", "XBI"]
}

for sector, tickers in sectors.items():
    print(f"\n{'='*50}")
    print(f"  {sector}")
    print(f"{'='*50}")

    sector_results = []
    for ticker in tickers:
        try:
            s = fa.stock_summary(ticker)
            sector_results.append({
                "ticker": ticker,
                "iv_rank": s.iv_rank,
                "iv_percentile": s.iv_percentile,
                "atm_iv": s.atm_iv
            })
        except Exception:
            continue
        time.sleep(0.5)

    sector_results.sort(key=lambda x: x["iv_rank"], reverse=True)

    avg_rank = sum(r["iv_rank"] for r in sector_results) / len(sector_results) if sector_results else 0
    print(f"  Sector Avg IV Rank: {avg_rank:.1f}%\n")

    for r in sector_results:
        bar = "#" * int(r["iv_rank"] / 5)
        print(f"  {r['ticker']:<6} IV Rank: {r['iv_rank']:>5.1f}%  |{bar}")

6. IV Rank with VRP Context

High IV rank alone doesn't tell you whether IV is rich relative to what the stock actually delivers in realized moves. The VRP (Volatility Risk Premium) context answers this: is the implied volatility actually overpriced vs historical realized vol?

The /v1/stock/{symbol}/summary endpoint includes a VRP assessment. For deeper analysis, /v1/vrp/{symbol} (Alpha plan) provides z-scores and percentiles.

def scan_rich_iv(watchlist):
    """Find high IV that is ALSO rich vs realized vol (positive VRP)."""
    rich = []
    for ticker in watchlist:
        try:
            s = fa.stock_summary(ticker)
            # High IV rank AND VRP indicates IV is rich vs realized
            if s.iv_rank >= 60 and s.vrp_assessment in ["rich", "very_rich"]:
                rich.append({
                    "ticker": ticker,
                    "iv_rank": s.iv_rank,
                    "iv_percentile": s.iv_percentile,
                    "atm_iv": s.atm_iv,
                    "historical_vol": s.historical_vol,
                    "vrp": s.vrp_assessment
                })
        except Exception:
            continue
        time.sleep(0.5)

    rich.sort(key=lambda x: x["iv_rank"], reverse=True)
    return rich

rich_iv = scan_rich_iv(watchlist)
print(f"\nHigh IV + Rich VRP ({len(rich_iv)} found):")
print(f"{'Ticker':<8} {'IV Rank':>8} {'ATM IV':>8} {'HV':>8} {'Spread':>8} {'VRP':>10}")
print("-" * 56)
for r in rich_iv:
    spread = r["atm_iv"] - r["historical_vol"]
    print(f"{r['ticker']:<8} {r['iv_rank']:>7.1f}% {r['atm_iv']:>7.1f}% "
          f"{r['historical_vol']:>7.1f}% {spread:>+7.1f}% {r['vrp']:>10}")

For Alpha plan users, the deeper VRP endpoint adds z-scores:

# Alpha plan: deeper VRP analysis
vrp = fa.vrp("TSLA")
print(f"VRP Z-Score:    {vrp.z_score}")
print(f"VRP Percentile: {vrp.percentile}")
print(f"Regime:         {vrp.regime}")

Complete Scanner Script

Here's a full scanner that pulls the ticker universe from the API, scans a configurable watchlist, and outputs a formatted table sorted by IV rank.

"""
IV Rank Scanner using FlashAlpha API
Usage: python iv_scanner.py
"""
from flashalpha import FlashAlpha
import time
import sys

API_KEY = "YOUR_KEY"
IV_RANK_THRESHOLD = 50      # minimum IV rank to display
SORT_BY = "iv_rank"          # iv_rank, iv_percentile, or atm_iv
DELAY = 0.5                  # seconds between requests

# Define your universe (or pull from the API)
WATCHLIST = [
    "SPY", "QQQ", "IWM", "AAPL", "MSFT", "GOOGL", "AMZN", "TSLA",
    "NVDA", "META", "AMD", "NFLX", "CRM", "COIN", "SHOP", "SQ",
    "ROKU", "SNAP", "UBER", "LYFT", "ABNB", "PLTR", "SOFI", "RIVN",
    "XLF", "XLE", "XLK", "XLV", "XBI", "GDX", "EEM", "TLT"
]

def main():
    fa = FlashAlpha(API_KEY)

    # Optionally: get full ticker universe
    # all_tickers = fa.tickers()
    # print(f"Universe: {len(all_tickers)} tickers available")

    print(f"Scanning {len(WATCHLIST)} tickers...\n")
    results = []
    errors = 0

    for i, ticker in enumerate(WATCHLIST):
        try:
            s = fa.stock_summary(ticker)
            results.append({
                "ticker": ticker,
                "iv_rank": s.iv_rank,
                "iv_percentile": s.iv_percentile,
                "atm_iv": s.atm_iv,
                "historical_vol": s.historical_vol,
                "vrp": s.vrp_assessment,
                "regime": s.regime
            })
        except Exception as e:
            errors += 1
        time.sleep(DELAY)

        # Progress indicator
        pct = (i + 1) / len(WATCHLIST) * 100
        sys.stdout.write(f"\r  Progress: {pct:.0f}% ({i+1}/{len(WATCHLIST)})")
        sys.stdout.flush()

    print(f"\n\nScanned {len(results)} tickers ({errors} errors)\n")

    # Filter and sort
    filtered = [r for r in results if r["iv_rank"] >= IV_RANK_THRESHOLD]
    filtered.sort(key=lambda x: x[SORT_BY], reverse=True)

    # Output table
    header = f"{'#':<4} {'Ticker':<8} {'IV Rank':>8} {'IV Pctl':>8} {'ATM IV':>8} {'HV':>8} {'Spread':>8} {'VRP':>12} {'Regime':>14}"
    print(header)
    print("-" * len(header))

    for i, r in enumerate(filtered, 1):
        spread = r["atm_iv"] - r["historical_vol"]
        print(f"{i:<4} {r['ticker']:<8} {r['iv_rank']:>7.1f}% {r['iv_percentile']:>7.1f}% "
              f"{r['atm_iv']:>7.1f}% {r['historical_vol']:>7.1f}% {spread:>+7.1f}% "
              f"{r['vrp']:>12} {r['regime']:>14}")

    print(f"\n{len(filtered)} tickers above {IV_RANK_THRESHOLD}% IV rank threshold")

if __name__ == "__main__":
    main()

Sample output:

#    Ticker   IV Rank  IV Pctl   ATM IV       HV   Spread          VRP         Regime
---------------------------------------------------------------------------------------
1    COIN       91.3%    94.2%    72.4%    58.1%   +14.3%         rich       positive
2    TSLA       82.0%    87.0%    48.2%    41.5%    +6.7%         rich       negative
3    ROKU       78.4%    81.6%    61.8%    55.2%    +6.6%         fair   transitional
4    SNAP       76.1%    79.3%    55.0%    52.8%    +2.2%         fair       positive
5    RIVN       72.5%    75.8%    68.1%    64.3%    +3.8%         fair       negative
6    AMD        68.9%    72.1%    42.3%    35.4%    +6.9%         rich       positive
7    NFLX       65.2%    68.7%    38.9%    31.2%    +7.7%         rich       positive
8    XBI        58.4%    62.0%    31.5%    27.8%    +3.7%         fair       positive
9    PLTR       54.7%    58.3%    52.1%    49.6%    +2.5%         fair   transitional

Scan your own watchlist in 60 seconds

Free tier: 5 requests/day, no credit card, no time limit. Enough to test the scanner on your top picks.

Get API Access

Daily Email / Slack Alert

Run the scanner on a schedule and push high-IV alerts to Slack or email. Here's a minimal Slack integration:

"""
Daily IV rank alert - run via cron at 9:00 AM ET
Sends high-IV alerts to a Slack webhook
"""
import requests
import time
from flashalpha import FlashAlpha

fa = FlashAlpha("YOUR_KEY")
SLACK_WEBHOOK = "https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
THRESHOLD = 75

watchlist = [
    "SPY", "QQQ", "IWM", "AAPL", "MSFT", "GOOGL", "AMZN", "TSLA",
    "NVDA", "META", "AMD", "NFLX", "COIN", "XBI", "GDX", "TLT"
]

alerts = []
for ticker in watchlist:
    try:
        s = fa.stock_summary(ticker)
        if s.iv_rank >= THRESHOLD:
            alerts.append(f"*{ticker}*: IV Rank {s.iv_rank:.0f}% | "
                         f"ATM IV {s.atm_iv:.1f}% | VRP: {s.vrp_assessment}")
    except Exception:
        continue
    time.sleep(0.5)

if alerts:
    message = {
        "text": f":chart_with_upwards_trend: *IV Rank Alert* - "
                f"{len(alerts)} tickers above {THRESHOLD}%\n\n"
                + "\n".join(alerts)
    }
    requests.post(SLACK_WEBHOOK, json=message)
    print(f"Sent {len(alerts)} alerts to Slack")
else:
    print("No tickers above threshold")

Schedule this with cron (Linux/Mac) or Task Scheduler (Windows):

# Run at 9:00 AM ET every weekday
0 9 * * 1-5 cd /path/to/scanner && python iv_alert.py

For email, swap the Slack webhook for SMTP or a service like SendGrid. The scanning logic stays identical.


AI Agents: Ask Claude for IV Scans

FlashAlpha provides an MCP (Model Context Protocol) server at https://lab.flashalpha.com/mcp. Connect it to Claude, Cursor, Windsurf, or any MCP-compatible AI assistant and query IV data conversationally:

  • "Which stocks in my watchlist have IV rank above 80?"
  • "Compare IV rank and IV percentile for TSLA, NVDA, and AMD"
  • "Find stocks with high IV rank and positive gamma regime"
  • "Is COIN's IV rich or cheap relative to realized vol?"

The MCP server exposes the same endpoints as the REST API. Your AI agent handles the scanning loop, formatting, and interpretation - you just ask questions in plain English.

MCP configuration for Claude Desktop:

{
  "mcpServers": {
    "flashalpha": {
      "url": "https://lab.flashalpha.com/mcp",
      "headers": {
        "X-Api-Key": "YOUR_KEY"
      }
    }
  }
}

Why Not Build It Yourself?

If you're considering computing IV rank and IV percentile yourself, here's what's involved:

  1. Raw options chain data - you need every listed option (all strikes, all expirations) to compute ATM IV accurately. For a single liquid stock like AAPL, that can be 5,000+ contracts. Across 6,000 tickers, you're processing millions of contracts daily.
  2. IV computation - implied volatility isn't a field in raw options data. You have to solve for it using BSM or a binomial model, handling dividends, early exercise, and bid/ask spread noise.
  3. 52-week history - IV rank requires the 52-week high and low of ATM IV. IV percentile requires storing daily ATM IV for every ticker for the past 252 trading days. That's 252 * 6,000 = 1.5 million daily data points, plus the chain data to compute each one.
  4. Daily updates - the entire pipeline needs to run before market open, every day. Miss a day and your rank/percentile computations are stale.
  5. Infrastructure - a database for historical IV, a scheduler, error handling, data vendor costs for the raw chains, and compute for the IV solver.

The API abstracts all of this. One call, one response, pre-computed and ready.


Pricing

PlanPriceRequestsIV Scanning Coverage
Free $0 5 req/day IV rank, IV percentile, ATM IV, VRP via /summary. Test scanner on a handful of tickers.
Basic from $63/mo 100 req/day Scan a 100-ticker watchlist daily. Full /summary data including regime and exposure levels.
Growth from $239/mo 2,500 req/day Scan 2,500 tickers daily. Adds /volatility endpoint for detailed RV, skew profiles, term structure.
Alpha from $1,199/mo Unlimited Full universe scanning. Adds /vrp endpoint for VRP z-scores. Zero-cache responses for max freshness.

Install the SDK in your language of choice:

# Python
pip install flashalpha

# JavaScript / TypeScript
npm install flashalpha

# C#
dotnet add package FlashAlpha
$ pip install flashalpha
>>> fa = FlashAlpha("KEY")
>>> fa.stock_summary("TSLA").iv_rank
82.0

FAQ

IV rank measures where current implied volatility sits within its 52-week range: (Current IV - 52w Low) / (52w High - 52w Low) * 100. An IV rank of 80 means current IV is 80% of the way between its annual low and high. It tells you how elevated IV is relative to its own historical extremes.
IV percentile measures the percentage of trading days over the past year that had lower implied volatility than today. An IV percentile of 87 means IV was lower than today on 87% of trading days. It's more robust than IV rank because it's less sensitive to single extreme spikes.
The API covers 6,000+ US equities and ETFs. Use GET /v1/tickers to retrieve the full list. How many you can scan daily depends on your plan: 5 on Free, 100 on Basic, 2,500 on Growth, unlimited on Alpha.
The Free plan (5 req/day) is enough to test the scanner on a handful of tickers. Basic ($63/mo, 100 req/day) covers a typical watchlist. Growth ($239/mo, 2,500 req/day) scans a large universe and adds the /volatility endpoint for deeper analysis. Alpha ($1,199/mo, unlimited) covers the full 6,000+ ticker universe with VRP z-scores and zero-cache freshness.

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!