← Dashboard

Methodology

GitHub

This document derives every formula computed in the dashboard. Written for someone who knows Black-Scholes and basic options microstructure but wants to verify the implementation matches their understanding. Honest about assumptions; explicit about limitations.

Data source: Derive (formerly Lyra), via the public market-data API at api.lyra.finance. Underlying: HYPE. The code retargets to any Derive underlying by changing one constant.

1. Black-Scholes greeks

Inputs: spot $S$, strike $K$, time-to-expiry $T$ (years), implied vol $\sigma$, risk-free rate $r$, dividend yield $q$. For HYPE we set $r = q = 0$; see §1.4 below.

$$d_1 = \frac{\ln(S/K) + (r - q + \sigma^2/2)\,T}{\sigma\sqrt{T}}, \qquad d_2 = d_1 - \sigma\sqrt{T}$$

1.1 Gamma

$$\Gamma = \frac{e^{-qT}\,\varphi(d_1)}{S\sigma\sqrt{T}}$$

where $\varphi$ is the standard normal pdf. With $q = 0$ this reduces to $\varphi(d_1) / (S\sigma\sqrt{T})$, which is what bsGamma() implements in js/black_scholes.js.

1.2 Delta (call / put)

$$\Delta_{\text{call}} = e^{-qT}\,N(d_1), \qquad \Delta_{\text{put}} = e^{-qT}\,(N(d_1) - 1)$$

We need $\Delta$ to find the $25\Delta$ put and call for risk-reversal / butterfly construction. Derive's /public/get_tickers does return pricer greeks per instrument, but we recompute locally from the mark IV: (a) the zero-gamma flip requires repricing $\Gamma$ at hypothetical spots, which the API can't give us, so for the at-spot snapshot to be consistent with the spot-shift curve both must come from the same engine; (b) it keeps the dashboard backend-free and robust to occasional null greeks in the wings. The API greeks are still decoded and kept for cross-checks.

Note: Derive returns IV as a decimal ($0.82 = 82\%$), unlike Deribit which returns a percentage. No rescale is applied.

1.3 Implementation note — N(x)

We use the Abramowitz-Stegun approximation 26.2.17 for $N(x)$ (max abs error $< 7.5 \times 10^{-8}$), which is sufficient for IV space. Verified in tests/test_black_scholes.html against published Hull and Python erf-based reference values.

1.4 Why $r = 0$ for HYPE

There is no canonical risk-free rate for crypto. Using a USD T-bill rate distorts forwards because the basis isn't financed at T-bill — it's financed at perpetual funding. Using a perp-funding-derived rate is unstable (negative on bear days, positive on bull days, mean-reverting on hours). Using $r = 0$ pushes the basis information into $F$ instead, which Derive hands us directly per option (see §2). This is cleaner and more defensible than picking an arbitrary rate.

2. Forward F per expiry

For each option expiry $t_i$ we need the forward $F_i$ for log-moneyness $k = \ln(K / F_i)$. Derive's pricer returns a per-option forward_price directly in get_tickers, so — unlike a Deribit build — there is no separate futures fetch. Within an expiry the forward is a function of expiry, not strike, so we take the median across that expiry's options to shrug off the occasional stale/zero outlier. forwardAt() interpolates linearly in time for any timestamp not directly present.

This is critical for the SVI fit: log-moneyness is $k = \ln(K / F_i)$, not $\ln(K / S)$. Using spot would bias $k$ by the basis, which drifts smoothly in time and would shift every smile horizontally without changing its shape — but term-structure comparisons across expiries would become noisy.

3. Dealer Gamma Exposure (GEX)

3.1 Per-option contribution

$$\text{GEX}_i = \Gamma_i \cdot \text{OI}_i \cdot \text{contractSize} \cdot S^2 \cdot 0.01 \cdot \epsilon_i$$

where $\epsilon_i = +1$ for calls and $\epsilon_i = -1$ for puts (SqueezeMetrics canonical assumption: dealers are net long calls, net short puts).

The factor $S^2 \cdot 0.01$ converts $\Gamma$ (dollar-gamma per share per dollar move) to the conventional GEX unit — dollar gamma per 1% spot move.

For Derive HYPE options, contractSize = 1 HYPE (1 contract = 1 unit underlying). OI is reported in contracts, so the product is in HYPE-denominated dollar exposure.

3.2 Aggregate by strike and zero-gamma flip

We sum $\text{GEX}_i$ across every live option at each strike, regardless of expiry, to get $\text{GEX}(K)$. The flip level is found by recomputing total GEX at hypothetical spot levels $S \in [0.80\,S_0, 1.20\,S_0]$ in 1% steps and locating the sign change (linearly interpolated). The flip is the spot at which dealers stop suppressing volatility (above flip → dealers long gamma → suppress; below → short gamma → amplify).

3.3 Dealer gamma regime

The sign of total GEX at spot gives the current regime, surfaced on the context strip:

The distance from spot to the zero-gamma flip (shown as a %) gauges how much room price has before the regime flips.

3.4 Honest limits

Citation: SqueezeMetrics, The Implied Order Book and Gamma Exposure, 2017.

4. Open Interest walls

