SDKs Python

FlashAlpha Python SDK

Official Python 3.10+ SDK for the FlashAlpha options analytics API. Exposure analytics, volatility, pricing, and the live options screener — with typed errors and a single dependency.

Install
pip install flashalpha
Version
0.3.0 · Python 3.10+
GitHub PyPI Single dep: requests MIT license

What the SDK gives you

Full endpoint coverage

Every REST endpoint — market data, exposure (GEX/DEX/VEX/CHEX), volatility, pricing, screener, account — is a typed method call.

Live options screener

Build filter/sort/select queries as Python dicts, including Alpha-tier formulas and cascading expiry/strike/contract filters.

Typed error hierarchy

AuthenticationError, TierRestrictedError, NotFoundError, RateLimitError, ServerError — all inherit from FlashAlphaError.

Dependency-light

Single runtime dependency: requests. Works inside pandas/numpy/polars pipelines without version conflicts.

Configurable client

Override base_url and timeout. Reuse a single FlashAlpha instance across your app — it pools HTTP connections.

Tier-aware responses

403 responses raise TierRestrictedError with current_plan and required_plan, so you can catch and prompt users to upgrade.

Install

pip install flashalpha

Requires Python 3.10 or newer. Grab your API key from your profile page — the Free tier needs no credit card.

Quick start

from flashalpha import FlashAlpha

fa = FlashAlpha("YOUR_API_KEY")

# Gamma exposure for SPY
gex = fa.gex("SPY")
print(gex["net_gex"], gex["gamma_flip"])

# Key support / resistance levels
key = fa.exposure_levels("SPY")["levels"]
print(key["call_wall"], key["put_wall"])

# BSM greeks for a single contract
g = fa.greeks(spot=655, strike=660, dte=7, sigma=0.18, type="call")
print(g["delta"], g["gamma"], g["theta"])

# Plan & quota usage
print(fa.account())

Live options screener

Screen the live universe by stock-, expiry-, strike-, or contract-level fields. On Alpha tier you get formulas and harvest scores.

# Harvestable VRP setups (Alpha tier)
result = fa.screener(
    filters={
        "op": "and",
        "conditions": [
            {"field": "regime",           "operator": "eq",  "value": "positive_gamma"},
            {"field": "vrp_regime",       "operator": "eq",  "value": "harvestable"},
            {"field": "dealer_flow_risk", "operator": "lte", "value": 40},
            {"field": "harvest_score",    "operator": "gte", "value": 65},
        ],
    },
    sort=[{"field": "harvest_score", "direction": "desc"}],
    select=["symbol", "price", "harvest_score", "dealer_flow_risk", "vrp_regime"],
)

for row in result["data"]:
    print(row["symbol"], row["harvest_score"])

Common recipes

Results into a pandas DataFrame

import pandas as pd

# GEX profile per strike, as a DataFrame
gex = fa.gex("SPY")
df = pd.DataFrame(gex["strikes"])
df["pct"] = df["net_gex"] / df["net_gex"].abs().sum()
print(df.sort_values("net_gex", ascending=False).head())

Poll the screener on a schedule

import time
from flashalpha import FlashAlpha, RateLimitError

fa = FlashAlpha("YOUR_API_KEY")

while True:
    try:
        top = fa.screener(
            sort=[{"field": "net_gex", "direction": "desc"}],
            select=["symbol", "net_gex", "regime"],
            limit=5,
        )
        for row in top["data"]:
            print(row)
    except RateLimitError as e:
        time.sleep(e.retry_after or 10)
        continue
    time.sleep(30)   # screener data refreshes every 5–10s

Cascading filters (0DTE call sellers)

# Dotted-prefix fields trim the tree down to matching contracts only
fa.screener(
    filters={
        "op": "and",
        "conditions": [
            {"field": "expiries.days_to_expiry", "operator": "eq",  "value": 0},
            {"field": "contracts.type",          "operator": "eq",  "value": "C"},
            {"field": "contracts.delta",         "operator": "gte", "value": 0.3},
            {"field": "contracts.oi",            "operator": "gte", "value": 1000},
        ],
    },
    select=["*"],
)

Method catalog

Every REST endpoint is a method on the FlashAlpha client. All methods return Python dict / list structures parsed from JSON.

