Pitfield St Derivatives data archive

Methodology

Every metric published on this site traces to a formula on this page. Where a choice was made, a convention, a filter, an assumption about flow, it is named here rather than buried in code.

1. Forward and rate extraction

We do not plug in a Treasury yield and a dividend estimate. Both are backed out of the chain, per expiry, from put–call parity:

C(K)P(K)=erTFerTKC(K) - P(K) = e^{-rT}F - e^{-rT}K

This is linear in K with slope β = −e−rT and intercept α = e−rTF, so a single regression of the call-minus-put mid on strike gives both quantities:

r=ln(β)T,F=αβr = -\frac{\ln(-\beta)}{T}, \qquad F = -\frac{\alpha}{\beta}

The forward recovered this way already contains dividends and borrow cost, which is precisely why it beats assuming them. A hard-coded dividend yield is the usual reason a fitted surface comes out skewed.

We use strikes in roughly the 0.85–1.15 moneyness band, where both legs are liquid, and fit twice: once against a spot-referenced band to obtain a first forward, then again against a band referenced to that forward. The regression is recorded per expiry and the expiry is rejected below 0.99. A poor parity fit means bad quotes, not an exotic forward.

A precision note on the rate

The forward is recovered essentially exactly at every maturity. The rate is not. Because r = −ln(−β)/T, any slope error is amplified by 1/T: at one week that factor exceeds 50, so tick rounding alone moves the extracted rate by tens of basis points, while at one year the same rounding moves it by less than one. The forward is the number this step exists to produce and it is reliable throughout; the short-dated rate is a by-product and is published as such. Downstream, the rate enters only as a discount factor, where the sensitivity is second order.

2. Surface calibration

We work in total implied variance w = σ²T against log-moneyness k = ln(K/F), using Gatheral's raw SVI parameterisation:

w(k)=a+b[ρ(km)+(km)2+σ2]w(k) = a + b\left[\rho(k-m) + \sqrt{(k-m)^2 + \sigma^2}\right]

subject to

b0,ρ<1,σ>0,a+bσ1ρ20b \ge 0, \quad |\rho| < 1, \quad \sigma > 0, \quad a + b\sigma\sqrt{1-\rho^2} \ge 0

The final constraint is exactly the statement that total variance is non-negative everywhere. Setting w′(k) = 0 puts the minimum where the wing slopes b(ρ ± 1) balance:

km=ρσ1ρ2    wmin=a+bσ1ρ2k - m = -\frac{\rho\sigma}{\sqrt{1-\rho^2}} \;\Longrightarrow\; w_{\min} = a + b\sigma\sqrt{1-\rho^2}

Mid prices are inverted to implied volatilities with Black-76 on the extracted forward, by Brent search on a bracketed interval; a contract whose price falls outside the no-arbitrage bounds has no implied volatility and is dropped and counted rather than coerced to a number. Each expiry is then calibrated by constrained weighted least squares (SLSQP), seeded from the previous day's parameters, surfaces move slowly, and a warm start keeps the parameter time series stable instead of hopping between equivalent optima.

Residuals are weighted by vega, never equally. Equal weighting lets illiquid wings dominate a fit that matters most at the money, and the wing failure mode that actually occurs is bias rather than noise: wing markets are wide, and the mid of a wide market is systematically off.

3. Arbitrage conditions

Both conditions are checked on every surface, every day, and the results, including the failures, are published.

Butterfly (Durrleman)

