Skip to content
All library documents

Estimating SPY Risk-Neutral Densities from Weekly Options

Article Quant Q&A · Author: Jordan Wrong

Summary

The document presents a question about extracting a risk-neutral density from SPY weekly options using the R package RND. The author fits a three-lognormal mixture to American option prices and plots the resulting density over strikes around spot, but finds an unexpected shape and asks whether the calculation is wrong.

It supplies calls, puts, strikes, the extraction settings, and the density plotting procedure, so the example is reproducible in principle. However, the document contains no answer or diagnosis, and therefore does not establish what caused the unusual curve or whether the fitted density is valid. The options and model inputs are evidence of the setup, not evidence supporting a conclusion. Treat it as an unresolved calibration question; it does not explain how American exercise, option data quality, or mixture fitting may affect the inferred density.

Key ideas

  • The example estimates a risk-neutral density from SPY weekly American option prices using a three-lognormal mixture.
  • The author reports an unexpected density shape over strikes near spot and asks for a diagnosis.
  • The supplied option prices and R procedure make the analysis reproducible in principle.
  • No answer is provided, so the cause and validity of the resulting curve remain unresolved.

Tags

Full text
# Risk Neutral Density Curve for SPY Options looks very weird


# Risk Neutral Density Curve for SPY Options looks very weird












I have created a risk neutral density curve using SPY weekly options and the RND package in R. I calculated the risk neutral density for the Feb07 options. The curve looks very weird when I look at the 280-350 strikes (spot at 321.75). I thought I would have seen some negative skew here. The function extracts the mixture of three lognormals from American options.

What am I doing wrong?

Here is my reproducible R code with the data (puts, calls, strikes)

```
library(RND)

data = structure(list(puts = c(0.065, 0.075, 0.095, 0.1, 0.115, 0.125, 
0.135, 0.145, 0.155, 0.16, 0.155, 0.165, 0.185, 0.195, 0.205, 
0.22, 0.225, 0.245, 0.265, 0.285, 0.325, 0.35, 0.355, 0.395, 
0.455, 0.505, 0.575, 0.615, 0.655, 0.735, 0.845, 0.955, 1.085, 
1.16, 1.235, 1.395, 1.575, 1.78, 2.015, 2.135, 2.26, 2.54, 2.84, 
3.17, 3.535, 3.705, 3.92, 4.35, 4.83, 5.355, 5.94, 6.255, 6.58, 
7.305, 8.07, 8.915, 9.895, 10.365, 10.76, 11.74, 12.72, 13.73, 
14.725, 15.23, 15.73), strike = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 
42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 
58, 59, 60, 61, 62, 63, 64, 65), calls = c(52.425, 47.45, 42.47, 
39.98, 37.49, 35.005, 32.52, 31.525, 30.535, 30.04, 29.54, 28.55, 
27.575, 26.575, 25.59, 25.095, 24.605, 23.625, 22.65, 21.68, 
20.715, 20.235, 19.755, 18.8, 17.85, 16.91, 15.975, 15.51, 15.05, 
14.12, 13.24, 12.34, 11.47, 11.045, 10.62, 9.795, 8.975, 8.185, 
7.4, 7.035, 6.65, 5.94, 5.235, 4.56, 3.915, 3.615, 3.31, 2.74, 
2.22, 1.74, 1.325, 1.145, 0.97, 0.67, 0.445, 0.285, 0.165, 0.125, 
0.1, 0.065, 0.035, 0.025, 0.015, 0.015, 0.015)), row.names = c(NA, 
65L), na.action = structure(66:91, .Names = c("66", "67", "68", 
"69", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", 
"80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "90", 
"91"), class = "omit"), class = "data.frame")

dens = extract.am.density(r = .016, te = 5/252, s0 = 321.75, market.calls = data$calls,
                          market.puts = data$puts, strikes = data$strike,
                          lambda = 1)

x = seq(from = 280, 350, by = 1)
y = dmln.am(x, u.1 = dens$u.1, 
            u.2 = dens$u.2, 
            u.3 = dens$u.3,
            sigma.1 = dens$sigma.1,
            sigma.2 = dens$sigma.2,
            sigma.3 =  dens$sigma.3,
            p.1 = dens$p.1, 
            p.2 = dens$p.2)

 plot(y ~ x, type = "l", col = "red")
```

Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.