Complete Guide to Volatility Relative-Value Trading | FlashAlpha

Complete Guide to Volatility Relative-Value Trading

A complete guidebook for vol-arb desks: arbitrage-free SVI surfaces, variance vs volatility risk premium, skew and term structure, dispersion and implied correlation, var-swap replication, worked SPX examples, kinks and common mistakes, and every FlashAlpha endpoint you need.

T
Tomasz Dobrowolski Quant Engineer
Jun 7, 2026
40 min read
VolatilityTrading RelativeValue SVI VRP Dispersion TermStructure QuantFinance Options
VOL-ARB TOOLKIT
SPX surface, VRP, dispersion — live
SVI parameters, arbitrage detection, variance vs volatility risk premium, dispersion and spot-vol correlation for SPX and single names. Alpha plan.
Get Alpha Access →

What relative-value volatility trading is

A directional equity trader has a view on where the stock goes. A volatility relative-value trader has a view on how much it should cost to insure it, and on whether that cost is mis-priced relative to history, relative to a model, or relative to another asset. The underlying price is not the primary variable — implied volatility is.

Relative-value vol trading exploits dislocations in the implied volatility surface: one tenor trading too rich versus another (calendar trades), the put wing too expensive versus fair value (skew trades), index implied correlation diverging from single-name vols (dispersion), or the market as a whole pricing future variance above what realised variance will deliver (variance/volatility risk premium). The common thread is that every trade is structural and model-referenced, not a directional bet on the S&P 500 going up or down.

This matters because the risk profile is fundamentally different. A well-constructed vol-arb trade is delta-hedged and, when also vega-hedged across legs, is primarily exposed to the shape of the surface rather than its level. That shape-exposure — the relative cheapness or richness of one part of the surface versus another — is more persistent and mean-reverting than the level of implied vol itself. That is the edge.

The toolkit

SVI surfaces and arbitrage-free constraints

The Stochastic Volatility Inspired (SVI) parameterisation, due to Gatheral (2004), maps log-moneyness k to total implied variance w for a single expiry slice:

SVI Total Variance (raw parameterisation) $$w(k) = a + b\!\left[\rho(k - m) + \sqrt{(k-m)^2 + \sigma^2}\right]$$

where k = ln(K/F) is log-moneyness relative to the forward F, and the five parameters carry clear economic content:

  • a — overall level of variance (vertical shift)
  • b — angle of the smile wings (controls vol-of-vol)
  • ρ — put/call asymmetry (ρ < 0 in equity markets due to the leverage effect)
  • m — moneyness at which the smile is most symmetric
  • σ — curvature of the ATM region

Five parameters are sufficient to describe a liquid equity smile. The real difficulty is not the fitting — it is ensuring the fitted surface is arbitrage-free. Two static arbitrage conditions must hold:

  • No butterfly arbitrage — the risk-neutral density must be non-negative at every strike: ∂²C/∂K² ≥ 0, which translates to ∂²w/∂k² ≥ 0 after the Dupire change of variable.
  • No calendar arbitrage — total variance must be non-decreasing across expiries at every moneyness: w(k, T&sub2;) ≥ w(k, T&sub1;) for all k whenever T&sub2; > T&sub1;.

If either condition fails, you have a surface that implies free money — and if you price trades off it, your prices are wrong in an unbounded way. This is why arbitrage detection is the first deliverable to check, not an afterthought.

Variance swap replication and the var-swap strike

A variance swap pays the difference between realised variance and a fixed strike K⊂var agreed at inception. The fair variance swap strike is the replication-theoretic value:

Var-Swap Strike via Log-Strip Replication (Demeterfi et al. 1999) $$K_{\text{var}} = \frac{2}{T}\left[\int_0^F \frac{P(K)}{K^2}\,dK + \int_F^\infty \frac{C(K)}{K^2}\,dK\right]$$

Because the integrand spans all strikes, you need a complete smile — which is exactly what the SVI fit provides. The numerical integral over the SVI smile gives you a clean, arb-consistent fair value for realised variance that goes beyond ATM implied vol. The convexity adjustment (fair vol minus ATM IV) measures how much the wings contribute; when the put wing is rich, the fair var-swap vol sits above ATM IV, and selling vol via variance swaps captures that richness.

