Open to everyone · last session Nov 13, 2026

Historical options data to download: max pain, GEX, implied volatility and put/call, session by session

For every stock and ETF on the site, the option market's positioning as one CSV row per session — computed from end-of-day option chains, years deep, no account and no payment.

73tickers with history from 2008
401from 2013 or earlier
482from 2020 or earlier
1,478stocks and ETFs in all

How to download

Open the ticker's page — stocks or ETFs — and use its Download box: one .zip with every file, a README and the column guide, or each file as CSV. A new row is added after each close.

TickerNameFromSessionsFiles
SPYS&P 500Jan 2, 20084,745SPY.zip
QQQNasdaq 100Mar 23, 20113,934QQQ.zip
AAPLAppleJan 2, 20084,642AAPL.zip
MSFTMicrosoftJan 2, 20084,746MSFT.zip
NVDANVIDIAJan 2, 20084,746NVDA.zip
AMZNAmazon.comJan 2, 20084,645AMZN.zip
GOOGLAlphabetJan 2, 20133,298GOOGL.zip
METAMeta PlatformsJul 8, 20211,256META.zip
TSLATeslaJul 8, 20104,113TSLA.zip
AMDAdvanced Micro DevicesJan 2, 20084,745AMD.zip
AVGOBroadcomAug 24, 20094,332AVGO.zip
NFLXNetflixJan 2, 20084,745NFLX.zip
PLTRPalantir TechnologiesOct 6, 20201,535PLTR.zip
JPMJPMorgan Chase &Jan 2, 20084,601JPM.zip
BACBank of AmericaJan 2, 20084,744BAC.zip
XOMExxonMobil HoldingsJan 2, 20084,746XOM.zip
INTCIntelJan 2, 20133,439INTC.zip
COINCoinbase GlobalApr 20, 20211,391COIN.zip
MSTRStrategyJan 2, 20133,440MSTR.zip
BAThe BoeingJan 2, 20084,744BA.zip
DISThe Walt DisneyJan 2, 20084,746DIS.zip
WMTWalmartJan 2, 20084,652WMT.zip

Every other ticker: the stock directory and the ETF directory.

What is in each ticker's download

The sample for code: GitHub and Kaggle

SPY, QQQ and 20 large stocks (AAPL, MSFT, NVDA, AMZN, GOOGL, META, TSLA, AMD, AVGO, NFLX, PLTR, JPM, BAC, XOM, INTC, COIN, MSTR, BA, DIS, WMT) — the same daily option series, with the column guide and a Python notebook, refreshed every week. Use it when a script, a notebook or a backtest must read the data by itself.

The repository and the dataset are being published; their addresses will be here.

Loading it in Python

Download the ticker's .zip, unpack it, and read the series with pandas. Strike levels are raw strikes: multiply them by split_factor before you compare them with the close.

import pandas as pd

df = pd.read_csv("SPY.csv", parse_dates=["date"]).set_index("date")
for c in ["max_pain_front", "max_pain_monthly", "call_wall_near", "put_wall_near", "gamma_flip"]:
    df[c] = df[c] * df["split_factor"]          # levels on the same scale as the close

print(df[["close", "max_pain_monthly", "gex", "pc_oi_ratio", "iv30"]].tail())

Read this before a backtest

Every column of the daily option series

The same guide travels in every .zip as _catalog.csv.

