Build a Vol Surface Visualizer with an API: SVI Implied Volatility Surface for Developers | FlashAlpha

Build a Vol Surface Visualizer with an API: SVI Implied Volatility Surface for Developers

How to build an implied volatility surface visualizer using the FlashAlpha API. Get pre-fitted SVI parameters, total variance surface grids, arbitrage detection, variance swap pricing, and higher-order Greeks surfaces. Render 3D vol surfaces in Python, JavaScript, or any language with one API call.

T
Tomasz Dobrowolski Quant Engineer
Mar 29, 2026
39 min read
VolSurface SVI ImpliedVolatility API Python DeveloperGuide QuantFinance

If you've searched for "SVI surface API", "implied volatility surface API", "3D vol surface Python", or "build volatility surface visualizer", this is the guide. One endpoint gives you everything you need to render interactive 3D surfaces, skew charts, term structure plots, and arbitrage dashboards — without fitting anything yourself.


What Is a Volatility Surface and SVI Parameterization?

An implied volatility surface maps every (strike, expiry) pair to the Black-Scholes implied vol that reprices the observed option. In practice, you don't observe a smooth surface — you observe a sparse grid of noisy market quotes. To price exotics, compute local vol, or even just interpolate between strikes, you need a parametric fit.

Gatheral's SVI (Stochastic Volatility Inspired) parameterization is the industry standard. It maps log-moneyness k to total implied variance:

w(k) = a + b(ρ(k - m) + √((k - m)² + σ²))

Five parameters (a, b, rho, m, sigma) per expiry slice. Simple enough to write down, painful enough to calibrate reliably across thousands of names every day. The optimizer doesn't always converge. Butterfly constraints (non-negative risk-neutral density) require careful penalty terms. Calendar arbitrage between adjacent slices requires monotonicity in total variance. This is 2,000-5,000 lines of infrastructure code that someone maintains — or it's one API call.

The API Approach: What You Get in One Call

The Advanced Volatility endpoint (GET /v1/adv_volatility/{symbol}) returns a complete, pre-fitted SVI surface:

SectionContentsWhat You Build With It
svi_parametersa, b, rho, m, sigma per expiry + forward, ATM IV, fit RMSEReconstruct the smile at any strike, feed into pricing models
forward_pricesForward price, spot, basis in bps per expiryNo-arbitrage forward curve for discounting
total_variance_surface2D grids of total variance and implied vol across moneyness and expiries3D surface rendering, heatmaps, local vol computation
arbitrage_flagsButterfly and calendar violations with severity, location, descriptionAlert panels, surface quality dashboards
variance_swap_fair_valuesFair variance, fair vol, ATM IV, convexity adjustment per expiryWing richness analysis, vol risk premium from skew
greeks_surfaces2D grids of vanna, charm, volga, speed across strikes and expiriesHigher-order risk heatmaps, dealer hedging analysis

You also have the simpler public endpoint (GET /v1/surface/{symbol}) that returns an IV surface grid without SVI parameters — no auth required, useful for quick visualizations. For raw option chains with per-contract IV, there's GET /optionquote/{ticker} (Growth+). And GET /v1/volatility/{symbol} (Growth+) returns realized vol, IV-RV spreads, skew profiles, and term structure.

Quick Start: All 6 Languages

from flashalpha import FlashAlpha

fa = FlashAlpha("YOUR_API_KEY")
surface = fa.adv_volatility("SPY")

print(f"Expiries: {len(surface['svi_parameters'])}")
print(f"Arb flags: {len(surface['arbitrage_flags'])}")
print(f"Grid shape: {len(surface['total_variance_surface']['expiries'])} x {len(surface['total_variance_surface']['moneyness_grid'])}")
import { FlashAlpha } from 'flashalpha';

const fa = new FlashAlpha('YOUR_API_KEY');
const surface = await fa.advVolatility('SPY');