Variance risk premium versus volatility risk premium

This is one of the most conflated concepts in practice. The variance risk premium (VaRP) is the expected profit from selling a variance swap and delta-hedging: it operates on squared vol. The volatility risk premium (VolRP) is the P&L from selling a vega-neutral straddle and continuously delta-hedging: it operates on vol itself.

Variance vs Volatility Risk Premium $$\text{VaRP} = K_{\text{var}} - \mathbb{E}[\sigma_R^2]\qquad\text{VolRP} = \sigma_{IV,\text{ATM}} - \mathbb{E}[\sigma_R]$$

These diverge because of the nonlinear relationship between variance and vol. In the tails, variance grows quadratically while vol grows linearly, so fat-tail regimes inflate VaRP far more than VolRP. A strategy that looks like it is selling VaRP may actually be mostly selling VolRP with a highly convex residual tail exposure — and vice versa. Knowing which you are trading, and sizing accordingly, is critical.

Skew and term structure

The implied volatility surface has two primary shape dimensions beyond the ATM level:

  • Skew — the slope of implied vol across strikes at a fixed expiry. In equity markets the put wing is systematically richer than the call wing (negative ρ in SVI terms). Skew trades exploit relative richness between put and call wings or between the skew of one name and another.
  • Term structure — the slope of ATM implied vol across expiries. Contango (front < back) is the normal regime; backwardation (front > back) occurs around events (earnings, FOMC, CPI) that concentrate near-term uncertainty. Calendar trades buy cheap tenors and sell rich ones.

Spot-vol correlation is a further shape measure: when spot falls, vol typically rises (negative spot-vol correlation in equity markets). A surface with a very steep downside skew reflects a high-magnitude negative spot-vol correlation priced into the smile. Monitoring spot-vol correlation over time reveals whether today's skew is normal or dislocated.

Dispersion and implied correlation

Implied correlation is extracted by comparing index implied vol to single-name implied vols:

Implied Correlation (simplified two-asset form) $$\rho_{\text{implied}} = \frac{\sigma_{\text{index}}^2 - \sum_i w_i^2 \sigma_i^2}{2\sum_{i < j} w_i w_j \sigma_i \sigma_j}$$

where w⊂i are index weights and σ⊂i are single-name ATM IVs. Implied correlation is typically higher than realised correlation because the index put skew is structurally bid — investors pay up to hedge the index as a unit rather than buying individual-name puts. A dispersion trade sells index vol and buys single-name vols (or vice versa), monetising that spread. When implied correlation exceeds realised correlation, the index is rich relative to constituents: sell the index, buy the names.

Reading the data

SVI parameters: what the numbers tell you

When you pull /v1/adv_volatility/SPX, the SVI parameters per expiry slice are the first thing to read systematically:

import requests

resp = requests.get(
    "https://lab.flashalpha.com/v1/adv_volatility/SPX",
    headers={"X-Api-Key": "YOUR_API_KEY"}
)
d = resp.json()

for s in d["svi_parameters"]:
    print(
        f"{s['expiry']} ({s['days_to_expiry']}d): "
        f"a={s['a']:.5f}  b={s['b']:.5f}  "
        f"rho={s['rho']:.4f}  m={s['m']:.4f}  sigma={s['sigma']:.4f}  "
        f"ATM IV={s['atm_iv']:.2f}%  "
        f"arb_free={s.get('arb_free', True)}"
    )

Interpretation per parameter:

  • rho more negative than −0.7: extremely steep put skew. This often indicates event risk or a structural demand for downside protection. Check whether this is a single-name earnings effect or a broad index regime.
  • b elevated (above 0.15): wide wings. The market is pricing large moves at both extremes. High b combined with a normal rho means symmetric wing richness — which is unusual and may indicate a vol-of-vol dislocation.
  • sigma very small (near zero): the smile is nearly V-shaped with minimal ATM curvature. This is a numerically fragile regime — the surface is harder to interpolate robustly and arb violations are more likely.
  • Cross-slice rho term structure flattening: near-term slices are typically steeper (more negative rho) than long-dated ones due to term-structure mean reversion. If the long-dated rho suddenly steepens to match the near-term slice, the long end is pricing a structural change — or someone is buying long-dated puts.

