Strasmore Research
Learn Matt ConnorBy Matt Connor

How the Put/Call Ratio Is Calculated

How the put/call ratio is calculated: the volume and open interest formulas, why index readings run higher, and what counts as a normal reading in 2026.

The put/call ratio is calculated by dividing the number of put contracts traded by the number of call contracts traded over the same window. If 250,000 puts and 500,000 calls change hands in a session, the ratio is 0.50. Every argument about the indicator, volume against open interest and equity against index, traces back to what got counted on each side of that division. For the plain definition, start with what the put/call ratio is. This page does the arithmetic.

The put/call ratio formula, step by step

The formula has two inputs and one operation: count the puts that traded, count the calls that traded, divide the first by the second. A put is a contract giving its owner the right to sell 100 shares of the underlying at a fixed strike price on or before expiry. A call gives the right to buy at a fixed strike. Volume counts the contracts that changed hands during the session, and it resets to zero at the next open.

Nothing in the count is weighted. A one lot in a far out of the money weekly counts as much as a one lot in the busiest strike on the board, and neither is scaled by the money at risk. The ratio is a contract count.

The choice that changes the answer is which contracts get counted. The panel below runs identical arithmetic across eight liquid names over one full month.

QueryPut and call volume for eight household names, July 2026
The exact SQL behind every number
SELECT
    underlying_symbol                 AS symbol,
    sumIf(volume, right_letter = 'P') AS put_volume,
    sumIf(volume, right_letter = 'C') AS call_volume,
    round(toFloat64(sumIf(volume, right_letter = 'P'))
        / toFloat64(sumIf(volume, right_letter = 'C')), 2) AS put_call_ratio
FROM
(
    SELECT
        underlying_symbol,
        volume,
        substring(ticker, length(ticker) - 8, 1) AS right_letter
    FROM global_markets.options_greeks
    WHERE date >= '2026-07-01'
      AND date <  '2026-08-01'
      AND underlying_symbol IN ('SPY', 'QQQ', 'IWM', 'AAPL', 'MSFT', 'NVDA', 'TSLA', 'KO')
      AND volume > 0
)
GROUP BY symbol
HAVING call_volume > 0 AND put_volume > 0
ORDER BY put_call_ratio DESC
Run this yourself

Over July 2026, IWM carried the highest ratio of the eight at 3.11 puts per call, and MSFT the lowest at 0.38. One formula, one month, and a spread between the top and bottom name far wider than the day to day wobble that gets written about. A ratio quoted without its category attached carries almost no information.

Volume based or open interest based

Two different counts can fill the numerator and denominator.

The volume version counts contracts traded in the window. It is a flow measure that starts from zero every session and describes what people did today. Every headline ratio in market coverage is this one.

The open interest version divides puts outstanding by calls outstanding, where open interest is the number of contracts opened and not yet closed, exercised, or expired. That is a stock measure, the accumulated position rather than the day's activity, and it moves slowly. A session in which 30,000 puts change hands between two existing holders adds 30,000 to volume and leaves open interest flat. Options volume versus open interest covers the bookkeeping.

Take a hypothetical name that ends Tuesday with 40,000 puts and 50,000 calls outstanding, an open interest ratio of 0.80. On Wednesday, 30,000 puts and 10,000 calls trade: a volume ratio of 3.00. Both numbers describe the same option chain on the same day, they disagree by nearly a factor of four, and both are correct. Open interest ratios also sit underneath the max pain calculation, which weights strikes by contracts outstanding rather than by contracts traded.

Flow measures are jumpy. Below is the daily volume ratio for one ETF and one single stock across the same month.

QueryDaily put/call volume ratio, SPY against AAPL, July 2026
The exact SQL behind every number
SELECT
    toString(d)                                                 AS session_date,
    concat(formatDateTime(d, '%b '), toString(toDayOfMonth(d))) AS day_label,
    round(toFloat64(sumIf(volume, sym = 'SPY' AND right_letter = 'P'))
        / toFloat64(sumIf(volume, sym = 'SPY' AND right_letter = 'C')), 2)  AS spy_put_call_ratio,
    round(toFloat64(sumIf(volume, sym = 'AAPL' AND right_letter = 'P'))
        / toFloat64(sumIf(volume, sym = 'AAPL' AND right_letter = 'C')), 2) AS aapl_put_call_ratio
