DEV Community

Cover image for I Charted 8 Years of SPY Skew History. The Folklore Is Backwards.
tomasz dobrowolski
tomasz dobrowolski

Posted on • Originally published at flashalpha.com

I Charted 8 Years of SPY Skew History. The Folklore Is Backwards.

The 25-delta skew is the implied volatility of the 25-delta put minus the implied volatility of the 25-delta call. In one number it tells you how much more the market is paying for downside protection than for upside participation. It is the cleanest single measure of the price of crash insurance.

You can look up today's value in about four seconds. Charting its history is close to impossible, and that is the interesting part.

To know what skew was on 13 March 2020 you need the whole option chain as it stood at that timestamp: strikes, quotes, and enough of the smile to interpolate to the 25-delta wings on both sides. Not a daily close, not a settlement file. The chain, at a minute, eight years ago. That data is rare enough that "what does skew normally do around selloffs" has stayed a folklore question rather than a data question.

So I rebuilt the series. Every Friday close from May 2018 through March 2026, 413 weeks. Then I tested the folklore, and it failed in a way that turns out to be more useful than if it had passed.

Method

  • Sample: 413 Friday closes (Thursday on holiday weeks), 2018-05-04 to 2026-03-27.
  • Source: GET /v1/stock/SPY/summary?at={date}, reading the volatility.skew_25d block, which carries the 25-delta put IV, the 25-delta call IV, and their difference on the front expiry, all derived from real point-in-time quotes.
  • Flavour: this is front-expiry skew, typically 2-5 DTE. It is the most reactive skew gauge there is. A 30-60 DTE series moves the same direction with smaller amplitude.
  • Forward returns: SPY close four weeks later against the sampling close.

Here is what one observation actually looks like, from the single most extreme week in the sample:

{
  "as_of": "2020-03-13T16:00:00",
  "price": { "mid": 270.96 },
  "volatility": {
    "skew_25d": {
      "expiry": "2020-03-16",
      "days_to_expiry": 3,
      "put_25d_iv": 87.19,
      "call_25d_iv": 59.87,
      "skew_25d": 27.32,
      "smile_ratio": 1.456
    }
  },
  "macro": { "vix": { "value": 57.83 } }
}
Enter fullscreen mode Exit fullscreen mode

87 vol points bid for the put wing, 60 offered on the call wing, VIX at 57.8. That is what maximum fear looks like as a number.

Eight years of skew, by year

Year Median skew (vol pts) 90th percentile Regime
2018 (May+) 2.12 4.96 Vol-normalizing, Q4 bear
2019 1.82 3.93 Grind higher
2020 3.21 7.71 Covid crash and recovery
2021 2.72 5.00 Bull with crash memory
2022 2.36 4.72 Bear market
2023 1.22 1.96 Skew collapse, 0DTE era
2024 1.30 2.21 Grind, brief August shock
2025 2.55 4.14 Tariff shock and recovery
2026 (Q1) 3.20 4.99 Elevated hedging demand

Two regime stories fall out of this table immediately.

The 2023-24 skew collapse is the one nobody talks about. Median front skew halved against every earlier year in the sample. That is the fingerprint of the 0DTE era: systematic call overwriting and relentless daily premium selling compressed the put wing's relative price for two full years. Crash insurance was on sale, and it stayed on sale long enough that people stopped noticing.

And 2026 Q1's median of 3.20 is running at essentially Covid-year levels. That is the market's standing bid for downside protection right now.

The ten most extreme prints, 2018-2026

Date Skew (vol pts) VIX Context
2020-03-13 27.32 57.8 Covid crash, pre -12% Monday
2020-03-20 13.71 66.0 Crash week 4
2020-03-06 11.26 41.9 Crash week 2
2021-01-29 10.76 33.1 Meme-stock degrossing week
2025-04-04 9.24 45.3 Tariff shock
2020-10-30 8.07 38.0 Pre-election hedging peak
2018-10-26 8.03 24.2 October 2018 selloff
2020-03-27 7.95 65.5 First rebound week
2020-02-28 7.82 40.1 Crash week 1
2020-04-03 7.29 46.8 Bottom week

Read the Context column and notice what is missing. There is not one quiet week in this table. Every extreme print landed during a stress event, never before one.

That observation is what the next section formalizes.

The folklore test

The received wisdom is that elevated skew is a warning. Smart money is buying puts, position accordingly.