Arbitrage flags: non-negotiable checks

flags = d.get("arbitrage_flags", [])
if flags:
    for f in flags:
        print(f"[{f['type'].upper()}] {f['expiry']} moneyness={f.get('moneyness','n/a')}: {f['description']}")
else:
    print("Surface is arbitrage-free")

A butterfly violation at a specific moneyness means the risk-neutral density goes negative there — any option price that references that region of the surface is theoretically undefined. A calendar violation between two expiries means a calendar spread at that moneyness is a free lunch: any calendar trade that straddles those expiries is exposing you to mispriced edge. Do not trade off a surface with active flags.

Reading the variance surface and var-swap strikes

# Var-swap fair values per expiry
# K_var is the fair variance strike (units: variance = vol²).
# fair_vol = sqrt(K_var) converts back to vol units for comparison with ATM IV.
for vs in d["variance_swap_fair_values"]:
    K_var    = vs["K_var"]                      # fair variance strike (annualised, e.g. 0.0324 = 18%² )
    fair_vol = vs["fair_vol"]                    # sqrt(K_var), vol units
    convexity = fair_vol - vs["atm_iv"]
    print(
        f"{vs['expiry']}: K_var={K_var:.6f}  "
        f"fair_vol=sqrt(K_var)={fair_vol:.2f}%  "
        f"ATM={vs['atm_iv']:.2f}%  "
        f"convexity_adj={convexity:+.2f}pp"
    )
# Note: the drift-correction terms in the Demeterfi replication formula vanish
# only when F = S₀·e^{rT} (cost-of-carry forward).  This holds for SPX (no
# dividends in the index itself) but introduces a small bias for dividend-paying
# single names where the true forward departs from the risk-free-rate forward.

The convexity adjustment is a direct measure of how much the wings cost relative to ATM. A convexity adjustment above +1.5pp (for SPX) is historically elevated, indicating the market is paying a premium for tail coverage beyond what ATM vol implies. Track this time series and you have a clean signal for when variance swaps are cheap or rich relative to straddles.

Reading dispersion and spot-vol correlation

# /v1/dispersion accepts query params: index, symbols, weights, horizon_days
# Adjust the symbols/weights list to your actual basket
disp = requests.get(
    "https://lab.flashalpha.com/v1/dispersion",
    params={
        "index": "SPX",
        "symbols": "AAPL,MSFT,NVDA,AMZN,GOOGL",
        "weights": "0.07,0.07,0.06,0.05,0.05",
        "horizon_days": 20,
    },
    headers={"X-Api-Key": "YOUR_API_KEY"}
).json()

print(f"SPX implied vol (index): {disp['implied_vol_index']*100:.2f}%")
print(f"Weighted basket IV:       {disp['implied_vol_basket']*100:.2f}%")
print(f"Implied correlation:      {disp['implied_correlation']:.4f}")
print(f"Realised correlation:     {disp['realized_correlation']:.4f}")
print(f"Corr premium:             {disp['correlation_premium']:+.4f}")

svc = requests.get(
    "https://lab.flashalpha.com/v1/volatility/spot-vol-correlation/SPX",
    headers={"X-Api-Key": "YOUR_API_KEY"}
).json()
print(f"Spot-vol correlation (20d): {svc['spot_vol_correlation_20d']:.4f}")
print(f"Spot-vol correlation (60d): {svc['spot_vol_correlation_60d']:.4f}")

The trades

Calendar / term-structure trades

A calendar spread buys total variance at one expiry and sells it at another. The carry is the theta differential; the P&L driver is whether the term structure steepness reverts toward its historical norm.

The standard setup: compute the ATM IV ratio between the front expiry and the back expiry via /v1/volatility/skew-term. If the ratio is in the top decile of its historical distribution, the front is rich relative to the back — sell front variance, buy back variance. Size the position to vega-neutrality across the two legs (not notional-neutrality, which ignores the different vega per expiry).

ts = requests.get(
    "https://lab.flashalpha.com/v1/volatility/skew-term/SPX",
    headers={"X-Api-Key": "YOUR_API_KEY"}
).json()