FROM
(
    SELECT
        date                                     AS d,
        underlying_symbol                        AS sym,
        volume,
        substring(ticker, length(ticker) - 8, 1) AS right_letter
    FROM global_markets.options_greeks
    WHERE date >= '2026-07-01'
      AND date <  '2026-08-01'
      AND underlying_symbol IN ('SPY', 'AAPL')
      AND volume > 0
)
GROUP BY d
HAVING countIf(sym = 'SPY' AND right_letter = 'C') > 0
   AND countIf(sym = 'AAPL' AND right_letter = 'C') > 0
ORDER BY d
Run this yourself

On Jul 1, SPY printed 1.1 against 0.49 for AAPL. By Jul 31 the pair read 2 and 0.55. Over 22 sessions the daily prints jump around, and the two series sit at different levels on the chart. The level gap is the more useful of the two facts.

Equity, index, ETP and total: four Cboe ratios

The number quoted as "the put/call ratio" comes from the Cboe daily market statistics, which publishes several of them. The categories, as Cboe names them:

  • Equity put/call ratio: options on individual stocks.
  • Index put/call ratio: options on indexes, including SPX and VIX.
  • Exchange traded products put/call ratio: options on ETFs, where SPY, QQQ and IWM sit.
  • Total put/call ratio: all categories added together.

Each is computed the same way, total puts over total calls inside the category, so the readings differ only by what is in the bucket. The buckets are not interchangeable.

Index options are the standard instrument for hedging an entire portfolio in one trade. A fund holding a broad book of stocks buys index puts against it and has no matching reason to buy index calls. That demand arrives one sided, and it lands entirely in the numerator of the index category. Single stock flow carries the opposite tilt, where call buying on individual names is a large and persistent share of the volume. The two categories sit at different levels as a matter of structure, and a reading from one measured against a benchmark from the other is the most common error made with this indicator.

Broad market ETFs carry the same hedging role as index options while being counted in the exchange traded products category. The panel below tracks a monthly median for both sides of that split.

QueryMonthly median put/call ratio: broad market ETFs against single stocks
The exact SQL behind every number
WITH
    daily AS
    (
        SELECT
            d,
            toFloat64(sumIf(volume, right_letter = 'P' AND sym IN ('SPY', 'QQQ', 'IWM')))
                / toFloat64(sumIf(volume, right_letter = 'C' AND sym IN ('SPY', 'QQQ', 'IWM')))     AS etf_ratio,
            toFloat64(sumIf(volume, right_letter = 'P' AND sym NOT IN ('SPY', 'QQQ', 'IWM')))
                / toFloat64(sumIf(volume, right_letter = 'C' AND sym NOT IN ('SPY', 'QQQ', 'IWM'))) AS stock_ratio
        FROM
        (
            SELECT
                date                                     AS d,
                underlying_symbol                        AS sym,
                volume,
                substring(ticker, length(ticker) - 8, 1) AS right_letter
            FROM global_markets.options_greeks
            WHERE date >= '2025-08-01'
              AND date <  '2026-08-01'
              AND underlying_symbol IN ('SPY', 'QQQ', 'IWM', 'AAPL', 'MSFT', 'NVDA', 'TSLA', 'KO')
              AND volume > 0
        )
        GROUP BY d
        HAVING countIf(right_letter = 'C' AND sym IN ('SPY', 'QQQ', 'IWM')) > 0
           AND countIf(right_letter = 'C' AND sym NOT IN ('SPY', 'QQQ', 'IWM')) > 0
    )
SELECT
    toString(toStartOfMonth(d))                AS month,
    formatDateTime(toStartOfMonth(d), '%b %Y') AS month_label,
    round(quantileExact(0.5)(etf_ratio), 2)    AS etf_median_ratio,
    round(quantileExact(0.5)(stock_ratio), 2)  AS stock_median_ratio