g(k)=(1kw(k)2w(k)) ⁣2w(k)24(1w(k)+14)+w(k)2g(k) = \left(1 - \frac{k\,w'(k)}{2w(k)}\right)^{\!2} - \frac{w'(k)^2}{4}\left(\frac{1}{w(k)} + \frac14\right) + \frac{w''(k)}{2}

g(k) ≥ 0 everywhere is equivalent to the fitted smile implying a non-negative probability density. We evaluate it on a dense grid and publish min g(k) for every expiry, so a reader sees the margin rather than a boolean.

Calendar

w(k,T)T0for all k\frac{\partial w(k,T)}{\partial T} \ge 0 \quad \text{for all } k

Total variance must not decrease with maturity at fixed log-moneyness.

Where the conditions are evaluated

Both are checked only across the log-moneyness range where that expiry had quotable contracts, and the surface is published only over the same range. This does not hide violations. It is the difference between a violation and an artefact. A seven-day expiry has no quotes thirty percent out of the money, so its fitted value there is pure extrapolation, and comparing that extrapolation against a longer expiry that does have quotes reports a crossing between one real curve and one invented one. We claim arbitrage-freedom only where we publish a number, and the rendered surface carries a ragged edge for the same reason: that edge is the data support.

4. Greeks and units

Everything is priced on the extracted forward with Black-76, which removes the dividend problem entirely because dividends are already inside F.

d1=ln(F/K)+12σ2TσT,d2=d1σTd_1 = \frac{\ln(F/K) + \tfrac12\sigma^2T}{\sigma\sqrt{T}}, \qquad d_2 = d_1 - \sigma\sqrt{T} Δ=erTN(d1),Γ=erTφ(d1)FσT,V=erTFφ(d1)T\Delta = e^{-rT}N(d_1), \quad \Gamma = \frac{e^{-rT}\varphi(d_1)}{F\sigma\sqrt{T}}, \quad \mathcal{V} = e^{-rT}F\varphi(d_1)\sqrt{T} vanna=erTφ(d1)d2σ,volga=Vd1d2σ\text{vanna} = -\frac{e^{-rT}\varphi(d_1)d_2}{\sigma}, \qquad \text{volga} = \mathcal{V}\,\frac{d_1 d_2}{\sigma}

Vanna is ∂𝒱/∂F and volga is ∂𝒱/∂σ; neither is asserted. Differentiating vega with respect to the forward and using d₂ = d₁ − σ√T:

VF=erTTφ(d1)[1d1σT]=erTφ(d1)d2σ\frac{\partial \mathcal{V}}{\partial F} = e^{-rT}\sqrt{T}\,\varphi(d_1)\left[1 - \frac{d_1}{\sigma\sqrt{T}}\right] = -\frac{e^{-rT}\varphi(d_1)d_2}{\sigma}

Theta and charm are one-day finite differences with a bump of 1/365 years, documented here because the bump size is part of the number. Closed forms exist; a bump is easier to verify against a repriced option, and the test suite checks it against the analytic result.

Published units. Half of all greek disagreements are unit disagreements.
Vegaper volatility point, i.e. per 0.01 of σ
Theta, charmper calendar day
Delta, gamma, vanna, volgaper unit of forward, discounted to today

5. Derived metrics

Constant-maturity implied volatility

Interpolation is in total variance, then converted back:

w(T)=w(Ti)+TTiTi+1Ti[w(Ti+1)w(Ti)],σ=w(T)/Tw(T^\ast) = w(T_i) + \frac{T^\ast - T_i}{T_{i+1} - T_i}\left[w(T_{i+1}) - w(T_i)\right], \qquad \sigma^\ast = \sqrt{w(T^\ast)/T^\ast}

Total variance is the quantity that is additive in time. Interpolating volatility directly is wrong and produces a term structure that sags between listed expiries. That is a common tell. We do not extrapolate beyond the last listed expiry; a target outside the quoted range returns null.

Skew

The 25-delta risk reversal and butterfly are computed at the strikes where delta genuinely equals 25, solved on the fitted smile: the strike at a given delta depends on the volatility there, which depends on the strike, so it is a root-find rather than an ATM-volatility approximation. The at-the-money skew slope is taken analytically from the fit:

σkk=0=w(0)2Tσ(0)\frac{\partial \sigma}{\partial k}\bigg|_{k=0} = \frac{w'(0)}{2T\sigma(0)}

Variance risk premium

VRP(t)=IV30(t)RV30(tt+30)\mathrm{VRP}(t) = \mathrm{IV}_{30}(t) - \mathrm{RV}_{30}(t \to t+30)

Only computable thirty days after the fact. It is published lagged and labelled as such. A forward-looking VRP presented as though it were known is a lookahead bug wearing a metric's clothes.

6. Realized volatility

Five estimators at 5, 10, 21, 63 and 252 trading days, annualised on 252 days: close-to-close, Parkinson, Garman–Klass, Rogers–Satchell and Yang–Zhang.

σYZ2=σovernight2+kσoc2+(1k)σRS2,k=0.341.34+N+1N1\sigma^2_{YZ} = \sigma^2_{\text{overnight}} + k\,\sigma^2_{\text{oc}} + (1-k)\,\sigma^2_{RS}, \qquad k = \frac{0.34}{1.34 + \frac{N+1}{N-1}}

They are published side by side because they measure different things. Parkinson, Garman–Klass and Rogers–Satchell use only intraday prices and are structurally blind to the overnight gap, so on gappy data they sit below close-to-close; Yang–Zhang is the one that adds the gap back. Rogers–Satchell is additionally drift-independent, which the other two are not.

We also publish σP / σCC, the ratio of the range-based estimator to close-to-close. It reads as an intraday-range indicator and essentially nobody publishes it.

7. Chain aggregates

GEX(K)=Γ(K)OI(K)multiplierS20.01\mathrm{GEX}(K) = \Gamma(K)\cdot \mathrm{OI}(K)\cdot \text{multiplier}\cdot S^2 \cdot 0.01

Dollar gamma per 1% move in spot.

The sign convention is an assumption, not a fact

The common convention treats dealers as long gamma from calls and short from puts. That assumes customers buy puts and sell calls, a generalisation about flow, not something anyone can observe, since no dealer's book is public. It is implemented as a configuration flag, the chosen convention travels with the number in the output schema, and it is restated on every page that displays a gamma figure. Flagging this assumption is a stronger signal about the number than the number itself.

Open interest compounds the problem: it is previous-day settled, so today's reported figure reflects yesterday's positions. Every metric built on it is timestamped to the open interest's effective date, not to the snapshot date.

8. Filtering and exclusions

Before calibration a contract is dropped if it is:

Nothing is dropped silently. Counts are published per expiry and in aggregate on the quality page, because the share of a chain excluded from a fit is part of the result: a surface fitted to a third of a chain is a different object from one fitted to all of it.

9. Known limitations