# Term structure slope: front ATM vs back ATM
front = ts["term_structure"][0]
back  = ts["term_structure"][-1]

ts_ratio = front["atm_iv"] / back["atm_iv"]
print(f"Front ATM ({front['expiry']}): {front['atm_iv']:.2f}%")
print(f"Back  ATM ({back['expiry']}):  {back['atm_iv']:.2f}%")
print(f"Front/back ratio: {ts_ratio:.4f}")
print(f"Regime: {ts['term_structure_regime']}")  # contango / flat / backwardation

Event distortions. The front expiry ratio inflates mechanically before FOMC, CPI, and earnings because the near-term expiry prices the event premium. A front/back ratio in the top decile during a FOMC week is not a calendar trade opportunity; it is the options market correctly pricing the event. The term-structure endpoint includes event flags — check them before putting on a calendar against elevated front-month vol.

Skew / risk-reversal trades

A risk reversal sells an OTM put and buys an OTM call (or vice versa) at the same delta, delta-hedged. It is a pure bet on the skew level relative to what it should be.

The signal: read the 25-delta risk reversal from /v1/volatility/skew-term. Compare it to its historical distribution. A 25-delta RR in the bottom decile (puts very cheap relative to calls, which is rare in equities) is a long skew opportunity. A top-decile RR (puts extremely rich) is a short skew opportunity — but the timing matters enormously because equity skew is structurally bid and can stay rich for months.

25-Delta Risk Reversal $$RR_{25} = \sigma_{IV}(\Delta_{put}=-0.25) - \sigma_{IV}(\Delta_{call}=+0.25)$$

Dispersion: index versus single-name vol

The canonical dispersion trade sells index variance and buys single-name variance in proportion to index weights. The P&L equals the realised correlation premium:

Dispersion P&L (off-diagonal cross-term form) $$\text{P\&L} \approx (\rho_{\text{realised}} - \rho_{\text{implied}}) \cdot \sum_{i < j} w_i w_j \sigma_i \sigma_j \;\times\; N$$

where N is the notional. The P&L is driven by the off-diagonal cross-terms: each pair of constituents (i, j) contributes wi wj σi σj weighted by the correlation gap. The diagonal idiosyncratic terms wi2 σi2 are common to both index and constituent legs and cancel out in a properly-weighted dispersion book; the net exposure is purely the off-diagonal covariance. When implied correlation exceeds realised, selling the index and buying the names earns positive carry. The dispersion endpoint gives you the live implied correlation and the realised correlation benchmark in one call.

Regime risk. The hardest part of dispersion is that correlation is regime-switching. In a broad risk-off event (2020 March, 2022 rate shock), realised correlation spikes to 0.9+ and the dispersion trade loses catastrophically because single-name vol cannot offset the index vol move. Sizing dispersion trades requires explicit correlation-scenario stress testing, not just historical mean-reversion assumptions.

Variance vs vol RP trades

Once you have VaRP and VolRP separately from /v1/vrp/{ticker}, you can trade the spread between them as a proxy for the wings. When the convexity adjustment (fair var-swap vol minus ATM IV) widens, the wings are expensive relative to ATM. A ratio spread that is long ATM and short the wings monetises this richness. When the convexity adjustment compresses, the wings are cheap: butterfly buyers and long vega-of-vol positions benefit.

vrp = requests.get(
    "https://lab.flashalpha.com/v1/vrp/SPX",
    headers={"X-Api-Key": "YOUR_API_KEY"}
).json()

print(f"VRP (variance basis):   {vrp['variance_risk_premium']:.2f}pp")
print(f"VolRP (vol basis):      {vrp['volatility_risk_premium']:.2f}pp")
print(f"VRP z-score:            {vrp['vrp_zscore']:.2f}")
print(f"VolRP z-score:          {vrp['volrp_zscore']:.2f}")
# When VRP z >> VolRP z: wings are rich, convexity is elevated
# When VolRP z >> VRP z: wings are cheap, ATM richness dominates
ALPHA PLAN
Run these trades with live data
SVI surfaces, var-swap strikes, VRP decomposition, dispersion, and term structure — all in structured JSON. One endpoint per strategy, no surface-building required.
Get Alpha Access →

