Data functions

The 34 functions that fetch market data into a formula: volatility, premium, VIX-style indexes, straddles, surface, distribution, greeks and FRED rates.

What the group is for

Data functions bring the site's market data into a formula in the Calculator or a Sheet. Each function fetches one data set for one symbol or one FRED series and returns a number or a Series. The other function groups then work on that value.

How every data function works

Latest value and history

Most data functions come in two forms with the same argument:

  • Plain form, such as iv30("SPY"): a number, the value on the latest trade date in the history.
  • .series form, such as iv30.series("SPY"): a Series of the whole daily history, oldest first. Each point is dated by its trade date; fred.series uses the observation date.

A point is a number on most dates. The first 19 points of vrpz.series and the first 20 points of volofvol.series are gaps, because the history is too short to compute them. The first point of ivpctile.series and hvpctile.series is 0.

iv30("SPY") => a number
iv30.series("SPY") => a Series of daily values

Five functions return a Series over something other than dates: fwd.curve, ivsurf.smile, ivsurf.term, dist.pdf and greek.strikes. Their x values are days to expiry, delta or strike, as each section below states. They describe the latest trade date only.

Arguments

  • Symbol: the first argument, a ticker in quotes, such as "SPY". There is no default symbol: iv30() returns E_ARITY. Case does not matter: iv30("spy") and iv30("SPY") fetch the same data.
  • Exact count: every argument is required. A call with too few or too many arguments returns E_ARITY.
  • Literal values only: each argument is text in quotes or a number, with an optional minus sign. A formula, a variable or a cell reference as an argument returns E_SLOT_ARGS. ivsurf("SPY", 15 * 2, -0.25) returns E_SLOT_ARGS; write ivsurf("SPY", 30, -0.25).
  • Nearest match: a tenor, delta, days to expiry or strike snaps to the nearest value in the data. Values between two grid points are never interpolated. A tenor snaps only within a limit, which each section below states.

Trade date and lag

Every value comes from the close of a finished session. The data updates once a day before the open, so the latest value is from the previous trading day's close. FRED series are dated by observation date, and FRED publishes a day late. The latest FRED date is usually one trading day older than the options data. The daily run and the lag rule describes the schedule.

Requests and the cache

The Calculator and the Sheet fetch data before they evaluate a formula:

  1. Calls that need the same data set share one request. iv30("SPY"), hv30("SPY") and vrp("SPY") make one request between them.
  2. Each request looks in the browser cache first. Only a miss goes to the network.
  3. Cached options data expires after 30 minutes and cached FRED data after 4 hours.
  4. When the site publishes new data, the browser clears the matching cache entries, and the next Calculator evaluation fetches again. A Sheet reloads at once every cell that uses the new data for that symbol.

A failed request does not stop the formula from compiling. The call returns E_NO_DATA when the formula is evaluated. In a Sheet, a failed request is tried again on a later evaluation.

Volatility levels

These functions return 30-day volatility and its rank in the symbol's own history.

Function Arguments Returns Units Measure
iv30, iv30.series symbol number, Series annualized decimal, 0.124 is 12.4% 30-day implied volatility
hv30, hv30.series symbol number, Series annualized decimal 30-day historical volatility
ivpctile, ivpctile.series symbol number, Series percentile, 0 to 100 IV percentile
hvpctile, hvpctile.series symbol number, Series percentile, 0 to 100 HV percentile
volofvol, volofvol.series symbol number, Series decimal, same units as iv30 Vol of vol

ivpctile(symbol): the percent of stored days with a strictly lower 30-day implied volatility, from 0 to 100.

iv30("QQQ") => a number
hv30("IWM") => a number
ivpctile("SPY") => a number
iv30("SPY") - hv30("SPY") => a number
volofvol.series("QQQ") => a Series of daily values

Volatility risk premium

Function Arguments Returns Units Measure
vrp, vrp.series symbol number, Series ratio, 0.05 is 5% Volatility risk premium
vrpz, vrpz.series symbol number, Series standard deviations Volatility risk premium

vrp(symbol): 30-day implied volatility divided by 30-day historical volatility, minus 1. A day with no historical volatility is left out of the history.

vrpz(symbol): the z-score of the latest premium against its trailing 20 trading days.

vrp("SPY") => a number
vrpz("QQQ") => a number
vrp.series("IWM") => a Series of daily values

Term structure and VIX

Function Arguments Returns Units Measure
vix30, vix30.series symbol number, Series percent, 15.4 is 15.4% 30-day VIX-style index
vix3m, vix3m.series symbol number, Series percent 3-month VIX-style index
fwd symbol, dte number dollars Forward price
fwd.curve symbol Series over days to expiry dollars Forward price

vix30 and vix3m are in percent, while iv30 is a decimal. Divide by 100 before you compare the two.

fwd(symbol, dte): the forward price for the listed expiry nearest dte days. A tie goes to the shorter expiry.

fwd.curve(symbol): forward prices as a Series. The x values are days to expiry, in ascending order.

vix30("SPY") => a number
vix30("SPY") - vix3m("SPY") => a number
vix30("SPY") / 100 - iv30("SPY") => a number
fwd("SPY", 30) => a number
fwd.curve("SPY") => a Series over days to expiry

Option prices

Function Arguments Returns Units Measure
straddle, straddle.series symbol number, Series fraction of the stock price, 0.028 is 2.8% Straddle price
strangle, strangle.series symbol number, Series fraction of the stock price Strangle price

straddle(symbol): the price of the at-the-money straddle near 30 days, as a fraction of the stock price.

strangle(symbol): the price of the 25 delta strangle on the same expiry, as a fraction of the stock price.

straddle("SPY") => a number
strangle("SPY") => a number
straddle("SPY") * fwd("SPY", 30) => a number
straddle.series("SPY") => a Series of daily values

