STRASMORE/EXPLORE 2,170 QUERIES 22Y EQUITIES · 12Y OPTIONS

2,170 answered market questions

every one with its exact SQL, its result and the date it was computed · free, no signup

Is 30% IV High? It Depends on the Ticker
IV rank against IV percentile: the latest reading inside each ticker's 52-week rangetable · 2026-08-02 · 8×6 Where a 30% reading sits in each ticker's own two-year distributiontable · 2026-08-02 · 8×6 Monthly median 30-day implied volatility: index ETF, staple, and chipmakerseries · 2026-08-02 · 24×5Preview: a 16-point series, ending lower. Implied volatility band against the move the underlying made the next sessiontable · 2026-08-02 · 5×5
IV rank against IV percentile: the latest reading inside each ticker's 52-week range

IV rank against IV percentile: the latest reading inside each ticker's 52-week range

most recentas of table 8×6read in context →
IV rank against IV percentile: the latest reading inside each ticker's 52-week range — 8 rows by 6 columns, computed from US exchange, SIP and OPRA data.
symbollatest_iv_pctlow_52w_iv_pcthigh_52w_iv_pctiv_rankiv_percentile
AAPL45.91945.910099.6
KO20.613.925.160.271.6
COIN77.948.897.759.689.2
NVDA42.232.454.444.658.4
MSFT33.418.253.942.678.4
MSTR7949.8129.436.675.6
TSLA45.540.164.82232.4
SPY14.612.326.316.740.8
the exact SQL behind every number
WITH atm AS (
    SELECT underlying_symbol AS symbol,
           date,
           avg(implied_volatility) * 100 AS iv_pct
    FROM global_markets.options_greeks
    WHERE underlying_symbol IN ('SPY', 'KO', 'AAPL', 'MSFT', 'NVDA', 'TSLA', 'COIN', 'MSTR')
      AND date >= toDate('2025-08-01')
      AND date <= toDate('2026-07-31')
      AND iv_converged = 1
      AND volume > 0
      AND underlying_close > 0
      AND days_to_expiry BETWEEN 20 AND 45
      AND abs(toFloat64(strike_price) / toFloat64(underlying_close) - 1) < 0.05
    GROUP BY symbol, date
),
latest AS (
    SELECT symbol,
           argMax(iv_pct, date) AS latest_iv
    FROM atm
    GROUP BY symbol
)
SELECT a.symbol AS symbol,
       round(any(l.latest_iv), 1) AS latest_iv_pct,
       round(min(a.iv_pct), 1) AS low_52w_iv_pct,
       round(max(a.iv_pct), 1) AS high_52w_iv_pct,
       round(100 * (any(l.latest_iv) - min(a.iv_pct)) / (max(a.iv_pct) - min(a.iv_pct)), 1) AS iv_rank,
       round(100 * countIf(a.iv_pct < l.latest_iv) / count(), 1) AS iv_percentile
FROM atm AS a
INNER JOIN latest AS l ON a.symbol = l.symbol
GROUP BY a.symbol
HAVING max(a.iv_pct) > min(a.iv_pct) AND count() >= 100
ORDER BY iv_rank DESC
$