Surface-anomaly rich/cheap wings

A more granular approach pulls the full variance surface grid from /v1/surface/svi/{ticker} and compares today's surface to its historical mean at each moneyness bucket. Strikes where today's total variance is two standard deviations above the rolling mean are rich; those two deviations below are cheap. These are the strikes to sell into (wing overwriters, ratio spreads) and buy from (butterflies, long wings) respectively.

import numpy as np

surf = requests.get(
    "https://lab.flashalpha.com/v1/surface/svi/SPX",
    headers={"X-Api-Key": "YOUR_API_KEY"}
).json()

# Compare today's IV at each moneyness to its 30-day mean
for bucket in surf["moneyness_buckets"]:
    k = bucket["log_moneyness"]
    iv_today = bucket["implied_vol"]
    iv_mean  = bucket["iv_mean_30d"]
    iv_std   = bucket["iv_std_30d"]
    z = (iv_today - iv_mean) / iv_std if iv_std > 0 else 0.0
    if abs(z) > 2.0:
        side = "RICH" if z > 0 else "CHEAP"
        print(f"k={k:+.3f}  IV={iv_today:.2f}%  mean={iv_mean:.2f}%  z={z:+.2f}  [{side}]")

Risk and sizing

Vega and gamma neutrality

Every vol-RV trade should be vega-hedged at the trade level — the book earns from surface-shape dislocations, not from the level of vol going up or down. The net vega of the book (across all legs) should be close to zero, rebalanced at least daily. Gamma neutrality is harder to achieve simultaneously: in a calendar spread, the short front-expiry leg has far higher gamma than the long back-expiry leg, so you will carry net gamma. Know your signed gamma before adding position size.

For a multi-name dispersion book, report risk in vega-weighted terms per name, not notional. A single-name position of 10,000 vega in NVDA carries far more vol-of-vol risk than 10,000 vega in MSFT, because NVDA's vol itself is more volatile. Normalise by vol-of-vol (which you can proxy via b from the SVI fit) when aggregating book risk.

Correlation risk

The residual risk in a delta- and vega-neutral vol book is correlation risk — between asset vols in a dispersion book, and between strike-level vols in a surface-shape trade. Both are fat-tailed and regime-switching. Size as a fraction of your total risk budget with correlation scenarios in mind: assume realised correlation can spike by 0.3-0.5 above its long-run mean during a single macro shock, and check that the resulting P&L is within your drawdown limit before going on.

The kinks and common mistakes

1. Trading off a non-arbitrage-free surface

This is the most important operational kink. A surface that fails the butterfly check implies a negative probability density at some strikes — which means any derivative price referenced to that region is undefined. The symptom is often subtle: a calendar spread that looks like it should pay positive carry instead bleeds theta because the fitted surface is locally inconsistent. Before placing any vol-RV trade, check arb_free per expiry slice in the API response. If any slice shows a violation, the trade that straddles that expiry is invalid. Wait for the surface to be clean, or restrict the trade to slices that are confirmed arbitrage-free.

2. Conflating variance risk premium with volatility risk premium

VaRP and VolRP are different quantities even when they rhyme. A high VolRP z-score tells you ATM straddles are overpriced relative to realised vol. A high VaRP z-score tells you the wings are also overpriced — the market is paying an additional premium for fat tails beyond what the ATM level implies. Selling a straddle when VaRP is rich but VolRP is not elevated earns no premium; the wing richness is in the variance-swap convexity adjustment, not in the straddle. The correct trade when VaRP is rich but VolRP is flat is an ATM long with short wings (a ratio spread), not an outright straddle sale.

3. Liquidity filtering of SVI fits

SVI fits are only as good as the input data. If you include stale, zero-OI, or wide-market strikes in the fit, the optimizer will anchor on those points and produce a distorted surface. The FlashAlpha pipeline filters aggressively — requiring minimum OI thresholds, bid-ask spread filters, and ATM-biased weighting — but if you are rebuilding fits internally, failing to apply equivalent filters produces a surface where the far OTM wings are largely noise. The practical consequence: rich/cheap signals in the far wings are often artefacts of liquidity filtering gaps, not real dislocations. Cross-check wing signals against raw chain liquidity before trading them.