Price 5
ColumnUnitWhat it is
dateMM/DD/YYYYSession — The trading session the chain was captured for (after the close).
close$Close — Daily close, Daily price file. Where the price file has no bar for one of the newest sessions yet, the option chain's own price (see bar_from_chain); blank where it has none for an older one.
spot$Chain spot — The underlying price the option chain was priced on — NOT split-adjusted, so it is in the same money as the strikes below. For a future: the price of the ONE contract month the series follows (the month that holds the option open interest), which can differ from the front-month close beside it.
split_factorratioSplit factor — Close ÷ chain spot as a level, held at exactly 1 unless a stock split separates the two (e.g. 0.25 before a 4:1 split). Multiply any strike level by it to draw it on the split-adjusted price chart. A session whose chain price disagrees with this level is flagged (`chain_flag` 4), not explained as a split. Blank for futures.
bar_from_chain1 or blankClose from the chain — 1 = the Daily price file had no bar for this session yet (the vendor's prices arrive later than the chain), so open, high, low and close are the option chain's own underlying price (× split_factor) and volume is blank. Only the newest sessions get one, at most 10, and only on a usable capture; never on a future (its chain is priced on the contract month that holds the options, not the front month of the price file). The night the real bar arrives it replaces this one. Blank on every other session.
Implied volatility 19
ColumnUnitWhat it is
iv30decimalIV 30d — At-the-money implied volatility at a constant 30 days, interpolated across expiries. 0.25 = 25 %. The headline IV number. Blank where the expiries around 30 days have no usable quote — most of 2008–2009, when the vendor's IV is its failed-solve value.
iv10decimalIV 10d — Constant-maturity ATM IV, 10 days.
iv20decimalIV 20d — Constant-maturity ATM IV, 20 days.
iv60decimalIV 60d — Constant-maturity ATM IV, 60 days.
iv90decimalIV 90d — Constant-maturity ATM IV, 90 days.
iv180decimalIV 180d — Constant-maturity ATM IV, 180 days.
iv_rank_1y0-100IV rank (1y) — Where today's IV 30d sits between its lowest (0) and highest (100) value of the last 252 sessions, today included. Blank until 126 sessions exist.
iv_pctl_1y%IV percentile (1y) — Share of the previous 252 sessions whose IV 30d was BELOW today's. Less sensitive to one spike than IV rank.
hv20decimalRealised vol 20d — Historical (realised) volatility: annualised standard deviation of the last 20 daily log returns of the close.
iv_hv_spreaddecimalIV − HV — IV 30d minus realised vol 20d. Positive = options price more movement than the stock has been delivering (premium is rich against the recent tape).
term_slopedecimalTerm slope 90−30 — IV 90d − IV 30d. Negative = backwardation: the near term is priced as more dangerous than the far (stress, an event ahead).
term_slope_shortdecimalTerm slope 60−10 — IV 60d − IV 10d, the short end of the curve.
skew25decimal25Δ skew 30d — 25-delta put IV − 25-delta call IV at 30 days. Positive = puts cost more than calls (demand for downside protection).
front_atm_ivdecimalFront ATM IV — ATM IV of the nearest live expiry (jumps around earnings and at roll).
front_skew25decimalFront 25Δ skew — 25Δ put − call IV on the nearest expiry.
exp_move_30d$Expected move 30d — One-standard-deviation move the options price over 30 days, in dollars of spot (spot × IV30 × √(30/365)).
exp_move_30d_pct%Expected move 30d % — The same move as a percent of spot.
exp_move_front$Expected move to the front expiry — One-standard-deviation move the options price between now and the nearest expiry, in dollars of spot, at that expiry's own ATM IV.
front_dtedaysDays to the front expiry — Calendar days to the nearest live expiry — the horizon of the column before.
Open interest & volume 21
ColumnUnitWhat it is
call_oicontractsCall OI — Call open interest, all live expiries (the contracts expiring that day are left out — see `oi_0dte_share`). As published that session = positions at the PREVIOUS session's close (OCC publishes overnight).
put_oicontractsPut OI — Put open interest, same basis as call OI.
total_oicontractsTotal OI — Call + put open interest.
call_oi_chgcontractsCall OI change — Daily OI flow: call OI minus the previous session's figure — the net call contracts opened (+) or closed (−). Because OI is published overnight this is mostly the PREVIOUS session's trading. Drops on expiry days include contracts that simply expired. Blank across a gap of more than 5 calendar days.
put_oi_chgcontractsPut OI change — Daily OI flow for puts, same rules as call OI change.
total_oi_chgcontractsTotal OI change — Call + put OI change.
call_volcontractsCall volume — Call contracts traded this session, every expiry — the contracts expiring that day included (on an index ETF they are most of the day).
put_volcontractsPut volume — Put contracts traded this session, every expiry, same-day expiries included.
total_volcontractsTotal option volume — All option contracts traded this session: call volume + put volume, same-day expiries included.
rel_vol_20ratioRelative option volume — Total option volume ÷ its average over the previous 20 usable sessions. 1 = normal, 3 = three times normal ("unusual activity").
pc_oi_ratioratioPut/call OI ratio — Put OI ÷ call OI.
pc_vol_ratioratioPut/call volume ratio — Put volume ÷ call volume, all contracts traded.
put_share_oi%Put share of OI — Puts as a percent of all OI — the bounded form of the P/C ratio (50 = balanced).
vol_oi_ratioratioTurnover — Volume ÷ open interest, both over every contract (same-day expiries included): how fast the book is turning over.
call_premium$Call premium traded — Σ mid × volume × 100 over calls: dollars spent on calls this session, priced at the closing mid. The contracts expiring that day are NOT in it: at the close their mid is what is left of them, not what they traded at.
put_premium$Put premium traded — Dollars spent on puts this session, same basis as call premium (closing mid, same-day expiries left out).
net_premium$Net premium — Call premium − put premium. Positive = more money went through calls.
delta_flow$Delta-weighted volume — Σ delta × volume × 100 × spot, at the closing delta, over the live expiries (a contract expiring that day closes at a delta of 0 or 1, which says where the price ended, not which way it traded): the share-equivalent dollars of the day's option trading. Positive = the trading leaned long delta (calls at their delta outweighed puts at theirs). Does not know buyer from seller.
near_oi_share%OI within 45 days — Percent of open interest expiring within 45 days.
front_oi_share%OI in the front expiry — Percent of open interest in the nearest live expiry.
oi_0dte_share%0DTE share of OI — Percent of OI in contracts expiring that day. Those positions are gone by the next morning, so open interest, the greeks (GEX, DEX, VEX, CHEX), the walls, max pain, premium and delta flow leave them out; the volume columns count them.
Dealer positioning (greeks) 26
ColumnUnitWhat it is
gex$ per 1% moveDealer gamma (GEX) — Dealer gamma exposure, dollars of hedging per 1 % move, assuming dealers are long calls and short puts. Positive = dealers dampen moves (sell rallies, buy dips); negative = they amplify them. It is the slope AT the close: when the gamma flip is nearer than 1 %, a full 1 % move hedges less than this number.
gex_0_14d$ per 1% moveGEX 0–14 days — The same gamma from expiries 0–14 days out only — the short-dated gamma that moves the tape.
gex_per_oi$ per contractGEX per contract — GEX ÷ total OI: gamma with the size of the book divided out, comparable across time.
gamma_regime+1 / −1Gamma regime — +1 when repriced dealer gamma at spot is positive (long-gamma, dampened), −1 when negative (short-gamma, amplified).
spot_vs_flip_pct%Spot vs gamma flip — (spot − flip) ÷ spot. Positive = spot above the flip.
dex$Delta exposure (DEX) — Book delta in dollars (calls + puts, delta × OI × 100 × spot).
vannashares per vol pointDealer vanna (shares) — Dealer vanna (calls − puts): how dealers' delta changes when IV moves one point, in shares of the underlying. Positive: falling IV makes dealers buy. In dollars this is the column `vex`.
charmshares per dayDealer charm (shares) — Dealer charm (calls − puts): how dealers' delta changes as one calendar day passes, in shares of the underlying. NEGATIVE (the usual state): the options' delta decays, so the passing days make dealers BUY shares back; positive: time makes them sell. In dollars this is the column `chex`.
vega$ per vol pointBook vega — Dollar vega of all open interest: what a one-point IV move is worth to the book.
gex_15_45d$ per 1% moveGEX 15–45 days — Dealer gamma from the expiries 15–45 days out — the monthly cycle.
gex_46_180d$ per 1% moveGEX 46–180 days — Dealer gamma from the expiries 46–180 days out.
gex_181d_plus$ per 1% moveGEX 181+ days — Dealer gamma from the expiries more than 180 days out (LEAPS): large in dollars, slow to re-hedge. The four horizons add up to GEX.
vanna_0_14dshares per vol pointVanna 0–14 days (shares) — Dealer vanna from the expiries inside 14 days only, in shares. In dollars: `vex_0_14d`.
charm_0_14dshares per dayCharm 0–14 days (shares) — Dealer charm from the expiries inside 14 days — the hedging the passing days force into an expiry week — in shares. In dollars: `chex_0_14d`.
spot_vs_delta_flip_pct%Spot vs delta flip — (spot − delta flip) ÷ spot. Positive = spot above the delta flip.
delta_tilt−1…+1δ tilt near spot — Mean call delta + mean put delta, weighted by open interest, over the strikes within ±5 % of spot (the put keeps its minus sign). Above zero = the contracts near the money lean long.
delta_net_near$Net δ$ near spot — Σ delta × OI × 100 × spot over the strikes within ±5 % of spot, calls plus puts. It grows with the size of the book — the share in the next column divides that out.
delta_share_near−1…+1δ$ share near spot — Net δ$ ÷ total |δ$| within ±5 % of spot: −1 = all put, +1 = all call. Does not move when the book simply gets bigger.
vex$ per vol pointVanna exposure (VEX) — Dealer vanna in dollars: the stock dealers have to trade when implied volatility moves ONE point, assuming dealers are long calls and short puts (Σ vanna × OI × 100 × spot, calls − puts). It is the change in the dealers' option delta, so they trade the opposite way: positive = rising IV makes dealers sell and falling IV makes them buy; negative = the reverse.
chex$ per dayCharm exposure (CHEX) — Dealer charm in dollars: the stock dealers have to trade as ONE calendar day passes with price and IV unchanged (Σ charm × OI × 100 × spot, calls − puts). It is the change in the dealers' option delta, so they trade the opposite way: NEGATIVE (the usual state) = the passing of time makes dealers BUY that many dollars of stock; positive = it makes them sell. Largest in the days before an expiry.
vex_0_14d$ per vol pointVEX 0–14 days — Vanna exposure of the expiries inside 14 days only.
chex_0_14d$ per dayCHEX 0–14 days — Charm exposure of the expiries inside 14 days only — the hedging the passing days force into an expiry week. This is where most of the charm lives.
vex_15_45d$ per vol pointVEX 15–45 days — Vanna exposure of the expiries 15–45 days out — the monthly cycle.
chex_15_45d$ per dayCHEX 15–45 days — Charm exposure of the expiries 15–45 days out.
vex_46_180d$ per vol pointVEX 46–180 days — Vanna exposure of the expiries 46–180 days out.
chex_46_180d$ per dayCHEX 46–180 days — Charm exposure of the expiries 46–180 days out.
Levels (strikes) 37
ColumnUnitWhat it is
gamma_flip$ (strike)Gamma flip — The spot price at which dealer gamma changes sign (repriced). Above it = long-gamma territory.
call_wall$ (strike)Call wall — The strike at or above spot with the most call OI, counted over EVERY live expiry — read as resistance. Long-dated positions count as much as this week's, so it can sit far above the price (more than 25 % away on about 1 session in 7): `call_wall_pct` says how far, and the walls by horizon (`call_wall_0_14d`, `call_wall_15_45d`) are the ones near the price.
call_wall_oicontractsCall wall OI — Open interest at the call wall.
call_wall_2$ (strike)Call wall 2 — The next-biggest call-OI strike above the call wall.
put_wall$ (strike)Put wall — The strike at or below spot with the most put OI, counted over EVERY live expiry — read as support. Far crash hedges count as much as this week's puts, so it can sit far below the price (more than 25 % away on about 1 session in 5; SPY's sits a median 21 % below): `put_wall_pct` says how far, and the walls by horizon (`put_wall_0_14d`, `put_wall_15_45d`) are the ones near the price.
put_wall_oicontractsPut wall OI — Open interest at the put wall.
put_wall_2$ (strike)Put wall 2 — The next-biggest put-OI strike below the put wall.
gamma_wall_up$ (strike)Gamma wall above — Strike at or above spot with the largest net dealer gamma.
gamma_wall_down$ (strike)Gamma wall below — Strike at or below spot with the most negative net dealer gamma.
max_pain_front$ (strike)Max pain (front) — Strike where option holders of the nearest expiry lose the most at expiry.
max_pain_monthly$ (strike)Max pain (monthly) — Max pain of the nearest standard monthly expiry (the third Friday — listed as the Saturday after it before 2015) at least 7 days out.
call_wall_pct%Distance to call wall — (call wall − spot) ÷ spot.
put_wall_pct%Distance to put wall — (spot − put wall) ÷ spot.
max_pain_front_pct%Max pain vs spot — (front max pain − spot) ÷ spot. Positive = the pin sits above spot.
delta_flip$ (strike)Delta flip — The spot price at which the delta of the whole book (repriced) crosses zero.
call_wall_3$ (strike)Call wall 3 — The third call-OI strike above spot.
put_wall_3$ (strike)Put wall 3 — The third put-OI strike below spot.
call_oi_peak$ (strike)Call OI peak — The strike with the most call OI anywhere, spot ignored. When it sits BELOW spot, price has run over the biggest call strike.
put_oi_peak$ (strike)Put OI peak — The strike with the most put OI anywhere, spot ignored. When it sits ABOVE spot, price has fallen through the biggest put strike.
max_pain_all$ (strike)Max pain (all expiries) — Max pain over every live expiry blended.
call_wall_0_14d$ (strike)Call wall 0–14 days — The call wall of the expiries inside 14 days only — the wall that matters this week and next.
put_wall_0_14d$ (strike)Put wall 0–14 days — The put wall of the expiries inside 14 days only.
max_pain_0_14d$ (strike)Max pain 0–14 days — Max pain of the expiries inside 14 days, blended.
call_wall_15_45d$ (strike)Call wall 15–45 days — The call wall of the expiries 15–45 days out — the monthly cycle.
put_wall_15_45d$ (strike)Put wall 15–45 days — The put wall of the expiries 15–45 days out.
max_pain_15_45d$ (strike)Max pain 15–45 days — Max pain of the expiries 15–45 days out, blended.
call_wall_46_180d$ (strike)Call wall 46–180 days — The call wall of the expiries 46–180 days out.
put_wall_46_180d$ (strike)Put wall 46–180 days — The put wall of the expiries 46–180 days out.
max_pain_46_180d$ (strike)Max pain 46–180 days — Max pain of the expiries 46–180 days out, blended.
call_wall_near$ (strike)Call wall (near) — The strike at or above spot with the most call OI among the strikes within 25 % of the price (the strike table's own window) — the same rule as `call_wall`, without the far strikes. Where the whole-book call wall is within 25 % the two are the same strike; where it is not, `call_wall` is a far position (a long-dated bet or hedge) and this is the wall the price meets first. The site's pages draw this one.
call_wall_near_oicontractsCall wall (near) OI — Open interest at the near call wall.
call_wall_near_pct%Distance to the near call wall — (near call wall − spot) ÷ spot. Never more than 25.
call_wall_near_2$ (strike)Call wall 2 (near) — The next-biggest call-OI strike above the near call wall, within 25 % of the price.
put_wall_near$ (strike)Put wall (near) — The strike at or below spot with the most put OI among the strikes within 25 % of the price — the same rule as `put_wall`, without the far crash hedges. Where the whole-book put wall is within 25 % the two are the same strike. The site's pages draw this one.
put_wall_near_oicontractsPut wall (near) OI — Open interest at the near put wall.
put_wall_near_pct%Distance to the near put wall — (spot − near put wall) ÷ spot. Never more than 25.
put_wall_near_2$ (strike)Put wall 2 (near) — The next-biggest put-OI strike below the near put wall, within 25 % of the price.
Chain quality 5
ColumnUnitWhat it is
chain_gradeA–FChain grade — The data-trust grade of this session's chain (A best), from its quotes: spreads, crossed markets, missing IV. Filter studies on it: before 2010 the vendor's IV is unreliable and few sessions grade A. It does not see a repeated or partial capture — `chain_flag` does.
chain_score0-100Chain score — The 0–100 score behind the grade.
chain_flag0–5Capture flag — 0 = a normal session. 1 to 4 = the chain captured that session is not a usable picture of the book, so EVERY option-market cell of the row is left blank (the price cells stay) and the row is skipped by the rolling columns: 1 = partial capture (under half the usual contracts) · 2 = the previous session's capture served again (same spot, open interest and volume to the contract) · 3 = a one-day jump in open interest, gone the next day · 4 = the chain's underlying price is more than 5 % away from the day's close, or its open interest sits nowhere near that price (strikes and price in different money — a split day, a vendor price error). 5 = the contracts that expired that day are missing from the capture: only the volume cells (call, put and total volume, the put/call volume ratio, relative volume, turnover) are blank, the rest of the row is good.
expiriesnLive expiries — Number of live expiries in the chain that session.
strikesnDistinct strikes — Number of distinct live strikes.
Call side vs put side 5
ColumnUnitWhat it is
adj_atm_pct%ATM call vs put — The call against the put at the two strikes around spot, nearest expiry, each repriced to the same distance from spot; percent of the cheaper one, + = the call costs more. At the money this is mostly the carry (interest − dividend − borrow), not a view.
adj_net_dollar$Call − put, in dollars — Σ (call − put) over every pair of strikes at equal distance from spot within ±25 %, every live expiry. + = the call side costs more. A raw sum: it grows with the stock price, the interest rate and the number of long-dated expiries.
adj_net_rungspairsCall − put, by count — Pairs where the call costs more minus pairs where the put does — how WIDELY one side is dearer, one vote per pair however thin.
delta_price25%Price of delta, 25Δ (30d) — What the 25-delta call costs against the 25-delta put at 30 days, percent of the cheaper one: + = the call's delta is dearer, − = the put's. Its resting value is NOT zero — with no skew at all it reads several percent put-dear, more when IV is high — so read the next column for the skew itself.
delta_price25_skewpointsPrice of delta over its floor — The column before minus what a smile with no skew would read, in points. Below zero = puts are bid beyond the plain geometry; above zero = calls are. The dollar companion of the 25Δ skew.

Questions and answers

Where can I download historical options data without an account?

On every stock and ETF page of this site: a .zip with the ticker's daily option series and its strike, expiry and horizon tables, or each file as CSV. No account and no payment — press the button. The series of the largest names starts in January 2008.

Is there historical max pain data?

Yes. Every row of the daily option series carries max pain for the front expiry (max_pain_front), for the monthly expiry (max_pain_monthly), for all expiries blended (max_pain_all) and for the 0–14, 15–45 and 46–180 day horizons, with the close of the same session next to it.

Is there historical gamma exposure (GEX) data?

Yes: net dealer gamma (gex) per 1% move, split by horizon (gex_0_14d, gex_15_45d, gex_46_180d, gex_181d_plus), the gamma flip, the gamma regime, and vanna, charm and delta exposure — one row per session.

Is there put/call ratio historical data?

Yes: the put/call ratio of open interest (pc_oi_ratio) and of volume (pc_vol_ratio), with call and put open interest, their daily change and volume, for every session.

Is there historical implied volatility data?

Yes: at-the-money implied volatility at constant 10, 20, 30, 60, 90 and 180 days, IV rank and IV percentile over a year, 20-day realised volatility, skew and the term slope.

Can I use it for backtesting?

Yes, with care: every figure is end-of-day, nothing in a row uses a later session, a blank cell means "no value" (never zero), open interest is the previous close, and strike levels are raw strikes — multiply by split_factor before comparing them with the close. The rules are listed on this page.

Do you offer raw option chains or tick data?

No. What you download is what we compute from end-of-day chains: the daily series, and the last session strike by strike and expiry by expiry. Raw chains, quotes and intraday data are not part of it.

Can a script download the files?

The files are for people: scripts that announce themselves are turned away, and each address may take 60 files an hour and 400 a day. For code, take the sample (SPY, QQQ and 20 large stocks, refreshed every week) or download a ticker's .zip in the browser and read the CSV from disk.

Data for research and education, not investment advice — see the terms. What the figures mean: ten short lessons.