CategoryMethodsTier
Market datastock_quote, option_quote, stock_summary, surfaceFree / Growth
Historical replay (point-in-time)historical_stock_quote, historical_option_quote, plus the full live API mirrored on historical.flashalpha.com via FlashAlpha(api_key, base_url="https://historical.flashalpha.com") with at= paramAlpha
Exposure (basic)gex, exposure_levelsFree+ (equities); Basic+ for ETFs & indexes
Exposure (Greeks)dex, vex, chex, maxpainBasic+
Exposure (Growth)exposure_summary, narrative, zero_dte, exposure_historyGrowth+
Pricinggreeks, iv, kellyFree / Growth
Volatilityvolatility, adv_volatilityGrowth / Alpha
ScreenerscreenerGrowth+
Referencetickers, options, symbolsFree+
Accountaccount, healthFree+

See the endpoint index for the full list of REST paths and response schemas.

Historical backtest pattern

The Alpha-tier Historical API mirrors every live endpoint shape. The SDK's high-level analytics methods (gex, vrp, maxpain, …) don't yet pass through the at= parameter (planned, not shipped as of flashalpha==0.3.7). For the historical-replay path, hit the REST endpoint directly with requests: response shape matches the SDK's live response exactly, so analysis code stays the same.

from datetime import datetime, timedelta
import requests

API_KEY = "YOUR_ALPHA_KEY"
HIST = "https://historical.flashalpha.com"
S = requests.Session()
S.headers.update({"X-Api-Key": API_KEY})

# 1. coverage check - never assume a symbol is backfilled
coverage = {t["symbol"]: t["coverage"]
            for t in S.get(f"{HIST}/v1/tickers").json()["tickers"]}
assert "SPY" in coverage

# 2. cache by (endpoint, symbol, at) - historical days are immutable once healthy
cache = {}
def gex_at(symbol, ts):
    key = ("gex", symbol, ts)
    if key not in cache:
        r = S.get(f"{HIST}/v1/exposure/gex/{symbol}", params={"at": ts})
        r.raise_for_status()
        cache[key] = r.json()
    return cache[key]

# 3. step through trading days, detect gamma-flip transitions
prev = None; flips = []
for d in (datetime(2024,7,1) + timedelta(days=i) for i in range((datetime(2024,9,30)-datetime(2024,7,1)).days+1)):
    if d.weekday() >= 5: continue
    snap = gex_at("SPY", f"{d:%Y-%m-%d}T10:30:00")
    regime = "neg" if snap["net_gex"] < 0 else "pos"
    if prev and regime != prev:
        flips.append((d, prev, regime, snap["underlying_price"]))
    prev = regime

# 4. join to your own price/return series and compute strategy P&L

# For LIVE calls in the same script you can use the SDK normally:
from flashalpha import FlashAlpha
fa = FlashAlpha(API_KEY)
live_snap = fa.gex("SPY")            # response shape matches the historical dict

Pitfalls. vrp.percentile is null until ~60 prior trading days accumulate (leak-free design). optionquote returns svi_vol: null with svi_vol_gated: "backtest_mode" intraday because SVI fits are stamped EOD - use implied_vol intraday or call at=YYYY-MM-DD for the EOD snapshot. at is ET wall-clock - do NOT add a trailing Z and do NOT shift by UTC offset. Never call live endpoints inside a historical backtest.

Full cookbook + six-step workflow + schema divergences from live: Historical API docs and historical.md ("Historical Backtest Cookbook" section).

Error handling

Non-2xx responses are converted to typed exceptions. Catch the specific class you care about, or FlashAlphaError as a catch-all.

from flashalpha import (
    FlashAlpha, FlashAlphaError,
    AuthenticationError, TierRestrictedError,
    NotFoundError, RateLimitError, ServerError,
)

fa = FlashAlpha("YOUR_API_KEY")

try:
    result = fa.narrative("SPY")
except TierRestrictedError as e:
    print(f"Need {e.required_plan}, currently on {e.current_plan}")
except RateLimitError as e:
    print(f"Slow down — retry after {e.retry_after}s")
except NotFoundError:
    print("Symbol not found")
except FlashAlphaError as e:
    print(f"API error {e.status_code}: {e}")
HTTPExceptionCarries
401AuthenticationError
403TierRestrictedErrorcurrent_plan, required_plan
404NotFoundError
429RateLimitErrorretry_after (seconds)
5xxServerErrorstatus_code
otherFlashAlphaErrorstatus_code, response

Client configuration

fa = FlashAlpha(
    api_key="...",
    base_url="https://lab.flashalpha.com",  # default
    timeout=30,                              # seconds
)

The client sends X-Api-Key on every request and pools connections via requests.Session. Reuse the same instance across your app.

Links

Ready to build?

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