4. Dispersion correlation regime shifts

The standard dispersion trade argument — implied correlation exceeds realised, so sell the index and buy the names — is structurally valid in a low-correlation regime. But correlation is not stationary. During a macro sell-off, realised correlation jumps toward 1.0 and stays there for weeks; the dispersion trade loses on both legs simultaneously (index vol explodes, single-name vol explodes proportionally). The historical correlation premium that justified the trade disappears precisely when you need it most. Dispersion books require hard stop-losses on realised correlation and active monitoring of the correlation premium (implied minus realised) in real time.

5. Term-structure event distortions

A calendar spread that looks rich based on the ATM ratio alone may be fully justified once you account for an event in the front expiry. If an FOMC meeting, CPI print, or large-cap earnings date falls inside the front expiry window but not the back expiry window, the front ATM IV is mechanically higher — it is pricing the event. Selling front variance against the back is not a vol-RV trade in this case; it is a short event-vol bet. Always check the term-structure endpoint's event flags before interpreting front-month richness as a calendar opportunity.

6. Realised vol estimator choice

The VRP calculation depends on the realised volatility estimator. FlashAlpha's /v1/volatility/{ticker} endpoint reports close-to-close realised vol (log returns, sample standard deviation, annualised by √252) across 5/10/20/30/60-day windows. The VRP endpoints use the same close-to-close series. Close-to-close is the standard estimator but is biased by overnight gaps and has higher estimation variance for short windows; range-based estimators such as Yang-Zhang (which combines overnight, open-to-close, and intraday range) cut that variance. If you compute your own Yang-Zhang RV from OHLC bars, expect it to differ from the API's close-to-close figure by roughly 0.5-2pp, which can shift the magnitude and even the sign of the z-score in moderate-richness regimes. See the full comparison in Yang-Zhang vs close-to-close realised volatility.

Worked examples

SPX surface snapshot — worked numbers

The table below is a representative SPX surface read (illustrative figures, not live quotes). It shows the three metrics that drive every strategy in this guide before any code is run:

Metric Front (21d) Back (49d) Interpretation
ATM IV 17.4% 15.8% Front/back ratio = 1.10 — mild backwardation; front modestly rich
25Δ Risk Reversal (RR25) −4.2pp −3.1pp Front put wing steeper than back; within normal range (top-60th pctile historically)
Var-swap strike Kvar (fair vol) 19.1% 17.2% Convexity adj = +1.7pp and +1.4pp above ATM; wings are elevated vs straddle
Butterfly spread (25Δ) 1.8pp 1.5pp Wing curvature above ATM; consistent with elevated convexity adjustment
Arb flags None None Surface is trade-ready on both slices

Read: the front convexity adjustment of +1.7pp is elevated versus the historical mean (~1.0pp for SPX), so variance swaps are expensive relative to straddles — a ratio spread (long ATM, short wings) or an outright var-swap sell is more attractive than a simple straddle sale. The skew signal is neutral (60th percentile), so no standalone RR trade is justified here.

Example 1: Reading the SPX surface for a skew trade

The following pattern produces a high-conviction put-wing rich signal. Pull the current advanced vol for SPX and look for two concurrent conditions: the 25Δ risk reversal is in the top decile of its 90-day distribution, and the near-term butterfly arb flag is clean (no butterfly violations).

import requests, numpy as np, pandas as pd
from datetime import date

LAB  = "https://lab.flashalpha.com"
HIST = "https://historical.flashalpha.com"   # point-in-time replay, ?at=
H = {"X-Api-Key": "YOUR_API_KEY"}

# Today's 25-delta risk reversal (skew_25d) for the front expiry
vol = requests.get(f"{LAB}/v1/volatility/SPX", headers=H).json()
rr_today = vol["skew_profiles"][0]["skew_25d"]

# 90-day history: pull skew_25d at each past session from the historical host
rr_hist = []
for d in pd.bdate_range(end=date.today(), periods=90):
    snap = requests.get(f"{HIST}/v1/volatility/SPX",
                        headers=H, params={"at": d.strftime("%Y-%m-%d")}).json()
    sp = snap.get("skew_profiles")
    if sp:
        rr_hist.append(sp[0]["skew_25d"])

