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 with FlashAlpha?

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

No credit card required Setup in 60 seconds Secure & reliable