Surface and distribution

Function Arguments Returns Units Measure
ivsurf symbol, tenor, delta number annualized decimal ATM implied volatility, 25 delta skew
ivsurf.smile symbol, tenor Series over delta annualized decimal ATM implied volatility
ivsurf.term symbol, delta Series over tenor in days annualized decimal ATM implied volatility
dist symbol, tenor, field number depends on the field Price percentiles, tail probability
dist.pdf symbol, tenor Series over strike probability per dollar Implied density

The vol surface

ivsurf(symbol, tenor, delta): implied volatility at the surface tenor nearest tenor days and the grid delta nearest delta.

  • Tenor: days. The surface grid is 7, 14, 30, 60, 90, 120, 180 and 365 days. The nearest grid tenor must lie within the larger of 5 days and one fifth of tenor, rounded down to whole days. A farther tenor returns E_NO_DATA.
  • Delta: signed. Positive is a call delta, negative a put delta. The grid runs from -0.5 to 0.5.
  • Ties: a value halfway between two grid points goes to the smaller one. A delta of 0 snaps to -0.05, the put side.

ivsurf.smile(symbol, tenor): the smile at one tenor, as a Series. The x values are the grid deltas, from -0.5 to 0.5. The tenor rule is the one ivsurf uses.

ivsurf.term(symbol, delta): the term structure at one delta, as a Series. The x values are the grid tenors in days.

ivsurf("SPY", 30, 0.5) => a number
ivsurf("SPY", 30, -0.25) - ivsurf("SPY", 30, 0.25) => a number
ivsurf.smile("SPY", 30) => a Series over delta
ivsurf.term("SPY", 0.5) => a Series over tenor

The distribution

dist(symbol, tenor, field): one summary number from the options-implied price distribution at expiry. The field is a name in quotes and is case sensitive:

  • Prices in dollars: "price_p10", "price_p25", "price_p50", "price_p75", "price_p90", "implied_mean", "implied_stdev", "forward_price", "spot".
  • Probabilities from 0 to 1: "tail_prob_down_10", "tail_prob_up_10", "crash_prob_20".
  • Percent from spot: "ci68_pct_low", "ci68_pct_high", "ci95_pct_low", "ci95_pct_high", "forward_premium_pct".
  • Shape, unitless: "implied_skewness", "implied_kurtosis", "tail_ratio".

A misspelled field, or a field whose value is text, returns E_NO_DATA.

dist.pdf(symbol, tenor): the implied probability density as a Series. The x values are strikes in dollars.

The site picks the listed expiry nearest tenor days. It accepts an expiry within the larger of 5 days and one fifth of tenor, rounded down to whole days. A tenor with no expiry that close returns E_NO_DATA.

dist("SPY", 30, "price_p50") => a number
dist("SPY", 30, "tail_prob_down_10") => a number
dist("SPY", 30, "price_p90") - dist("SPY", 30, "price_p10") => a number
dist.pdf("SPY", 30) => a Series over strike

Greeks

Function Arguments Returns Units Measure
greek symbol, greek, tenor, strike number greek per share times contracts Gamma, vanna, charm exposure
greek.strikes symbol, greek, tenor Series over strike greek per share times contracts Vanna exposure
greeksum symbol, tenor, field number depends on the field Peak exposure strike, open interest

greek(symbol, greek, tenor, strike): the exposure to one greek at the listed strike nearest strike, on the expiry nearest tenor days.

  • Greek: "gamma", "vanna" or "charm". Case does not matter.
  • Tenor: the expiry rule is the one dist uses.
  • Strike: dollars. A tie goes to the smaller strike.
  • Date: always the latest trade date.

greek.strikes(symbol, greek, tenor): the exposure at every listed strike, as a Series. The x values are strikes in dollars.

greeksum(symbol, tenor, field): one field from the greek summary, on the expiry nearest tenor days. The field is a name in quotes and is case sensitive, such as "net_gamma_exposure", "net_vanna_exposure", "peak_exposure_strike", "total_call_oi" or "total_put_oi". A tie between two expiries goes to the shorter one. The tenor rule is the one dist uses: an expiry farther than the larger of 5 days and one fifth of tenor returns E_NO_DATA.

greek("SPY", "vanna", 30, 765) => a number
greek.strikes("SPY", "vanna", 30) => a Series over strike
greeksum("SPY", 30, "net_gamma_exposure") => a number
greeksum("SPY", 30, "total_put_oi") / greeksum("SPY", 30, "total_call_oi") => a number

FRED rates

Function Arguments Returns Units Measure
fred name number as the series publishes it, percent for rates SOFR minus EFFR
fred.series name Series dated by observation date as the series publishes it SOFR minus EFFR

fred(name): the latest value of a FRED series or a spread the site computes, such as "SOFR" or "SOFR_minus_EFFR". Case does not matter. Values are not rescaled: 3.63 means 3.63%, and a spread of 0.02 means 0.02 percentage points.

fred.series(name): the daily history of the same series, oldest first.

fred("SOFR") => a number
fred("SOFR_minus_EFFR") => a number
fred.series("SOFR") => a Series of daily values
fred.series("SOFR_minus_EFFR") => a Series of daily values

Combine with other groups

A data function returns an ordinary number or Series, so every other group accepts it.

pctile(iv30.series("SPY"), 252) => a number
pctile(fred.series("SOFR_minus_EFFR"), 60) => a number

The function reference lists every signature.

Errors

Code Cause in a data function
E_NO_DATA The site has no data for the symbol, series, tenor or field, or the request failed.
E_SLOT_ARGS An argument is a formula, a variable or a cell reference instead of a literal value.
E_ARITY The call has too few or too many arguments.

Errors lists every code with its fix.