rr_pctile = np.mean(np.array(rr_hist) <= rr_today) * 100

# Confirm an arbitrage-free surface (no butterfly violations) before trading it
adv = requests.get(f"{LAB}/v1/adv_volatility/SPX", headers=H).json()

# Arb check on front slice
front_arb_free = adv["svi_parameters"][0].get("arb_free", True)

print(f"25d RR today: {rr_today:.2f}pp  (percentile: {rr_pctile:.0f}th)")
print(f"Front slice arb-free: {front_arb_free}")

if rr_pctile > 85 and front_arb_free:
    print("PUT WING RICH: candidate for short skew / short RR trade")
    print("  Structure: sell 25d put, buy 25d call, delta-hedge")
    print("  Size: vega-neutral via front-expiry vega per delta")
elif rr_pctile < 15 and front_arb_free:
    print("PUT WING CHEAP: candidate for long skew / long RR trade")
    print("  Structure: buy 25d put, sell 25d call, delta-hedge")
else:
    print(f"No skew signal: RR at {rr_pctile:.0f}th percentile")

Example 2: A dispersion read on SPX versus constituents

This example reads the current dispersion spread, computes the implied correlation premium, and thresholds it against a historical range to determine whether a dispersion trade is justified.

# Snapshot: today's implied vs realised correlation
BASKET_PARAMS = {
    "index": "SPX",
    "symbols": "AAPL,MSFT,NVDA,AMZN,GOOGL",
    "weights": "0.07,0.07,0.06,0.05,0.05",
    "horizon_days": 20,
}

disp = requests.get(
    "https://lab.flashalpha.com/v1/dispersion",
    params=BASKET_PARAMS,
    headers={"X-Api-Key": "YOUR_API_KEY"}
).json()

ic_today = disp["implied_correlation"]
rc_today = disp["realized_correlation"]
corr_premium = disp["correlation_premium"]  # implied - realized

# To build a historical distribution, call /v1/dispersion repeatedly for prior
# dates (point-in-time) or use your own log.  The endpoint is stateless and
# does not ship a built-in history route.
print(f"Implied correlation:   {ic_today:.4f}")
print(f"Realised correlation:  {rc_today:.4f}")
print(f"Correlation premium:   {corr_premium:+.4f}")
print(f"Index IV:              {disp['implied_vol_index']*100:.2f}%")
print(f"Basket weighted IV:    {disp['implied_vol_basket']*100:.2f}%")

# Signal logic based on premium vs your own historical baseline
PREM_RICH_THRESHOLD  = 0.05   # calibrate to your history
PREM_CHEAP_THRESHOLD = -0.02

if corr_premium > PREM_RICH_THRESHOLD:
    print("\nDISPERSION LONG: implied correlation rich vs realised")
    print("  Trade: sell SPX variance, buy constituent variances (vega-weighted)")
    print("  Risk: correlation regime shift — size conservatively, hard corr stop")
elif corr_premium < PREM_CHEAP_THRESHOLD:
    print("\nDISPERSION SHORT: implied correlation cheap vs realised")
    print("  Trade: buy SPX variance, sell constituent variances (vega-weighted)")
else:
    print(f"\nNo dispersion signal: correlation premium {corr_premium:+.4f}")

Tooling: FlashAlpha endpoints for vol-arb

Every workflow described above maps to a specific endpoint. The complete set for a vol-RV desk:

EndpointWhat it deliversTier
/v1/adv_volatility/{t}SVI parameters per expiry, variance surface grid, arb flags, var-swap fair values, greeks surfacesAlpha
/v1/surface/{t}Full IV surface grid (historical replay available)Alpha
/v1/surface/svi/{t}Per-moneyness-bucket IV with rolling mean and z-score (rich/cheap wings)Alpha
/v1/vrp/{t}Variance RP, volatility RP, z-scores, directional decompositionAlpha
/v1/dispersion?index={t}&symbols=...&weights=...Implied correlation, realised correlation, correlation premium, per-constituent vol contributionsAlpha
/v1/volatility/skew-term/{t}Per-expiry ATM IV, 25Δ RR, butterfly spread, term structure regime, event flagsGrowth
/v1/volatility/spot-vol-correlation/{t}30-day, 90-day, 6-month spot-vol correlationGrowth
/v1/volatility/{t}ATM IV, close-to-close realised vol (rv_5d..rv_60d), IV-RV spreads, skew profiles, term structureGrowth
/v1/surface/{t}?at= (historical host)Point-in-time IV surface replay for backtestingAlpha

