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
- 49 typed methods: full coverage of every typed /v1/* operationId. Compute (price, greeks, exposure, scenario, sensitivity, max pain, expected move, probability, calibrate) plus 40 data endpoints (snapshot, metrics, IV surface, Greeks history, ATS/OTC/blocks, calendars, FRED, Treasury, bond ETFs, news).
- 17 pricing models: Black-Scholes, Heston, SABR, Jump Diffusion, FFT, PDE, Binomial, Compound, Asian, Barrier, Multi-Asset. One signature, one return type; switch models with a string.
- Drift-checked against the spec: a drift gate test fails CI if the SDK manifest gets out of sync with /openapi.json. You cannot accidentally ship a stale SDK.
- Calibration round-trip: calibration helper persists fitted model params (Heston, SABR, Variance Gamma, Jump Diffusion, or Local Vol) to disk. Reload hours later, evaluate anywhere across the chain; never re-touches the 30-second calibrationId TTL.
- BYOK helpers: TradierCredentials and TastytradeCredentials forward broker tokens transparently for live-chain calibration. No data markup, no proxy fees.
- Typed errors: every error subclass carries the HTTP status, server error code, and structured fields (retry_after, bucket, required_scope, resets_at). No JSON-key archaeology.
Who it's for
- Quants (calibrate, evaluate, refit): fit any of the 5 calibrateable models (Heston, SABR, Variance Gamma, Jump Diffusion, Local Vol) once via /compute/calibrate, persist the fitted params, evaluate fair value or full Greeks anywhere across the chain. Refit on a schedule with a single call.
- Backtesters (historical IV, Greeks, regime): pull Greeks history, IV surface snapshots, regime classifications, and ATS/OTC volume across years; one method per dataset, all typed.
- AI agents (LLM-friendly typed responses): Pydantic v2 models give an LLM-callable surface that fails loudly on schema drift. Pair with the OpenAPI spec for tool-use definitions.
- Algo traders (real-time GEX/DEX exposure): pre-computed dealer gamma/delta exposure by strike, max pain, expected move, IV rank; call once per ticker, cached at the edge.
FAQ
- Do I need a separate API key, or does my web subscription work? API access is its own tier ($99/mo). The web app subscription does not include programmatic access. See pricing for details.
- Does the SDK require Python 3.12? Python 3.10+ is supported. CI runs on 3.10, 3.11, and 3.12.
- How do I handle calibration with a broker token? Pass a TradierCredentials or TastytradeCredentials instance to client.calibrate(...). The SDK forwards the broker token in the documented headers; the server pulls the live chain and fits the model. No markup.
- What happens to my code when the API spec changes? New fields are silently ignored by older SDK versions (extra="ignore" forward-compat). New endpoints fail the drift gate test until added to the manifest. Type-changes are caught by mypy --strict on regen. The drift gate is the forcing function.
- Is there an async client? Synchronous only in 0.1.x. AsyncOASClient is on the roadmap once a user need surfaces.
Ready to build?
The SDK is free and open. API access (the data + compute key) is the API tier.