FROM daily
GROUP BY month, month_label
ORDER BY month
Run this yourself

The panel runs from Aug 2025 to Jul 2026. At both ends the ETF basket's median daily ratio sat near or above 1.0, 1.52 in the first month and 1.49 in the last. The single stock basket stayed below 1.0 at both ends, 0.6 and 0.56, across all 12 months on the chart. That standing gap is why a benchmark has to name its category before it means anything.

What counts as a normal put/call ratio

Normal is a range, and the range belongs to a category rather than to the indicator. The panel below takes every session over the trailing twelve months and reports the median daily ratio for each basket, with the 10th and 90th percentile edges around it.

QueryWhere the daily ratio actually sits, twelve months of sessions
The exact SQL behind every number
WITH
    daily AS
    (
        SELECT
            d,
            toFloat64(sumIf(volume, right_letter = 'P' AND sym IN ('SPY', 'QQQ', 'IWM')))
                / toFloat64(sumIf(volume, right_letter = 'C' AND sym IN ('SPY', 'QQQ', 'IWM')))     AS etf_ratio,
            toFloat64(sumIf(volume, right_letter = 'P' AND sym NOT IN ('SPY', 'QQQ', 'IWM')))
                / toFloat64(sumIf(volume, right_letter = 'C' AND sym NOT IN ('SPY', 'QQQ', 'IWM'))) AS stock_ratio,
            toFloat64(sumIf(volume, right_letter = 'P'))
                / toFloat64(sumIf(volume, right_letter = 'C'))                                      AS all_ratio
        FROM
        (
            SELECT
                date                                     AS d,
                underlying_symbol                        AS sym,
                volume,
                substring(ticker, length(ticker) - 8, 1) AS right_letter
            FROM global_markets.options_greeks
            WHERE date >= '2025-08-01'
              AND date <  '2026-08-01'
              AND underlying_symbol IN ('SPY', 'QQQ', 'IWM', 'AAPL', 'MSFT', 'NVDA', 'TSLA', 'KO')
              AND volume > 0
        )
        GROUP BY d
        HAVING countIf(right_letter = 'C' AND sym IN ('SPY', 'QQQ', 'IWM')) > 0
           AND countIf(right_letter = 'C' AND sym NOT IN ('SPY', 'QQQ', 'IWM')) > 0
    )
SELECT
    p.2                                  AS category,
    round(quantileExact(0.1)(p.3), 2)    AS p10_ratio,
    round(quantileExact(0.5)(p.3), 2)    AS median_ratio,
    round(quantileExact(0.9)(p.3), 2)    AS p90_ratio
FROM
(
    SELECT arrayJoin([
        tuple(1, 'Broad market ETFs', etf_ratio),
        tuple(2, 'Single stocks',     stock_ratio),
        tuple(3, 'All eight names',   all_ratio)
    ]) AS p
    FROM daily
)
GROUP BY p.1, p.2
ORDER BY p.1
Run this yourself

For the single stock basket the median session came in at 0.58, with 0.45 at the 10th percentile and 0.76 at the 90th. The broad market ETF basket sat higher across the distribution: a median of 1.54 between edges of 1.25 and 1.86.

So is 1.20 high? Against the single stock basket, a 1.20 print sits past the 90th percentile of 0.76, which makes it unusual. Against the ETF basket it is close to routine. Against the index category, where the hedging flow described above concentrates, the same figure has to be judged against a different set of levels again. One number, and the category settles the verdict before any interpretation starts.

These ranges also drift. Percentiles computed over the trailing twelve months describe the trailing twelve months, and a benchmark range copied from an article written a decade ago describes a market with a different contract mix and almost no zero day expiry trading in it. Recomputing the percentiles over a recent window is the only honest way to call a reading high or low.

Interpretation is a separate job from calculation. A high reading gets read by some as bearish positioning and by contrarians as a crowded hedge, and whether a high put/call ratio is bullish takes that argument apart properly.

Why the 21 day moving average