MCP connector for Claude integrations

If you are running a Claude-based research or signal-generation agent, the vol-arb MCP connector is available at:

https://lab.flashalpha.com/mcp-oauth/volarb

This OAuth-authenticated MCP endpoint exposes the full advanced volatility, VRP, surface, dispersion, and term-structure tools as Claude-callable functions, letting you run natural-language vol-arb analysis sessions against live market data. See the MCP setup guide for authentication and tool registration details.

α Quick integration check

Pull the SPX advanced vol endpoint, check the arb flags, read the var-swap fair values, and compare them to your own surface. If the fits are comparable to your in-house calibration and the arb flags are at least as strict, the maintenance argument is settled.

Try in Playground →

FAQ

How do I know if a calendar spread is a genuine term-structure trade or just an event bet?

Check the event_flags field in the skew-term response for both expiry legs. If the front expiry carries an FOMC, CPI, or earnings event flag and the back does not, the front ATM premium reflects event pricing rather than structural term-structure richness. A genuine calendar trade requires clean event flags on the front expiry — or explicit sizing of the event component as a separate risk.

Can I backtest dispersion signals historically?

For the surface: the historical host's /v1/surface/{ticker}?at= replays the surface shape at any past timestamp, so you reconstruct history by iterating dates yourself. For dispersion, call /v1/dispersion with your basket parameters for each date you want. Both require the Alpha plan.

Why does the var-swap strike often exceed ATM IV?

The var-swap strike is the fair value of realised variance, computed by integrating across all strikes (not just ATM). In equity markets the put wing is systematically bid, adding a convexity adjustment above ATM IV. This adjustment is the market's price for fat-tail risk — it is normally positive and ranges from ~0.3pp to ~2pp for SPX depending on the skew regime.

What is the difference between implied correlation and realised correlation for dispersion sizing?

Implied correlation is derived from today's option prices — it is forward-looking. Realised correlation is computed from historical price returns — it is backward-looking. The dispersion trade earns the spread between the two, but realised correlation is estimated with noise. The 30-day estimate has high variance; using 60-day or 90-day realised correlation gives a more stable signal but lags regime changes. The dispersion endpoint returns all three lookbacks; using a blend of 30-day and 90-day estimates reduces noise without too much lag.

Which realised vol estimator should I use for VRP calculations?

FlashAlpha's /v1/volatility and VRP endpoints use close-to-close realised vol (log returns, sample standard deviation, annualised by √252) — that is the series behind every VRP signal. Yang-Zhang is a lower-variance alternative (roughly 1.3–1.5× lower estimation variance than close-to-close for a 30-day window) that you can compute yourself from OHLC bars. The practical difference can be material: in moderate-richness regimes (VRP of 1–2pp), the estimator choice can shift the z-score by half a standard deviation, so don't mix estimators within a single comparison. Full comparison: Yang-Zhang vs close-to-close realised volatility.

Do I need the Alpha plan for all of this?

The SVI surface, advanced vol endpoint, variance surfaces, arb detection, VRP, and dispersion are Alpha-only. The skew/term-structure endpoint, spot-vol correlation, and basic IV data are available on the Growth plan. The historical surface and historical dispersion are Alpha. For a vol-arb desk the Alpha plan is the correct tier; the Growth plan covers the directional vol-informing signals but not the full quantitative surface toolkit.

Related reading

Live Market Pulse

Get tick-by-tick visibility into market shifts with full-chain analytics streaming in real time.

Intelligent Screening

Screen millions of option pairs per second using your custom EV rules, filters, and setups.

Execution-Ready

Instantly send structured orders to Interactive Brokers right from your scan results.

Join the Community

Discord

Engage in real time conversations with us!

Twitter / X

Follow us for real-time updates and insights!

GitHub

Explore our open-source SDK, examples, and analytics resources!