console.log(`Expiries: ${surface.svi_parameters.length}`);
console.log(`Grid: ${surface.total_variance_surface.expiries.length} x ${surface.total_variance_surface.moneyness_grid.length}`);
using FlashAlpha;

var fa = new FlashAlphaClient("YOUR_API_KEY");
var surface = await fa.AdvVolatilityAsync("SPY");

Console.WriteLine($"Expiries: {surface.SviParameters.Count}");
Console.WriteLine($"Arb flags: {surface.ArbitrageFlags.Count}");
fa := flashalpha.NewClient("YOUR_API_KEY")
surface, _ := fa.AdvVolatility(ctx, "SPY")

fmt.Printf("Expiries: %d\n", len(surface.SviParameters))
fmt.Printf("Arb flags: %d\n", len(surface.ArbitrageFlags))
FlashAlphaClient fa = new FlashAlphaClient("YOUR_API_KEY");
JsonObject surface = fa.advVolatility("SPY");

System.out.println("Expiries: " + surface.getAsJsonArray("svi_parameters").size());
System.out.println("Arb flags: " + surface.getAsJsonArray("arbitrage_flags").size());
curl -H "X-Api-Key: YOUR_API_KEY" \
  "https://lab.flashalpha.com/v1/adv_volatility/SPY"
$ pip install flashalpha  |  npm install flashalpha  |  dotnet add package FlashAlpha  |  go get github.com/FlashAlpha-lab/flashalpha-go

Full Response Walkthrough

Here's the structure of a real response (SPY, during market hours). Numeric arrays are truncated for readability:

{
  "symbol": "SPY",
  "underlying_price": 581.40,
  "as_of": "2026-03-29T14:30:00Z",
  "svi_parameters": [
    {
      "expiry": "2026-04-04",
      "dte": 6,
      "a": 0.004521,
      "b": 0.031245,
      "rho": -0.1823,
      "m": -0.0012,
      "sigma": 0.0845,
      "forward": 581.25,
      "atm_total_variance": 0.00295,
      "atm_iv": 17.9,
      "fit_rmse": 0.00018
    },
    {
      "expiry": "2026-04-17",
      "dte": 19,
      "a": 0.005812,
      "b": 0.028901,
      "rho": -0.2145,
      "m": -0.0028,
      "sigma": 0.0912,
      "forward": 582.10,
      "atm_total_variance": 0.00631,
      "atm_iv": 18.2,
      "fit_rmse": 0.00021
    },
    {
      "expiry": "2026-05-16",
      "dte": 48,
      "a": 0.008234,
      "b": 0.025678,
      "rho": -0.2534,
      "m": -0.0045,
      "sigma": 0.0988,
      "forward": 584.30,
      "atm_total_variance": 0.01752,
      "atm_iv": 19.1,
      "fit_rmse": 0.00015
    }
  ],
  "forward_prices": [
    { "expiry": "2026-04-04", "forward": 581.25, "spot": 581.40, "basis_bps": -2.6 },
    { "expiry": "2026-04-17", "forward": 582.10, "spot": 581.40, "basis_bps": 12.0 },
    { "expiry": "2026-05-16", "forward": 584.30, "spot": 581.40, "basis_bps": 49.9 }
  ],
  "total_variance_surface": {
    "moneyness_grid": [-0.50, -0.475, -0.45, "...", 0.45, 0.475, 0.50],
    "expiries": ["2026-04-04", "2026-04-17", "2026-05-16"],
    "total_variance": [["2D array: expiries x moneyness"]],
    "implied_vol": [["2D array: expiries x moneyness"]]
  },
  "arbitrage_flags": [
    {
      "type": "butterfly",
      "expiry": "2026-04-04",
      "moneyness": 0.35,
      "severity": "warning",
      "description": "Marginal negative density at deep OTM call wing",
      "value": -0.0003
    }
  ],
  "variance_swap_fair_values": [
    { "expiry": "2026-04-04", "fair_variance": 336.72, "fair_vol": 18.35, "atm_iv": 17.90, "convexity_adjustment_bps": 45.0 },
    { "expiry": "2026-04-17", "fair_variance": 357.96, "fair_vol": 18.92, "atm_iv": 18.20, "convexity_adjustment_bps": 72.0 },
    { "expiry": "2026-05-16", "fair_variance": 394.02, "fair_vol": 19.85, "atm_iv": 19.10, "convexity_adjustment_bps": 75.0 }
  ],
  "greeks_surfaces": {
    "strikes": [523.0, 535.0, 546.0, "...", 616.0, 628.0, 640.0],
    "expiries": ["2026-04-04", "2026-04-17", "2026-05-16"],
    "vanna": [["2D array"]],
    "charm": [["2D array"]],
    "volga": [["2D array"]],
    "speed": [["2D array"]]
  }
}

