← Back to Home

Python SDK for the Options Analysis Suite API

Type-safe httpx + Pydantic v2 client. 17 pricing models, full Greeks, GEX/DEX exposure, IV surfaces, and 5-model calibration (Heston, SABR, Variance Gamma, Jump Diffusion, Local Vol), drift-checked against the deployed OpenAPI spec.

View on PyPI · OpenAPI 3.1 Docs

pip install options-analysis-suite

Quickstart

Cached end-of-day snapshot (max pain, GEX, atmIV, IV rank) and on-demand pricing with any of 17 models, in five lines.

from oas import OASClient

with OASClient(api_key="oas_live_...") as client:
    # End-of-day analytics: spot, atmIv, GEX, DEX, max pain, IV rank, ...
    snap = client.snapshot("SPY")
    print(snap.spotPrice, snap.atmIv, snap.netGex, snap.maxPain)

    # 17 pricing models, all with the same signature.
    price = client.price(model="bs", is_call=True, S=650, K=655,
                         r=0.05, q=0.012, sigma=0.18, t=0.25)
    greeks = client.greeks(model="heston", is_call=True, S=650, K=655,
                           r=0.05, q=0.012, sigma=0.18, t=0.25)

Calibrate, persist, reuse

Calibration is the most expensive call in the API. The SDK wraps a fit in a Calibration object you can persist to disk and reload later: no second fit, no calibrationId-TTL games.

from oas import OASClient, Calibration, TradierCredentials

with OASClient(api_key="oas_live_...") as client:
    # Fit Heston to the live SPY chain via your broker's data - no markup.
    cal = client.calibrate(
        "SPY", model="heston",
        broker=TradierCredentials(token="..."),
    )
    cal.save("spy_heston.json")  # persist fitted params to disk

# Days later, in another process - no re-fit needed:
cal = Calibration.from_json("spy_heston.json")
with OASClient(api_key="oas_live_...") as client:
    cal.bind(client)
    fair = cal.price(is_call=True, K=655, expiry="2026-06-19")
    g = cal.greeks(is_call=True, K=655, expiry="2026-06-19")

Stream batched metrics across a watchlist

iter_metrics auto-chunks across /v1/data/metrics/batch: one HTTP call per 50 symbols, IV rank and max pain returned typed.

from oas import OASClient

with OASClient(api_key="oas_live_...") as client:
    # Auto-chunks across /v1/data/metrics/batch - one call per 50 symbols.
    watchlist = ["SPY", "QQQ", "IWM", "DIA", "TLT", "GLD", "USO", "VIX"]
    for m in client.iter_metrics(watchlist, batch_size=50):
        print(f"{m.symbol:5s} ivRank={m.ivRank:.2f} "
              f"P/C={m.putCallRatio:.2f} maxPain={m.maxPain}")

Typed errors with structured fields

Every error subclass surfaces the HTTP status, the server's structured error code, and the relevant context fields.

from oas.errors import (
    NotFoundError, RateLimitError,
    CalibrationQuotaError, PermissionDeniedError,
)

try:
    snap = client.snapshot("UNKNOWN")
except NotFoundError as e:
    print(f"warehouse miss: {e}")
except RateLimitError as e:
    # Server-emitted Retry-After + bucket info preserved.
    print(f"slow down - retry in {e.retry_after}s (bucket: {e.bucket})")
except CalibrationQuotaError as e:
    print(f"calibration quota exhausted; resets at {e.resets_at}")
except PermissionDeniedError as e:
    print(f"need scope: {e.required_scope}")

What's in the box

Who it's for

FAQ

Ready to build?

The SDK is free and open. API access (the data + compute key) is the API tier.

View Pricing · View on PyPI