I split all 413 weeks at the 90th skew percentile and measured SPY's return over the following four weeks:

Condition Weeks Median 4-week forward return
Top-decile skew 42 +2.74%
All other weeks 371 +1.61%

The folklore fails, and it fails informatively. Extreme skew did not predict drawdowns. It marked weeks where fear was already fully priced, which pushed forward returns higher, not lower.

The mechanism is obvious once you have looked at the top-10 table. Skew explodes when everyone is bidding for puts simultaneously, and that happens mid-panic, near capitulation. By the time crash protection is historically expensive, most of the crash has already happened. You are not being warned. You are being billed.

Rebuild it

One call per date:

curl -H "X-Api-Key: $FLASHALPHA_KEY" \
  "https://historical.flashalpha.com/v1/stock/SPY/summary?at=2020-03-13"
Enter fullscreen mode Exit fullscreen mode

The whole series plus the forward-return split:

import requests
import pandas as pd

HEADERS = {"X-Api-Key": "YOUR_API_KEY"}
BASE = "https://historical.flashalpha.com/v1"


def week_row(date: str) -> dict:
    s = requests.get(
        f"{BASE}/stock/SPY/summary",
        params={"at": date},
        headers=HEADERS,
    ).json()

    skew = s["volatility"]["skew_25d"]
    return {
        "date": date,
        "skew": skew["skew_25d"],
        "put_25d_iv": skew["put_25d_iv"],
        "call_25d_iv": skew["call_25d_iv"],
        "dte": skew["days_to_expiry"],
        "close": s["price"]["mid"],
        "vix": s["macro"]["vix"]["value"],
    }


dates = pd.date_range("2018-05-04", "2026-03-27", freq="W-FRI").strftime("%Y-%m-%d")
df = pd.DataFrame([week_row(d) for d in dates])

df["fwd_4w"] = df["close"].shift(-4) / df["close"] - 1

cut = df["skew"].quantile(0.90)
top, rest = df[df["skew"] >= cut], df[df["skew"] < cut]

print(f"cutoff:           {cut:.2f} vol pts")
print(f"top-decile weeks: {len(top):>3}  median 4w fwd {top.fwd_4w.median():+.2%}")
print(f"all other weeks:  {len(rest):>3}  median 4w fwd {rest.fwd_4w.median():+.2%}")
print(df.nlargest(10, "skew")[["date", "skew", "vix"]].to_string(index=False))
Enter fullscreen mode Exit fullscreen mode

Obvious extensions, all one-line edits: resample to daily instead of weekly to catch intraweek spikes, swap in a fixed-DTE expiry from iv_term_structure for a less twitchy series, or condition the forward-return split on VIX regime rather than skew percentile.

What skew history is actually for

Since it does not warn you, here is what it does do.

Hedge-cost timing. The yearly table is a price chart for protection. Buying puts in 2023 (median 1.22) cost half what the same insurance cost in 2021. The time to own hedges is when skew is compressed, which is precisely when nobody wants them.

Contrarian context at extremes. Top-decile skew has historically been a better moment to start scaling into risk than out of it. Not a signal on its own. Useful context against a signal you already have.

Regime identification. A persistent shift in median skew, like 2023's collapse or 2026's elevation, says the options market has structurally re-priced tail risk. Strategy mix should follow.

Put-spread design. When skew is fat, put spreads that sell the inflated lower wing beat outright puts. When skew is flat, outright puts are the better hedge. The history tells you which regime you are standing in.

Honest limitations

Weekly Friday sampling misses intraweek skew spikes that resolved by the close. Front-expiry skew is deliberately twitchy; a 30-60 DTE series shows the same regimes with smaller amplitudes. And the forward-return split is descriptive, not a hypothesis test: 42 extreme weeks clustered into a handful of episodes is nowhere near 42 independent observations. March 2020 alone contributes five of the top ten.

I would rather state that plainly than dress up a five-episode sample as statistics.

Conclusion

Eight years of history replaces two pieces of folklore with two usable facts.

Skew does not warn. It confirms, loudly, at the worst possible price.

And skew regimes persist for years, which makes the level chart actionable in a way the daily print never is: cheap-skew years are when hedges should be accumulated, fat-skew weeks are when they should be monetized or spread.

Both facts were invisible until the history existed. Pull any week and check.


Originally published at flashalpha.com. Endpoint docs here; the archive replays any minute back to January 2017.

Top comments (0)