Every section maps directly to a visualization panel. Let's build them.

Visualization 1: 3D Implied Volatility Surface

The headline visualization. The total_variance_surface gives you a pre-computed grid of implied vol across moneyness and expiries — no interpolation needed.

import numpy as np
import plotly.graph_objects as go
from flashalpha import FlashAlpha

fa = FlashAlpha("YOUR_API_KEY")
data = fa.adv_volatility("SPY")

surface = data["total_variance_surface"]
k = np.array(surface["moneyness_grid"])
expiries = surface["expiries"]
iv = np.array(surface["implied_vol"])

# DTE for the y-axis (more intuitive than date strings)
from datetime import datetime, date
today = date.today()
dte = [(datetime.strptime(e, "%Y-%m-%d").date() - today).days for e in expiries]

fig = go.Figure(data=[go.Surface(
    x=k,
    y=dte,
    z=iv,
    colorscale="RdYlBu_r",
    colorbar=dict(title="IV (%)"),
    hovertemplate="Moneyness: %{x:.3f}
DTE: %{y}d
IV: %{z:.1f}%" )]) fig.update_layout( title="SPY Implied Volatility Surface (SVI-Fitted)", scene=dict( xaxis_title="Log-Moneyness", yaxis_title="Days to Expiry", zaxis_title="Implied Vol (%)", camera=dict(eye=dict(x=1.5, y=-1.8, z=0.8)) ), width=900, height=650 ) fig.show()

This produces an interactive 3D surface you can rotate, zoom, and hover over. The skew (downward slope in moneyness) and term structure (upward slope in DTE) are immediately visible. No fitting code, no optimizer, no convergence checks — just render the grid the API returns.

Visualization 2: Skew Smile Per Expiry

Slice the surface horizontally to see individual expiry smiles:

import matplotlib.pyplot as plt

surface = data["total_variance_surface"]
k = np.array(surface["moneyness_grid"])
iv = np.array(surface["implied_vol"])
expiries = surface["expiries"]

fig, ax = plt.subplots(figsize=(10, 5))
for i, expiry in enumerate(expiries):
    ax.plot(k, iv[i], label=f"{expiry}", linewidth=1.8)

ax.axvline(0, color="gray", linewidth=0.5, linestyle="--", label="ATM")
ax.set_xlabel("Log-Moneyness")
ax.set_ylabel("Implied Vol (%)")
ax.set_title("SPY Volatility Smile by Expiry")
ax.legend()
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()

Short-dated expiries show steeper skew (more pronounced put-wing richness). Longer-dated smiles flatten as mean reversion dominates. Your SVI parameters let you evaluate the smile at any moneyness — not just the grid points.

Visualization 3: ATM Term Structure

Extract ATM IV from the SVI parameters to plot the term structure:

svi = data["svi_parameters"]

dtes = [s["dte"] for s in svi]
atm_ivs = [s["atm_iv"] for s in svi]

fig, ax = plt.subplots(figsize=(8, 4))
ax.plot(dtes, atm_ivs, "o-", color="#7c3aed", linewidth=2, markersize=6)
ax.set_xlabel("Days to Expiry")
ax.set_ylabel("ATM Implied Vol (%)")
ax.set_title("SPY ATM IV Term Structure")
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()

An upward-sloping term structure (contango) is the typical regime for equity indices. Inversion (backwardation) signals near-term stress — the market is pricing higher uncertainty in the immediate future than the medium term.

Visualization 4: SVI Parameter Table

Display the raw SVI parameters for quant users who want to plug them into their own models:

print(f"{'Expiry':>12} {'DTE':>4} {'a':>9} {'b':>9} {'rho':>7} {'m':>8} {'sigma':>7} {'ATM IV':>7} {'RMSE':>8}")
print("-" * 82)
for s in data["svi_parameters"]:
    print(f"{s['expiry']:>12} {s['dte']:>4} {s['a']:>9.6f} {s['b']:>9.6f} {s['rho']:>7.4f} "
          f"{s['m']:>8.4f} {s['sigma']:>7.4f} {s['atm_iv']:>6.1f}% {s['fit_rmse']:>8.5f}")
      Expiry  DTE         a         b     rho        m   sigma  ATM IV     RMSE
----------------------------------------------------------------------------------
  2026-04-04    6  0.004521  0.031245 -0.1823  -0.0012  0.0845   17.9% 0.00018
  2026-04-17   19  0.005812  0.028901 -0.2145  -0.0028  0.0912   18.2% 0.00021
  2026-05-16   48  0.008234  0.025678 -0.2534  -0.0045  0.0988   19.1% 0.00015

The fit_rmse tells you how well the SVI curve fits the observed market quotes. Values below 0.001 indicate tight fits. The rho parameter captures skew direction and magnitude — negative rho means the put wing is steeper than the call wing, which is standard for equity indices.

Visualization 5: Arbitrage Flag Panel

Static arbitrage in a fitted surface means your prices are wrong in a way that creates unbounded risk. The API checks both butterfly (negative density) and calendar (non-monotonic total variance) violations automatically:

flags = data["arbitrage_flags"]

if not flags:
    print("Surface is arbitrage-free")
else:
    print(f"{len(flags)} arbitrage flag(s) detected:\n")
    for f in flags:
        icon = "!!" if f["severity"] == "violation" else "!"
        print(f"  [{icon}] {f['type'].upper()} | {f['expiry']} | moneyness={f['moneyness']:.3f}")
        print(f"      {f['description']}")
        print(f"      value: {f['value']:.6f} | severity: {f['severity']}")
        print()

Butterfly violations indicate negative risk-neutral density — a butterfly spread at those strikes is a free lunch. Calendar violations mean total variance decreases between expiries at the same moneyness — a calendar spread is a free lunch. Both are checked on every request. If you're pricing exotics off a surface that contains these violations, your hedges are wrong.

Visualization 6: Variance Swap Fair Values

The fair variance swap strike is computed by integrating the SVI-fitted smile across all strikes. The convexity adjustment (fair vol minus ATM IV) measures how much the wings contribute beyond ATM pricing:

print(f"{'Expiry':>12} {'Fair Vol':>9} {'ATM IV':>7} {'Convexity':>10} {'Fair Var':>9}")
print("-" * 52)
for vs in data["variance_swap_fair_values"]:
    conv_pp = vs["convexity_adjustment_bps"] / 100
    print(f"{vs['expiry']:>12} {vs['fair_vol']:>8.2f}% {vs['atm_iv']:>6.2f}% {conv_pp:>+9.2f}pp {vs['fair_variance']:>9.2f}")
      Expiry  Fair Vol  ATM IV  Convexity  Fair Var
----------------------------------------------------
  2026-04-04    18.35%  17.90%     +0.45pp    336.72
  2026-04-17    18.92%  18.20%     +0.72pp    357.96
  2026-05-16    19.85%  19.10%     +0.75pp    394.02

A large convexity adjustment means the wings (OTM puts especially) are priced richly relative to ATM. Track this over time and you have a clean signal for the vol risk premium embedded in the skew. When convexity spikes, tail hedges are expensive. When it compresses, wings are cheap relative to ATM.

Visualization 7: Higher-Order Greeks Surfaces

The greeks_surfaces section provides 2D grids of vanna, charm, volga, and speed across strikes and expiries. These are the second and third-order sensitivities that drive dealer hedging dynamics:

import matplotlib.pyplot as plt
import numpy as np

greeks = data["greeks_surfaces"]
strikes = np.array(greeks["strikes"])
expiries = greeks["expiries"]

fig, axes = plt.subplots(2, 2, figsize=(14, 10))

for ax, name in zip(axes.flat, ["vanna", "charm", "volga", "speed"]):
    values = np.array(greeks[name])
    im = ax.imshow(values, aspect="auto", cmap="RdBu_r",
                   extent=[strikes[0], strikes[-1], len(expiries)-0.5, -0.5])
    ax.set_yticks(range(len(expiries)))
    ax.set_yticklabels(expiries, fontsize=8)
    ax.set_xlabel("Strike")
    ax.set_title(name.capitalize(), fontweight="bold")
    plt.colorbar(im, ax=ax, shrink=0.8)

plt.suptitle("SPY Higher-Order Greeks Surfaces", fontsize=14, fontweight="bold")
plt.tight_layout()
plt.show()

Vanna shows where delta shifts as vol moves — when dealers are short vanna, a spot drop + vol spike forces them to sell shares, amplifying the move. Charm shows overnight delta drift. Volga measures exposure to vol-of-vol. Speed shows how fast gamma shifts as spot moves. Each surface tells a different story about market microstructure and hedging pressure.

$ pip install flashalpha plotly
>>> fa = FlashAlpha("YOUR_KEY")
>>> surface = fa.adv_volatility("SPY")
{"svi_parameters": [{"expiry": "2026-04-04", "a": 0.004521, ...}], "arbitrage_flags": [...], ...}

Complete Plotly 3D Surface: Copy-Paste Code

Here's a self-contained Python script that pulls the SVI surface and renders an interactive 3D visualization with Plotly. Copy, paste, replace the API key, and run.

"""
Vol Surface Visualizer - FlashAlpha API + Plotly
Renders an interactive 3D implied volatility surface from pre-fitted SVI data.
"""
import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from flashalpha import FlashAlpha
from datetime import datetime, date

# --- Config ---
API_KEY = "YOUR_API_KEY"
SYMBOL = "SPY"

# --- Fetch data ---
fa = FlashAlpha(API_KEY)
data = fa.adv_volatility(SYMBOL)

surface = data["total_variance_surface"]
svi = data["svi_parameters"]
varswap = data["variance_swap_fair_values"]

k = np.array(surface["moneyness_grid"])
iv = np.array(surface["implied_vol"])
expiries = surface["expiries"]
today = date.today()
dte = [(datetime.strptime(e, "%Y-%m-%d").date() - today).days for e in expiries]

# --- 3D Surface ---
fig = make_subplots(
    rows=1, cols=2,
    specs=[[{"type": "surface"}, {"type": "xy"}]],
    subplot_titles=[f"{SYMBOL} IV Surface (SVI-Fitted)", f"{SYMBOL} ATM Term Structure"],
    column_widths=[0.6, 0.4]
)

fig.add_trace(
    go.Surface(
        x=k, y=dte, z=iv,
        colorscale="RdYlBu_r",
        colorbar=dict(title="IV (%)", x=0.45),
        hovertemplate="k: %{x:.3f}
DTE: %{y}d
IV: %{z:.1f}%" ), row=1, col=1 ) # --- Term structure --- atm_iv = [s["atm_iv"] for s in svi] fair_vol = [vs["fair_vol"] for vs in varswap] svi_dte = [s["dte"] for s in svi] fig.add_trace( go.Scatter(x=svi_dte, y=atm_iv, mode="lines+markers", name="ATM IV", line=dict(color="#7c3aed", width=2), marker=dict(size=7)), row=1, col=2 ) fig.add_trace( go.Scatter(x=svi_dte, y=fair_vol, mode="lines+markers", name="Fair Vol (VarSwap)", line=dict(color="#16a34a", width=2, dash="dash"), marker=dict(size=7)), row=1, col=2 ) fig.update_layout( height=600, width=1200, scene=dict( xaxis_title="Log-Moneyness", yaxis_title="DTE", zaxis_title="IV (%)", camera=dict(eye=dict(x=1.5, y=-1.8, z=0.8)) ), xaxis2=dict(title="Days to Expiry"), yaxis2=dict(title="Implied Vol (%)"), showlegend=True ) # --- Print arb flags --- flags = data["arbitrage_flags"] if flags: print(f"\n{len(flags)} arbitrage flag(s):") for f in flags: print(f" [{f['severity']}] {f['type']} at {f['expiry']}, k={f['moneyness']:.3f}: {f['description']}") else: print("\nSurface is arbitrage-free.") fig.show()

This renders a side-by-side view: the 3D surface on the left and the ATM term structure (with variance swap fair vol overlay) on the right. The gap between ATM IV and fair vol is the convexity adjustment — visible at a glance.

JavaScript Chart Rendering

For browser-based visualizations, the response maps directly to any 3D charting library. With Plotly.js:

import { FlashAlpha } from 'flashalpha';
import Plotly from 'plotly.js-dist';

const fa = new FlashAlpha('YOUR_API_KEY');
const data = await fa.advVolatility('SPY');

const surface = data.total_variance_surface;

Plotly.newPlot('chart', [{
  type: 'surface',
  x: surface.moneyness_grid,
  y: surface.expiries,
  z: surface.implied_vol,
  colorscale: 'RdYlBu',
  reversescale: true,
  colorbar: { title: 'IV (%)' }
}], {
  title: 'SPY Implied Volatility Surface',
  scene: {
    xaxis: { title: 'Log-Moneyness' },
    yaxis: { title: 'Expiry' },
    zaxis: { title: 'IV (%)' }
  }
});

The same approach works with Three.js, Deck.gl, or any WebGL-based library. The key point: the API returns the grid, you render it. No fitting, no interpolation, no numerical code in your frontend.

Using Vol Surface Data with AI Agents

FlashAlpha provides an MCP (Model Context Protocol) server that lets AI coding assistants query vol surface data directly. Connect Claude, Cursor, Windsurf, or any MCP-compatible agent:

{
  "mcpServers": {
    "flashalpha": {
      "url": "https://lab.flashalpha.com/mcp",
      "headers": {
        "X-Api-Key": "YOUR_API_KEY"
      }
    }
  }
}

The agent can then pull SVI parameters, check arbitrage flags, compare variance swap convexity adjustments across symbols, and generate surface analysis — all grounded in live data. Ask the agent to "compare SPY and QQQ skew" or "check if the TSLA surface has arbitrage violations" and it will call the endpoint, interpret the response, and give you a structured answer.

Why Not Build It Yourself?

You can. Here's what that project looks like:

  1. Raw option chain data source — OPRA feed or vendor API (Polygon, Intrinio, ThetaData). Budget $200-2,500/mo just for data.
  2. Chain filtering — Remove stale quotes, zero-OI strikes, wide markets, penny-wide illiquid options that will poison your fit.
  3. Forward price estimation — Put-call parity with dividend adjustments. Errors here propagate into every SVI parameter.
  4. SVI calibration per expiry — Levenberg-Marquardt or trust-region optimizer. Handle non-convergence, local minima, and numerical instability. The raw SVI parameterization has five free parameters and a non-convex loss surface. 500-1,000 lines of code.
  5. Butterfly constraint enforcement — Ensure the second derivative of total variance w.r.t. moneyness is non-negative everywhere. Requires either penalty terms in the objective function or a constrained optimization formulation.
  6. Calendar constraint enforcement — Ensure total variance is non-decreasing across expiries at every moneyness point. This couples the calibration of adjacent slices, adding significant complexity.
  7. Surface interpolation — Build the full 2D grid from per-expiry SVI fits. Choose an interpolation scheme (linear in total variance, cubic in vol, etc.).
  8. Variance swap integration — Numerical integration of the smile to compute fair variance swap strikes. Handle truncation at the wings.
  9. Higher-order Greeks — Finite-difference computation of vanna, charm, volga, speed across the strike/expiry grid. Requires a well-fitted surface to avoid noise amplification.
  10. Infrastructure — Run all of this for your universe on a schedule. Monitor data quality, handle feed outages, cache and invalidate, manage compute costs.

That's 3-6 months of engineering and ongoing maintenance. When the optimizer breaks on a low-liquidity name at 9:35am and your surface is stale, someone debugs it. The FlashAlpha endpoint exists so you don't have to.

API Access and Pricing

The Advanced Volatility endpoint with SVI parameters requires the Alpha plan. The simpler IV surface grid (/v1/surface/{symbol}) is available on the free tier with no authentication.

PlanPriceSVI ParametersIV Surface GridRate Limit
Free$0NoYes (public)5 req/day
Basicfrom $63/moNoYes100 req/day
Growthfrom $239/moNoYes2,500 req/day
Alphafrom $1,199/moYesYesUnlimited

The Alpha plan includes unlimited API requests, SVI-smoothed IV on all option quotes, zero-cache responses, and dedicated support. SDKs in Python, JavaScript, C#, Go, and Java with typed exceptions and automatic retries. Explore data visually on per-stock dashboards at flashalpha.com/stock/{ticker} before writing code.

α Alpha Plan

The Advanced Volatility endpoint is on the Alpha plan: unlimited API requests, SVI-smoothed IV on all option quotes, zero cache, and dedicated support.

Questions about integration or want to discuss your use case? Reply to any email from us or reach out at [email protected].

View Alpha Plan →

Frequently Asked Questions

An SVI volatility surface API returns pre-calibrated Gatheral SVI parameters (a, b, rho, m, sigma) per expiry slice, along with a total variance grid, arbitrage detection, and derived quantities like variance swap fair values. Instead of fitting SVI parameters yourself, you call the API and get a production-quality surface in structured JSON. FlashAlpha's /v1/adv_volatility/{symbol} endpoint returns all of this for 6,000+ US equities and ETFs.
Use the FlashAlpha SDK to pull the pre-fitted surface, then render with Plotly or matplotlib. Three lines: fa = FlashAlpha("KEY"), data = fa.adv_volatility("SPY"), then pass data["total_variance_surface"]["implied_vol"] to go.Surface(). The API returns the complete 2D grid — no fitting or interpolation code needed.
Two types of static arbitrage are checked automatically: butterfly arbitrage (negative risk-neutral density, meaning the second derivative of total variance w.r.t. moneyness goes negative) and calendar arbitrage (total variance decreasing from one expiry to the next at the same moneyness). Both are returned as structured flags with type, location, severity, and description.
Yes. The /v1/surface/{symbol} endpoint is public and requires no API key. It returns an IV surface grid suitable for basic visualizations. For SVI parameters, arbitrage detection, variance swap pricing, and Greeks surfaces, you need the Alpha plan and the /v1/adv_volatility/{symbol} endpoint.
The convexity adjustment is the difference between the fair variance swap vol (computed by integrating the full smile) and ATM IV. A large positive adjustment means the wings — particularly OTM puts — are priced richly. It measures the vol risk premium embedded in the skew beyond what ATM IV captures. The API returns this per expiry so you can track wing richness over time.
No. The API returns pre-calibrated SVI parameters with fit quality metrics (RMSE). The fits use weighted least-squares with ATM bias and enforce butterfly and calendar arbitrage constraints. You can evaluate fit quality from the RMSE values and compare against your own calibration if you have one.

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!