What Is the Put-Call Ratio? A Data Guide
The put-call ratio is puts traded divided by calls traded. See its real range on the full US options tape: by expiration, index vs equity, and against a decade.
The put-call ratio is the day's put volume divided by its call volume: how many bearish-side contracts traded for every bullish-side one. A reading above 1.0 means more puts than calls changed hands; well below 1.0 means calls dominated. Most explanations stop at the definition and a folk rule of thumb. This page computes the real thing, every listed US option contract, day by day, then splits it the way the professionals do: index versus equity, expiration by expiration, and against a decade of history.
How is the put-call ratio calculated?
Take every option trade in a session, sum the contract volume in puts, sum it in calls, divide. A put gains value as the underlying falls; a call gains as it rises, so the ratio is read as a rough temperature of downside positioning versus upside positioning.
The arithmetic is deliberately simple. Say a stock trades 40,000 put contracts and 60,000 call contracts in a session: 40,000 ÷ 60,000 = 0.67, two puts for every three calls. Keep calls at 60,000 and lift puts to 90,000 and the ratio becomes 1.5. That is the whole formula; everything hard here is in the interpretation, not the division.
Two details hide inside the word "volume":
- Volume, not open interest. The standard ratio counts contracts traded that day. A variant uses open interest, contracts outstanding, which moves far more slowly. Know which one a chart is showing you.
- Every trade has two sides. A put bought to open, a put sold to close a hedge, and a put written for income all print the same volume. The ratio counts activity, not intent.
What does the market-wide put-call ratio look like?
Computed across every listed US equity, ETF and index option, day by day, from June 1 through the last complete session in our tape:
| day | day_label | put_call_ratio | contracts_mm |
|---|---|---|---|
| 2026-06-01 | June 1 | 0.589 | 70.8 |
| 2026-06-02 | June 2 | 0.6 | 61.7 |
| 2026-06-03 | June 3 | 0.651 | 63.6 |
| 2026-06-04 | June 4 | 0.679 | 66.7 |
| 2026-06-05 | June 5 | 0.866 | 103.1 |
| 2026-06-08 | June 8 | 0.765 | 66 |
| 2026-06-09 | June 9 | 0.861 | 82.4 |
| 2026-06-10 | June 10 | 0.864 | 67.8 |
| 2026-06-11 | June 11 | 0.808 | 70 |
| 2026-06-12 | June 12 | 0.654 | 76.3 |
| 2026-06-15 | June 15 | 0.714 | 73.3 |
| 2026-06-16 | June 16 | 0.79 | 66 |
| 2026-06-17 | June 17 | 0.853 | 72.3 |
| 2026-06-18 | June 18 | 0.793 | 79.2 |
| 2026-06-22 | June 22 | 0.755 | 65.3 |
| 2026-06-23 | June 23 | 0.884 | 60.4 |
| 2026-06-24 | June 24 | 0.867 | 68.4 |
| 2026-06-25 | June 25 | 0.923 | 65.9 |
| 2026-06-26 | June 26 | 0.895 | 71.9 |
| 2026-06-29 | June 29 | 0.794 | 65.7 |
The exact SQL behind every number
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS day,
concat(monthName(day), ' ', toString(toDayOfMonth(day))) AS day_label,
round(sumIf(toFloat64(volume), substring(ticker, length(ticker) - 8, 1) = 'P')
/ sumIf(toFloat64(volume), substring(ticker, length(ticker) - 8, 1) = 'C'), 3) AS put_call_ratio,
round(sum(toFloat64(volume)) / 1e6, 1) AS contracts_mm
FROM global_markets.options_minute_aggs
WHERE window_start >= '2026-06-01 04:00:00'
AND window_start < '2026-07-11 04:00:00'
GROUP BY day
ORDER BY dayThe series opened the window at 0.589 on June 1, closed it at 0.686 on July 10, and never crossed 1.0 in between, calls out-traded puts on all 28 sessions. That is the first practical lesson: 1.0 is not the neutral midpoint a beginner assumes. The information lives in the ratio's movement inside its own range. Here is that range for the completed month of June:
| june_median | june_high | june_high_day | june_low | june_low_day |
|---|---|---|---|---|
| 0.793 | 0.923 | June 25 | 0.589 | June 1 |
The exact SQL behind every number
WITH daily AS (
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS day,
sumIf(toFloat64(volume), substring(ticker, length(ticker) - 8, 1) = 'P')
/ sumIf(toFloat64(volume), substring(ticker, length(ticker) - 8, 1) = 'C') AS ratio
FROM global_markets.options_minute_aggs
WHERE window_start >= '2026-06-01 04:00:00'
AND window_start < '2026-07-01 04:00:00'
GROUP BY day
)
SELECT round(quantileDeterministic(0.5)(ratio, cityHash64(toString(day))), 3) AS june_median,
round(max(ratio), 3) AS june_high,
concat(monthName(argMax(day, ratio)), ' ', toString(toDayOfMonth(argMax(day, ratio)))) AS june_high_day,
round(min(ratio), 3) AS june_low,
concat(monthName(argMin(day, ratio)), ' ', toString(toDayOfMonth(argMin(day, ratio)))) AS june_low_day
FROM dailyJune's median sat at 0.793, inside a band from 0.589 (on June 1) up to 0.923 (on June 25). Now the session everyone remembers from the month, the June 5 selloff, documented in the June 2026 recap. Options traded 103.1 million contracts, the busiest session of the window, and the ratio jumped to 0.866 from 0.679 the day before. The selloff and the put-heavy, record-volume session were the same session: the ratio registered the surge of downside positioning as it happened.
Two practical notes. The level drifts with the mix of products trading that week, so small day-to-day wiggles inside the band carry little meaning alone. And total volume is essential context, the same ratio on double the contracts is a much louder statement, which is why the panel carries contract counts alongside the ratio.
CBOE, ISEE and the other named put-call benchmarks
If your broker or a financial-news chart quotes "the" put-call ratio, it is almost certainly quoting one of a handful of named, published series, and they measure different populations:
- $CPC, the CBOE total put/call ratio: every option traded on the CBOE exchanges, puts over calls.
- $CPCE, the equity-only ratio: options on individual stocks. Physically-settled ETF options such as SPY sit on the equity side of this line, even though traders use them like index products.
- $CPCI, the index-only ratio: cash-settled index options (SPX, NDX, RUT, VIX and friends).
- ISEE, the ISE Sentiment Index, built the other way up: calls divided by puts, times 100, counted only from opening long customer purchases. A high ISEE is call-heavy; a high $CPC is put-heavy. Read one as if it were the other and the message inverts.
CBOE's own equity/index line puts ETF options like SPY on the equity side. The panel below draws the boundary differently, carving broad-market ETFs out from single stocks: the two trade nothing alike. Every June 2026 contract, sorted into three populations:
| population | put_call_ratio | contracts_mm | pct_of_volume |
|---|---|---|---|
| Broad-market ETFs (SPY, QQQ, IWM, DIA) | 1.175 | 476.3 | 32.2 |
| Index options (SPX, VIX, NDX) | 1.096 | 115.7 | 7.8 |
| Single stocks and other ETFs | 0.588 | 885.8 | 59.9 |
The exact SQL behind every number
WITH substring(ticker, 3, length(ticker) - 17) AS root
SELECT multiIf(root IN ('SPX', 'SPXW', 'XSP', 'NDX', 'NDXP', 'RUT', 'RUTW', 'VIX', 'VIXW', 'DJX', 'OEX', 'XEO'), 'Index options (SPX, VIX, NDX)',
root IN ('SPY', 'QQQ', 'IWM', 'DIA'), 'Broad-market ETFs (SPY, QQQ, IWM, DIA)',
'Single stocks and other ETFs') AS population,
round(sumIf(toFloat64(volume), substring(ticker, length(ticker) - 8, 1) = 'P')
/ sumIf(toFloat64(volume), substring(ticker, length(ticker) - 8, 1) = 'C'), 3) AS put_call_ratio,
round(sum(toFloat64(volume)) / 1e6, 1) AS contracts_mm,
round(100 * sum(toFloat64(volume)) / sum(sum(toFloat64(volume))) OVER (), 1) AS pct_of_volume
FROM global_markets.options_minute_aggs
WHERE window_start >= '2026-06-01 04:00:00'
AND window_start < '2026-07-01 04:00:00'
GROUP BY population
ORDER BY put_call_ratio DESCThe two index-linked populations both ran put-heavy, broad-market ETFs at 1.175 and cash-settled index options at 1.096, each above 1.0, while single stocks and everything else printed 0.588, barely more than one put per two calls. The mechanism is structural: index products are the standard vehicles for portfolio hedging, and hedging is done with puts; single stocks attract the speculative call buying. The volume shares matter too, single stocks and other ETFs carried 59.9% of June's contracts, so a "total" ratio is mostly an equity ratio wearing an index hat.
The ratio depends on what you point it at
Zoom in one more level. The same measurement, June 2026, pointed at five of the most active names:
| underlying | put_call_ratio | contracts_mm |
|---|---|---|
| SPY | 1.16 | 263.2 |
| QQQ | 1.11 | 165.9 |
| TSLA | 0.73 | 58 |
| AAPL | 0.64 | 27 |
| NVDA | 0.56 | 64.6 |
The exact SQL behind every number
SELECT multiIf(ticker LIKE 'O:SPY2%', 'SPY',
ticker LIKE 'O:QQQ2%', 'QQQ',
ticker LIKE 'O:NVDA2%', 'NVDA',
ticker LIKE 'O:TSLA2%', 'TSLA',
'AAPL') AS underlying,
round(sumIf(toFloat64(volume), substring(ticker, length(ticker) - 8, 1) = 'P')
/ sumIf(toFloat64(volume), substring(ticker, length(ticker) - 8, 1) = 'C'), 2) AS put_call_ratio,
round(sum(toFloat64(volume)) / 1e6, 1) AS contracts_mm
FROM global_markets.options_minute_aggs
WHERE window_start >= '2026-06-01 04:00:00'
AND window_start < '2026-07-01 04:00:00'
AND (ticker LIKE 'O:SPY2%' OR ticker LIKE 'O:QQQ2%' OR ticker LIKE 'O:NVDA2%'
OR ticker LIKE 'O:TSLA2%' OR ticker LIKE 'O:AAPL2%')
GROUP BY underlying
ORDER BY put_call_ratio DESCSPY ran the most put-heavy of the five at 1.16; NVDA sat at just 0.56. Comparing one ticker's ratio with another's is close to meaningless, the useful comparison is a ticker against its own history.
Does the put-call ratio change with expiration?
A day's volume is not one homogeneous pile: some contracts expire in hours, some in years. Sorting June's volume by days to expiration, see what DTE means, separates the hedges from the lottery tickets:
| expiry_bucket | put_call_ratio | contracts_mm | pct_of_volume |
|---|---|---|---|
| 0DTE (expires today) | 0.957 | 506.3 | 34.3 |
| 1-7 days | 0.756 | 406 | 27.5 |
| 8-30 days | 0.717 | 261.2 | 17.7 |
| 31-90 days | 0.634 | 164.3 | 11.1 |
| 91+ days | 0.564 | 140 | 9.5 |
The exact SQL behind every number
WITH toDate(toTimeZone(window_start, 'America/New_York')) AS trade_day,
toDate(concat('20', substring(ticker, length(ticker) - 14, 2), '-',
substring(ticker, length(ticker) - 12, 2), '-',
substring(ticker, length(ticker) - 10, 2))) AS expiry,
dateDiff('day', trade_day, expiry) AS dte
SELECT multiIf(dte <= 0, '0DTE (expires today)', dte <= 7, '1-7 days', dte <= 30, '8-30 days',
dte <= 90, '31-90 days', '91+ days') AS expiry_bucket,
round(sumIf(toFloat64(volume), substring(ticker, length(ticker) - 8, 1) = 'P')
/ sumIf(toFloat64(volume), substring(ticker, length(ticker) - 8, 1) = 'C'), 3) AS put_call_ratio,
round(sum(toFloat64(volume)) / 1e6, 1) AS contracts_mm,
round(100 * sum(toFloat64(volume)) / sum(sum(toFloat64(volume))) OVER (), 1) AS pct_of_volume
FROM global_markets.options_minute_aggs
WHERE window_start >= '2026-06-01 04:00:00'
AND window_start < '2026-07-01 04:00:00'
GROUP BY expiry_bucket
ORDER BY min(dte)The ratio falls at every step out the calendar. Contracts expiring the same day, 0DTE options, printed 0.957, the put-heaviest bucket of the five, and they alone carried 34.3% of June's total volume. One to seven days out, the ratio drops to 0.756; at 8–30 days it is 0.717; at 31–90 days 0.634; and in the 91-days-and-out bucket, the LEAPS end of the curve, it bottoms at 0.564, the most call-heavy corner of the market.
That table quietly rewrites the folk interpretation. A market-wide ratio is a blend across expirations whose mix changes week to week: a heavy expiration Friday shifts weight toward the short end and the headline number moves, with no change in how anxious anyone is. Compare like with like. Expiration cuts the other way too: where the ratio sums a day's flow into a single number, max pain reads the open interest parked at each individual strike into that same Friday, so the two describe different halves of the same expiry.
How extreme is a reading, historically?
Six weeks cannot tell you whether a reading is rare. For that you need years, so here is the longest-running, most-traded option family in the market, SPY, with the median, low and high of its daily put-call ratio for every full year in our options tape:
| year | sessions | median_ratio | low | high |
|---|---|---|---|---|
| 2015 | 252 | 1.754 | 0.987 | 2.96 |
| 2016 | 252 | 1.508 | 0.503 | 2.508 |
| 2017 | 251 | 1.597 | 0.581 | 3.541 |
| 2018 | 250 | 1.438 | 0.611 | 2.362 |
| 2019 | 252 | 1.524 | 0.693 | 2.351 |
| 2020 | 253 | 1.431 | 0.59 | 2.282 |
| 2021 | 252 | 1.314 | 0.656 | 2.167 |
| 2022 | 251 | 1.361 | 0.983 | 1.927 |
| 2023 | 250 | 1.242 | 0.693 | 1.716 |
| 2024 | 252 | 1.175 | 0.829 | 1.897 |
| 2025 | 250 | 1.168 | 0.587 | 1.793 |
| 2026 | 150 | 1.234 | 0.729 | 1.751 |
The exact SQL behind every number
WITH daily AS (
SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS day,
sumIf(toFloat64(volume), substring(ticker, length(ticker) - 8, 1) = 'P')
/ sumIf(toFloat64(volume), substring(ticker, length(ticker) - 8, 1) = 'C') AS ratio
FROM global_markets.options_minute_aggs
WHERE ticker LIKE 'O:SPY%'
GROUP BY day
HAVING sumIf(toFloat64(volume), substring(ticker, length(ticker) - 8, 1) = 'C') > 0
)
SELECT toYear(day) AS year,
count() AS sessions,
round(quantileDeterministic(0.5)(ratio, cityHash64(toString(day))), 3) AS median_ratio,
round(min(ratio), 3) AS low,
round(max(ratio), 3) AS high
FROM daily
WHERE toYear(day) >= 2015
GROUP BY year
ORDER BY yearThree things fall out of it. First, SPY's median daily ratio finished above 1.0 in every year on the table, the put-heavy tilt of index hedging is not a 2026 mood, it is the resting state of the product. Second, the level has drifted down over the decade: the median was 1.754 in 2015 and 1.168 in 2025, alongside the growth of short-dated call trading. Third, the annual ranges are wide, 2026 so far spans 0.729 to 1.751 across 150 sessions. That is the honest answer to "is today's reading extreme?": judge it against its own product's distribution, never against 1.0.
How to watch the put-call ratio for one stock
The panels above are recipes, not fixed reports. To build the ratio for a name you own:
- Pick the population. One ticker's options, not "the market", the mix effects above make blended numbers unreadable.
- Sum the day's put volume and its call volume across every strike and expiration of that ticker, then divide. In the option symbol, the letter nine characters from the end is
PorC, that one character is the whole classification. - Build the history before judging the level. A single day's 0.9 means nothing until you know that ticker's own median and range, what the SPY panel does year by year.
- Read volume alongside it. A spike on ordinary volume is noise; the same spike on the busiest tape in six weeks is the June 5 session above.
- Fix your expiration scope. All expirations, or short-dated only? Both are defensible; mixing them across days is not.
How traders read it, and the honest limits
Stated as interpretations, not laws: a rising ratio is read as growing hedging demand, and an extreme spike is read by contrarians as capitulation, the crowd has finally bought its insurance. The June 5 session shows the mechanism honestly: the ratio spiked during the selloff, not ahead of it. Over this window it behaved as a coincident thermometer, not a forecast. Test any rule of thumb against the actual series, and remember that 0DTE volume keeps changing what "normal" looks like.
FAQ
What is a normal put-call ratio?
It depends entirely on the population. Across every listed US option in June 2026 the daily market-wide median was 0.793, ranging 0.589 to 0.923, never above 1.0. Broad-market ETF options ran 1.175 over the same month while single stocks and other ETFs ran 0.588. "Normal" for SPY is not normal for a single stock.
Is a high put-call ratio bullish or bearish?
Both readings exist, and neither is a law. Taken at face value, heavy put volume is downside positioning; contrarians read extreme spikes as a sign the selling crowd is fully positioned. In the June 2026 data the spike arrived on the selloff day itself, coincident, not predictive.
Is the put-call ratio the same as the VIX or implied volatility?
No, and this is the most common mix-up. The put-call ratio is built from volume, how many contracts changed hands. The VIX and implied volatility come from option prices: how expensive those contracts are, expressed as an annualized volatility. Implied-volatility skew compares the price of downside puts with upside calls. Heavy put volume can trade at calm prices, and thin volume at panicked prices, the two gauges can disagree, and both can be right.
What are $CPC, $CPCE and $CPCI?
They are CBOE's published put-call ratios: $CPC for total volume, $CPCE for equity options (SPY and other ETFs count as equity there) and $CPCI for cash-settled index options. The split matters. Our own three-way version, which carves broad-market ETFs out from both index options and single stocks rather than following CBOE's two-way line, measured June 2026 at 1.175 for broad-market ETFs and 1.096 for index options, both above 1.0, against 0.588 for single stocks and other ETFs. ISE's ISEE is a separate, inverted index: calls over puts, opening customer buys only.
Does the put-call ratio use volume or open interest?
The standard ratio uses the day's traded volume. An open-interest variant exists and moves far more slowly, and the two can point in different directions on the same day, volume vs open interest covers the distinction.
Every value here is a stored query over the full options tape, expand any panel's SQL, or compute the ratio for your own watchlist on the Strasmore terminal.