Liquidity API - Per-Expiry Execution Score & Spreads - FlashAlpha Lab API
Lab API Liquidity

Liquidity API

Per-expiry execution score (0-100), ATM bid-ask spread %, OI-weighted spread %, ATM OI depth, plus chain-level OI-weighted score and best/worst expiry.

Endpoint

GET /v1/liquidity/{symbol}
Auth required (X-Api-Key) Rate Limited: Yes Growth plan+

Parameters

Name In Required Default Description
symbol path yes - Underlying symbol
curl -H "X-Api-Key: YOUR_API_KEY" \
  "https://lab.flashalpha.com/v1/liquidity/SPY"
import requests

resp = requests.get(
    "https://lab.flashalpha.com/v1/liquidity/SPY",
    headers={"X-Api-Key": "YOUR_API_KEY"}
)
data = resp.json()
print(f"Chain score: {data['chain_execution_score']}")
const resp = await fetch(
  "https://lab.flashalpha.com/v1/liquidity/SPY",
  { headers: { "X-Api-Key": "YOUR_API_KEY" } }
);
const data = await resp.json();
console.log("Chain score: " + data.chain_execution_score);

Response

{
  "symbol": "SPY",
  "underlying_price": 597.50,
  "as_of": "2026-05-29T15:30:00Z",
  "chain_execution_score": 78,
  "best_expiry": "2026-05-30",
  "worst_expiry": "2027-01-15",
  "thin_expiry_count": 1,
  "expiries": [
    { "expiration": "2026-05-30", "dte": 1,   "atm_spread_pct": 0.45, "weighted_spread_pct": 1.10, "atm_oi": 48200, "execution_score": 86, "label": "tight" },
    { "expiration": "2026-06-18", "dte": 20,  "atm_spread_pct": 0.78, "weighted_spread_pct": 1.95, "atm_oi": 31400, "execution_score": 68, "label": "normal" }
  ]
}

Key Response Fields

Field Description
chain_execution_scoreOI-weighted average of per-expiry execution_score across the chain (0-100).
best_expiry / worst_expiryExpirations with the highest / lowest execution_score.
thin_expiry_countNumber of expiries labelled illiquid.
expiries[].atm_spread_pctAverage bid-ask spread % at the strike closest to spot, across the side(s) that quote. null when neither side quotes.
expiries[].weighted_spread_pctOI-weighted bid-ask spread % across contracts in the expiry that both carry OI (> 0) and quote a valid spread (ask > bid > 0). null when no contract satisfies both.
expiries[].atm_oiSum of call+put OI at the strike closest to spot.
expiries[].execution_score0-100. Composite: 70% spread-tightness (exp-decay) + 30% ATM-OI depth (5000 contracts saturates). Same formula as /v1/exposure/zero-dte's liquidity.execution_score.
expiries[].labelDiscrete bucket derived from execution_score: tight (≥75) / normal (≥50) / wide (≥20) / illiquid (<20).

Errors

Status Description
403Requires Growth plan or higher
404Symbol not found or no options data

About

Returns a per-expiry execution score (0-100) alongside ATM bid-ask spread %, OI-weighted spread %, and ATM OI depth, plus a chain-level OI-weighted score and the best/worst expiry. Each expiry carries a label: tight (≥75) / normal (≥50) / wide (≥20) / illiquid (<20).

The score is heuristic - read the label and direction of the number rather than treating any threshold as a hard tradability rule. Expirations with all-zero OI or only one-sided quotes still appear; they typically score 0 and label illiquid. Read chain_execution_score alongside best_expiry to judge whether "best" actually means tradable.

Common Use Cases

  • Route to the cleanest expiry by selecting best_expiry (or the highest per-expiry execution_score) before sending a multi-leg order
  • Gate a watchlist on chain_execution_score so only names with a tradable chain reach the order stage
  • Skip label: illiquid expiries to keep slippage out of backtests and live fills
  • Size and price limit orders off expiries[].atm_spread_pct and weighted_spread_pct rather than crossing the full quoted spread
  • Confirm depth at the working strike with expiries[].atm_oi before scaling order size
  • Alert on thin_expiry_count rising or chain_execution_score falling to catch degrading liquidity before it bites
  • Sanity-check a "best" expiry by reading worst_expiry alongside it, since "best" can still be untradeable on thin names

Related reading

Complementary endpoints

  • Option Quote - the per-contract bid/ask/OI behind each expiry's spread and depth figures
  • Screener - filter the universe down to names that pass a liquidity threshold
  • Volatility - read IV and term structure on the expiries that score as executable
  • SVI Parameters - the calibrated surface fit you should run only on liquid expiries

Ready to build?

Get your free API key and start pulling live options data in 30 seconds.