One session's ratio is a small sample of a noisy series, so the published version is usually smoothed. The common convention is a 21 session moving average, roughly one trading month: sum the last 21 daily ratios, divide by 21, then step the window forward a session. Ten and fifty session versions exist as well, and the length picked sets how much of a single day spike survives.

Two details are worth knowing. Averaging 21 daily ratios is not the same arithmetic as dividing a month of put volume by a month of call volume; the first weights every session equally, the second weights busy sessions more heavily. And a smoothed reading at an extreme was assembled over a month of sessions, so it leaves that extreme slowly too.

QueryDaily single stock put/call ratio against its 21 session average
The exact SQL behind every number
WITH
    daily AS
    (
        SELECT
            d,
            toFloat64(sumIf(volume, right_letter = 'P'))
                / toFloat64(sumIf(volume, right_letter = 'C')) AS raw_ratio
        FROM
        (
            SELECT
                date                                     AS d,
                volume,
                substring(ticker, length(ticker) - 8, 1) AS right_letter
            FROM global_markets.options_greeks
            WHERE date >= '2026-01-02'
              AND date <  '2026-08-01'
              AND underlying_symbol IN ('AAPL', 'MSFT', 'NVDA', 'TSLA', 'KO')
              AND volume > 0
        )
        GROUP BY d
        HAVING countIf(right_letter = 'C') > 0
    )
SELECT
    session_date,
    day_label,
    daily_ratio,
    ma21_ratio
FROM
(
    SELECT
        d,
        toString(d)                                                 AS session_date,
        concat(formatDateTime(d, '%b '), toString(toDayOfMonth(d))) AS day_label,
        round(raw_ratio, 2)                                         AS daily_ratio,
        round(avg(raw_ratio) OVER (ORDER BY d ROWS BETWEEN 20 PRECEDING AND CURRENT ROW), 2) AS ma21_ratio
    FROM daily
)
WHERE d >= '2026-04-01'
ORDER BY d
Run this yourself

The jagged line is the daily ratio for the single stock basket, the smooth one its 21 session average. On the first session shown, Apr 1, the daily print was 1.04 against a smoothed 0.81. On Jul 31 the pair read 0.56 and 0.58. Across 84 sessions the average travels a fraction of the distance the raw series covers, which is the entire point of quoting the smoothed number.

How these panels count

Contract type comes from the option symbol itself: the letter sitting in front of the eight digit strike code is C for a call and P for a put. Only contracts with reported volume for the session enter a count, so a strike that never traded adds nothing to either side. The first panel divides the month's total put volume by the month's total call volume for each name. The remaining panels compute one ratio per session first, then summarize those sessions, which matches how a published moving average is built. Baskets: SPY, QQQ and IWM on the broad market side, with AAPL, MSFT, NVDA, TSLA and KO on the single stock side. Every panel carries the exact SQL that produced it.

FAQ

How do you calculate the put/call ratio?

Divide the number of put contracts by the number of call contracts over the same window. Most published versions use the session's volume, so a reading of 0.65 means 65 puts traded for every 100 calls. The open interest version uses contracts outstanding instead of contracts traded and answers a different question.

Is a put/call ratio above 1 high?

It depends on the category. For the single stock basket in the panels above, the 90th percentile of daily readings sits at 0.76, so prints above that level are uncommon. For broad market ETFs and index options, where portfolio hedging concentrates on the put side, readings around and above 1 are ordinary.

What is the difference between the volume and open interest put/call ratio?

Volume counts contracts that traded during the session and resets each morning. Open interest counts contracts that remain open and carries over from day to day. The volume version can double inside one session while the open interest version shifts by a few percent, so the two often point in different directions on the same day.

Which put/call ratio does the financial press quote?

Usually the Cboe equity put/call ratio or the total put/call ratio, and most often as a 21 session moving average rather than a raw daily print. The four Cboe categories run at different levels, so a quoted figure with no category attached cannot be measured against any benchmark.


Every panel on this page ships with the SQL that produced it, so each count can be checked line by line. To run the same arithmetic on a different name or a longer window, ask for it in plain English on the Strasmore terminal.

#put call ratio#options#sentiment#cboe#options volume