Independently of gamma, we aggregate raw open interest by strike, split call vs put. Large call OI above spot tends to act as resistance / a dealer-supply zone; large put OI below spot tends to act as support. This complements GEX: GEX is the gamma-weighted hedging pressure, OI walls are the raw positioning that pressure acts on. Calls are drawn upward, puts downward, with spot and nearest-expiry max-pain annotated.

5. SVI implied vol surface

5.1 Raw parameterization (Gatheral 2004)

For a single expiry $T$, total variance $w(k) = \sigma^2_{\text{IV}}(k) \cdot T$ is fit as

$$w(k) = a + b\bigl(\rho\,(k - m) + \sqrt{(k - m)^2 + \sigma^2}\bigr)$$

with five parameters $\{a, b, \rho, m, \sigma\}$ per expiry. Convex in $k$ when $b \ge 0$, $|\rho| < 1$, $\sigma > 0$.

5.2 Fitting

For each expiry we minimize

$$L(\theta) = \sum_i \bigl(w_i^{\text{market}} - w(k_i;\theta)\bigr)^2 + \lambda \cdot P(\theta)$$

where the penalty $P(\theta)$ enforces:

ConstraintPenalty term
$b \ge 0$$\max(0, -b)^2$
$|\rho| < 1$$\max(0, |\rho| - 0.999)^2$
$\sigma > 0$$\max(0, 10^{-6} - \sigma)^2$
$a + b\sigma\sqrt{1-\rho^2} \ge 0$$\max(0, -(a + b\sigma\sqrt{1-\rho^2}))^2$

Optimizer: Nelder-Mead simplex, hand-implemented in js/svi.js. Initial simplex seeded from market-implied moments: $m_0 = \arg\min_k w_i$, $a_0 = \min_i w_i$, $b_0 = $ rough slope, $\rho_0 = -0.3$, $\sigma_0 = 0.1$. Expiries with fewer than 5 priced strikes are skipped.

To maximize smile coverage, the fit includes options with zero open interest as long as the pricer returns a valid IV — they add smile points without affecting OI-weighted measures (GEX, max pain), which ignore them.

5.3 Honest limits

Citation: Gatheral, J., A parsimonious arbitrage-free implied volatility parameterization, 2004.

6. ATM IV term structure

For each expiry $T_i$ with fitted SVI parameters $\theta_i$, ATM IV is

$$\sigma_{\text{ATM}}(T_i) = \sqrt{w(0; \theta_i) / T_i}$$

i.e. evaluate the fitted total-variance curve at $k = 0$. We do not linearly interpolate market IVs at $k = 0$ because the at-the-money mark is not always on a listed strike (forward sits between two strikes), and using the SVI fit gives a smooth, mathematically consistent curve.

Plotted vs days-to-expiry on a log-x axis.

7. 25Δ Risk-reversal and Butterfly

For each expiry:

  1. Compute $\Delta$ for every option using §1.2.
  2. Find the put with $\arg\min_i |\Delta_i^{\text{put}} + 0.25|$ → call its IV $\sigma_{25\text{p}}$.
  3. Find the call with $\arg\min_i |\Delta_i^{\text{call}} - 0.25|$ → call its IV $\sigma_{25\text{c}}$.
  4. Compute:
$$\text{RR}_{25} = \sigma_{25\text{c}} - \sigma_{25\text{p}}$$ $$\text{BF}_{25} = \frac{\sigma_{25\text{c}} + \sigma_{25\text{p}}}{2} - \sigma_{\text{ATM}}$$

Plot RR and BF as term structures across expiries.

Convention reminder: by industry convention, "25Δ put" refers to the put whose magnitude of $\Delta$ is 0.25 — i.e., $\Delta = -0.25$. We use the absolute value when matching. Skew rejects expiries where the best-match strike is more than 0.15 away from $\pm 0.25$ (sparse strike grid means no credible 25Δ point).

8. Max pain

For each expiry separately, candidate strikes $\{S^*\}$ are the listed strikes for that expiry. Total option-holder loss at expiry, were spot to land at $S^*$:

$$\text{pain}(S^*) = \sum_{\text{calls}} \text{OI}_c \cdot \max(0,\, S^* - K_c) + \sum_{\text{puts}} \text{OI}_p \cdot \max(0,\, K_p - S^*)$$

Max-pain strike is $\arg\min_{S^*} \text{pain}(S^*)$ — the strike at which option holders collectively lose the most (and writers, by symmetry, retain the most premium). The bar chart shows pain across all candidate strikes; the argmin is annotated.

The "magnetism" interpretation that spot drifts toward max-pain is folklore, not a derivation. The chart is informative because the shape of $\text{pain}(S^*)$ tells you where dealer / writer P&L is anchored, regardless of whether spot actually pins.

9. OI-weighted Put/Call ratio

Aggregate across all expiries:

$$\text{P/C} = \frac{\sum_{\text{puts}} \text{OI}_p}{\sum_{\text{calls}} \text{OI}_c}$$

Reported on the context strip. > 1 means more put than call OI (defensive / hedged positioning); < 1 the reverse.

10. Refresh and rate budget

The dashboard refreshes every 30 seconds. Per refresh:

Total: ≈11 HTTP requests per 30s ≈ 0.4 req/s, well within Derive's public-tier limits. The header surfaces the cumulative call counter so the operator (or reviewer) can verify the budget at a glance.

11. Citations