{"openapi":"3.1.0","jsonSchemaDialect":"https://json-schema.org/draft/2020-12/schema","info":{"title":"Options Analysis Suite API","version":"1.0.0","description":"Institutional-grade options analytics API. Programmatic access to 17 pricing models (including 7 exotic options), auto-calibration, real-time exposure analytics, WebSocket streaming, and pre-computed market data.\n\n## Features\n\n- **17 pricing models** — 10 standard (Black-Scholes, Heston, SABR, FFT (Carr-Madan with 6 characteristic functions), Variance Gamma, Jump Diffusion (Kou/Bates/Merton), Binomial, PDE, Monte Carlo, Local Volatility (Dupire + eSSVI)) plus 7 exotic (Barrier, Asian, Lookback, Digital, Compound, Chooser, Multi-Asset) with optional strategy-insight card via `includeInsight`\n- **Auto-calibration** — Heston, SABR, VG, JD, and Local Vol calibrate against live broker chain data in 0.25-16s\n- **Greek exposure** — GEX, DEX, VEX, Vanna, Charm, Vomma with gamma flip detection, call/put walls, abs gamma anchor, dealer positioning regime\n- **Real-time streaming** — WebSocket endpoint for live quotes, Greeks, and computed exposure snapshots\n- **Pre-computed data** — market regime, IV surfaces, snapshots, metrics, scanner, risk-neutral + lognormal probability distributions\n\n## Authentication\n\nAll `/v1/*` endpoints require an API key. Pass it via either header:\n\n- `Authorization: Bearer oas_live_...`\n- `X-API-Key: oas_live_...`\n\n## Rate limits\n\nSeparate buckets for data and compute endpoints (per user, shared across all API keys):\n\n- **Data** (`/v1/data/*`): **120 requests/minute**\n- **Compute** (`/v1/compute/*`): **120 requests/minute**\n- **Cheap compute** (BS, binomial, exposure, max pain, expected move): max **6 concurrent**\n- **Heavy compute** (MC, PDE, Heston, Local Vol, SABR, JD, VG, scenario, sensitivity): max **2 concurrent**\n- **Calibration**: max **1 concurrent** job (own lane, separate from compute pools) · hard-capped at **500/day** per user\n- Heavy compute endpoints may return **503** when worker capacity is unavailable\n- 429 responses include `X-RateLimit-Bucket` header (`data` or `compute`)\n\n## Broker credentials (BYOK)\n\nSome endpoints (calibration, full-mode probability, streaming) require live broker chain data. The API doesn't pay for market data — you supply your own credentials via headers:\n\n- **TastyTrade**: `X-Broker-Type: tastytrade`, `X-Tastytrade-Refresh-Token`, `X-Tastytrade-Client-Secret`\n- **Tradier**: `X-Broker-Type: tradier`, `X-Tradier-Key`\n\nNote: Public.com is **not supported on the API tier** (their Individual API program restricts third-party platforms). Public is available on the Pro webapp tier for in-browser use only.\n\n## Best practices (especially for LLM-driven agents)\n\n- **Calibrate once, then persist the fitted params — not the `calibrationId`.** `calibrationId` is a short-lived handle into a 30-second in-memory cache; it works for immediate follow-up `/price` and `/greeks` calls but is not durable. For reuse beyond 30s, save the fitted parameters from the calibration response and pass them as `modelParams` on subsequent calls. Either path avoids the 500/day calibration quota. Don't set `resolve.calibration: true` on every repeated call for the same symbol.\n- **Prefer `/v1/data/*` over recomputing.** Greeks history, IV surfaces, snapshot metrics, metrics-batch, scanner rankings, and regime classifications are precomputed or cached where available — typically much faster than recomputing from scratch. Don't loop `/v1/compute/greeks` to reconstruct what `/v1/data/greeks-history/:symbol` already returns.\n- **Use batch endpoints.** `/v1/data/metrics/batch` takes multiple symbols in one call; MultiAsset accepts `modelParams.tickers` for basket pricing. One batch call beats a loop of N single-symbol calls.\n- **Use ticker auto-fill instead of fabricated numerics.** Pass `symbol` + `expiry` and let the API resolve `S`, `sigma`, `r`, `t` from cached market data — the response's `resolved` block shows which source filled each field (`snapshot`, `atmIv-expiry`, `hv-30d`, `fred-DGS3MO`, …). Don't hallucinate market values from training data.\n- **Always inspect `warnings` and `resolved`.** The compute route returns top-level `warnings` plus a `resolved` block whenever ticker auto-fill ran. Agents that ignore these can act on a price computed with a stale spot or a missing-dividend fallback.\n- **Honor `Retry-After` on 429.** Sleep the suggested duration. Retrying instantly in a tight loop wastes tokens and bounces off the same limit.\n- **Use `X-Cache-Status` to guide polling cadence.** Data responses include `X-Cache-Status`; values include `HIT`, `MISS`, `DEDUP`, `NO_REDIS`, and error/fallback statuses. If you see all HITs, you're polling faster than the underlying data updates — back off.\n- **Don't repoll faster than the underlying data updates.** Most `/v1/data/*` endpoints back tables that refresh on a documented daily cron. Repolling every 30s returns the same bytes.\n- **Stream live data over `/v1/ws`, don't poll REST.** Up to 30 msg/sec × 50 symbols × 5 sessions beats any REST polling loop on freshness and rpm budget.\n- **Match model to task.** Black-Scholes and Binomial are sub-100ms and correct for vanilla options. Reserve Heston/SABR/Local Vol/JD/MC for cases where skew, jumps, or path-dependence actually matter.\n- **Scope and secure keys.** Create compute-only, data-only, or streaming-only keys to limit blast radius. Never embed keys in client-side JS, browser extensions, public repos, or LLM tool manifests.","contact":{"name":"Options Analysis Suite","url":"https://optionsanalysissuite.com"},"license":{"name":"Commercial","url":"https://optionsanalysissuite.com/legal/terms"}},"servers":[{"url":"https://data.optionsanalysissuite.com","description":"Production"},{"url":"http://localhost:3003","description":"Local development"}],"tags":[{"name":"Compute","description":"Pricing, Greeks, and analytics endpoints. Multi-model (17 pricing models: 10 standard — BS, Heston, SABR, FFT, VG, JD, Binomial, PDE, Monte Carlo, Local Vol — plus 7 exotic — Barrier, Asian, Lookback, Digital, Compound, Chooser, Multi-Asset). Auto-calibration available for Heston, SABR, VG, JD, and Local Vol against live broker chain data. Exotic models support the optional includeInsight flag for strategy-level comparison metrics."},{"name":"Data","description":"Pre-computed market data: regime detection, IV surfaces, snapshots, metrics, scanner results, market trends. All endpoints read from the Options Analysis Suite data warehouse."},{"name":"Streaming","description":"Real-time WebSocket streaming at `/v1/ws`. Supports quote, greeks, and exposure channels with BYOK broker credentials (TastyTrade, Tradier). See streaming documentation."},{"name":"Health","description":"Unauthenticated health check endpoint for monitoring."}],"paths":{"/health":{"get":{"operationId":"health.check","summary":"Health check","description":"Unauthenticated health probe. Returns current service status and uptime.","tags":["Health"],"security":[],"responses":{"200":{"description":"Service is healthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/v1/compute/price":{"post":{"operationId":"compute.price","summary":"Multi-model option pricing","description":"Price an option using one of 17 supported pricing models. For advanced models, pass model-specific parameters via `modelParams`, or use a `calibrationId` from `/v1/compute/calibrate` to reuse calibrated parameters.\n\n**Required tenor:** every request must specify a time-to-expiry. Provide either `t` (numeric years) **or** `expiry` / `expiration` (YYYY-MM-DD). Missing both returns a `400` validation error.\n\n**Ticker auto-fill:** supply `symbol: \"AAPL\"` (plus `expiry: \"YYYY-MM-DD\"` since tenor is mandatory) to let the API fill `S`, `sigma`, `q`, `r`, and `t` from cached market data. User-supplied numeric fields always win; the response `resolved` block reports the effective value + source (`override`, `snapshot`, `atmIv-expiry`, `hv-30d`, `dividends-ttm`, `fred-DGS3MO`, etc.). For MultiAsset, supply `modelParams.tickers: [\"SPY\",\"QQQ\",...]` to build the basket from 5y monthly correlations. Requires both `compute` and `data` scopes on the API key. Set `resolve.calibration: true` (Heston/SABR/VG/JD/LocalVol only) to additionally run auto-calibration under the existing calibration quota — broker headers (`X-Broker-Type`, `X-Tradier-Key`, …) are required for this mode.\n\n**modelParams by model:**\n\n- **heston:** `v0`, `kappa` / `hestonKappa`, `theta` / `hestonTheta`, `volOfVol` / `xi` / `hestonVolOfVol` (legacy alias: `sigma`), `rho` / `hestonRho`, `integrationPoints` (legacy alias: `hestonOrder`)\n- **sabr:** `sabrAlpha` / `alpha`, `sabrBeta` / `beta`, `sabrRho` / `rho`, `sabrNu` / `nu`, `approximationMethod` (hagan | obloj | paulot, default hagan), `shift`, `expansionOrder`, `useSmallTimeCorrection`, `fixBeta`, `fixedBetaValue`, `atmReference`, `volFloor`, `useArbitrageChecks`\n- **fft:** `processType` (blackScholes | merton | varianceGamma | heston | kou | bates), `N`, `alpha`, `eta`, `integrationMethod` (legacy aliases: `fftGridSize`, `fftAlpha`, `fftEta`, `fftIntegrationMethod`). Process-specific params match the webapp: Merton `mertonLambda`, `mertonMuJ`, `mertonSigmaJ`; Variance Gamma `vgSigma`, `vgNu`, `vgTheta`; Heston `hestonV0`, `hestonKappa`, `hestonTheta`, `hestonXi`, `hestonRho`; Kou `kouLambda`, `kouP`, `kouEta1`, `kouEta2`; Bates `batesV0`, `batesKappa`, `batesTheta`, `batesSigmaV`, `batesRho`, `batesLambda`, `batesMuJ`, `batesSigmaJ`\n- **vg:** `sigma` / `vgSigma`, `nu` / `vgNu`, `theta` / `vgTheta`, optional `method`, `fftPoints`, `alpha`, `eta`, `cacheFFT`, `weighting`\n- **jd:** `modelType` / `jdModel` (kou | merton | bates, default kou). Merton/Kou accept `baseVolatility` as the diffusion sigma override. Kou: `lambda`, `pUp`, `etaUp`, `etaDown`, optional `tailTolerance` / `tailTol`, `maxK`, `forceFFT`, `fftGridSize`. Merton: `lambda`, `muJ`, `sigmaJ`, optional `maxPoisson`. Bates: `v0`, `kappa`, `theta`, `sigmaV` / `volOfVol` / `xi`, `rho`, `lambda`, `muJ`, `sigmaJ`, optional `forceExactCF`, `fftGridSize`\n- **binomial:** `steps`, `enableAmerican` / `isAmerican`, `treeType` (CRR | JR | TIAN | LR), optional Richardson controls `useRichardsonExtrap`, `richardsonMode`, `stepMultiplier`, `extrapOrder`, and discrete-dividend inputs either as `dividends` array or the webapp-style `useDiscreteDividends`, `exDividendDates`, `dividendAmounts`. The public API uses the ex-date discrete-dividend model.\n- **pde:** `forceMethod` / `pdeForceMethod`, `accuracyThreshold` / `pdeAccuracyThreshold`, plus grid controls `spaceSteps`, `timeSteps`, `sMin`, `sMax`, `gridSpacing`, `rannacherSteps`\n- **mc:** `paths` / `mcPaths` / `nPaths`, `steps` / `stepsPerPath` / `timeSteps` / `nSteps`, `seed` / `mcSeed`, `process` / `processType` (`blackscholes` | `jumpdiffusion` | `meanreverting` | `heston` | `localvolcev` | `localvoldupire`; aliases such as `BlackScholes`, `Merton`, `LocalVolatility`, `Dupire`, and `CEV` are normalized), top-level process params or nested `processParams`, `useAntithetic`, `useControlVariate`, `useImportanceSampling`, `useMomentMatching`, `useQMC`, `qmcType`. `rngMethod: SobolTrue` is normalized to Sobol QMC; non-QMC browser RNG labels fall back to the standard server RNG path. Monte Carlo pricing in the API is European-only. Browser-only execution flags such as `useGPU`, `batchSize`, and `parallelThreads` are ignored server-side.\n- **localvol:** PDE-only public surface. Supported params: `impliedVolData` (array or JSON string), `impliedVolDataArray`, `useDupire`, `useAmerican`, `interpolation` (essvi | linear | svi | dupire; cubic is no longer supported), `spotSteps` / `pdeGridSize`, `timeSteps` / `pdeTimeSteps`, `rannacherSteps`, `regularizationParam`, `localVolBeta` / `beta` / `cevBeta`, `cevScale`, `minVol` / `dupireMinVol`, `maxVol` / `dupireMaxVol`, `ticker`\n- **barrier:** `barrierType` (up-out | down-out | up-in | down-in | double-out | double-in), `barrierLevel`, `rebate`, `monitoringType` (continuous | discrete | window), `monitoringFreq`, `upperBarrier`, `lowerBarrier`, `upperRebate`, `lowerRebate`, `windowStart`, `windowEnd`\n- **asian:** `averagingType` (arithmetic | geometric), `strikeType` (fixed | floating), `method` (curran | geometric; `mc`/`montecarlo` requests are normalized to curran server-side), `numObservations`, `observationFreq`, `observationDates`, `pastFixings`, `runningAverage`, `runningSum`, `fixingsElapsed`\n- **lookback:** `lookbackType` (floating | fixed), `currentMax`, `currentMin`, `monitoringType` / `monitoring`, `monitoringFrequency`, `method`\n- **digital:** `type` / `digitalType` — accepts either short form (`cash` | `asset` | `gap`) or long form (`cash-or-nothing` | `asset-or-nothing` | `gap`); both are equivalent server-side. Also `cashAmount`, `gapAmount`, `smoothing` (clamped server-side to a minimum of 1e-4), `method`\n- **compound:** `compoundType` (call-on-call | call-on-put | put-on-call | put-on-put), `underlyingStrike`, `firstExpiry`, `secondExpiry` (defaults to request `t`), `method`, `mcPaths`, `mcSeed`, `useAntithetic`, `useControlVariate`\n- **chooser:** `chooserType` (simple | complex), `choiceTime`, `maturity`, `callStrike`, `putStrike`, `callMaturity`, `putMaturity`, `method`, `mcPaths`, `useAntithetic`, `useControlVariate`\n- **multiasset:** `payoffType` / `type` / `multiAssetType` (basket | spread | max | min), `numAssets`, `correlation`, `corrMatrix` / `correlationMatrix`, `prices[]`, `volatilities[]`, `dividends[]`, `weights[]`, `method`, `mcPaths`, `seed`, `useAntithetic`, `useControlVariate`, `useSobol`. If `prices[]` is omitted, the request spot `S` is used as the first asset price.","tags":["Compute"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceRequest"},"examples":{"bs":{"summary":"Black-Scholes call option","value":{"model":"bs","isCall":true,"S":100,"K":100,"r":0.05,"q":0,"sigma":0.2,"t":1}},"mc":{"summary":"Monte Carlo (100K paths, seeded)","value":{"model":"mc","isCall":true,"S":100,"K":100,"r":0.05,"q":0,"sigma":0.2,"t":1,"modelParams":{"paths":100000,"seed":42,"process":"BlackScholes"}}},"heston":{"summary":"Heston stochastic volatility","value":{"model":"heston","isCall":true,"S":100,"K":100,"r":0.05,"q":0,"sigma":0.2,"t":1,"modelParams":{"v0":0.04,"kappa":2,"theta":0.04,"volOfVol":0.3,"rho":-0.7,"integrationPoints":16}}},"fftHeston":{"summary":"FFT Carr-Madan with Heston process","value":{"model":"fft","isCall":true,"S":100,"K":100,"r":0.05,"q":0,"sigma":0.2,"t":1,"modelParams":{"processType":"heston","N":4096,"alpha":1.5,"eta":0.25,"hestonV0":0.04,"hestonKappa":2,"hestonTheta":0.04,"hestonXi":0.3,"hestonRho":-0.7}}},"fftHighRes":{"summary":"FFT with high-resolution grid (8192 points)","value":{"model":"fft","isCall":true,"S":100,"K":100,"r":0.05,"q":0,"sigma":0.2,"t":1,"modelParams":{"processType":"blackScholes","N":8192,"alpha":1.5,"eta":0.25}}},"jdMerton":{"summary":"Merton jump diffusion","value":{"model":"jd","isCall":true,"S":100,"K":100,"r":0.05,"q":0,"sigma":0.2,"t":1,"modelParams":{"modelType":"merton","lambda":0.1,"muJ":-0.05,"sigmaJ":0.15,"maxPoisson":50}}},"jdKou":{"summary":"Kou double-exponential jump diffusion","value":{"model":"jd","isCall":true,"S":100,"K":100,"r":0.05,"q":0,"sigma":0.2,"t":1,"modelParams":{"modelType":"kou","lambda":0.5,"pUp":0.4,"etaUp":10,"etaDown":10,"tailTolerance":1e-12}}},"binomialAmerican":{"summary":"Binomial tree (American put, 500 steps)","value":{"model":"binomial","isCall":false,"S":100,"K":100,"r":0.05,"q":0.02,"sigma":0.2,"t":1,"modelParams":{"steps":500,"enableAmerican":true}}},"localvol":{"summary":"Local Volatility with calibration ID","value":{"model":"localvol","isCall":true,"S":555,"K":560,"r":0.05,"q":0,"sigma":0.2,"t":0.0833,"calibrationId":"cal_abc123xyz"}},"barrier":{"summary":"Barrier option (up-and-out call)","value":{"model":"barrier","isCall":true,"S":100,"K":100,"r":0.05,"q":0.01,"sigma":0.2,"t":1,"modelParams":{"barrierType":"up-out","barrierLevel":110,"rebate":0,"monitoringType":"continuous"}}},"asian":{"summary":"Asian option (Curran arithmetic average)","value":{"model":"asian","isCall":true,"S":100,"K":100,"r":0.05,"q":0.01,"sigma":0.2,"t":1,"modelParams":{"averagingType":"arithmetic","strikeType":"fixed","method":"curran","numObservations":252}}},"lookback":{"summary":"Lookback option (floating strike)","value":{"model":"lookback","isCall":true,"S":100,"K":100,"r":0.05,"q":0.01,"sigma":0.2,"t":1,"modelParams":{"lookbackType":"floating","currentMin":92,"monitoringType":"discrete","monitoringFrequency":252}}},"digital":{"summary":"Digital cash-or-nothing call (long-form enum)","value":{"model":"digital","isCall":true,"S":100,"K":100,"r":0.05,"q":0.01,"sigma":0.2,"t":1,"modelParams":{"type":"cash-or-nothing","cashAmount":1,"smoothing":0.0005}}},"compound":{"summary":"Compound option (call on call)","value":{"model":"compound","isCall":true,"S":100,"K":10,"r":0.05,"q":0.01,"sigma":0.2,"t":0.25,"modelParams":{"compoundType":"call-on-call","underlyingStrike":100,"firstExpiry":0.25,"secondExpiry":1,"method":"analytical"}}},"chooser":{"summary":"Chooser option (simple chooser)","value":{"model":"chooser","isCall":true,"S":100,"K":100,"r":0.05,"q":0.01,"sigma":0.2,"t":0.25,"modelParams":{"chooserType":"simple","choiceTime":0.25,"maturity":1,"method":"analytical"}}},"multiasset":{"summary":"Multi-asset basket option","value":{"model":"multiasset","isCall":true,"S":100,"K":100,"r":0.05,"q":0.01,"sigma":0.2,"t":1,"modelParams":{"payoffType":"basket","numAssets":2,"prices":[100,95],"volatilities":[0.2,0.25],"dividends":[0.01,0.015],"weights":[0.5,0.5],"correlation":0.3,"method":"analytical","mcPaths":25000,"seed":42}}},"bsFromTicker":{"summary":"Black-Scholes from ticker (auto-fill S/σ/q/r/t)","value":{"model":"bs","isCall":true,"K":180,"symbol":"AAPL","expiry":"2026-06-19"}},"hestonFromTicker":{"summary":"Heston from ticker (auto-calibration, requires broker headers)","value":{"model":"heston","isCall":true,"K":180,"symbol":"AAPL","expiry":"2026-06-19","resolve":{"calibration":true}}},"multiassetFromTickers":{"summary":"Multi-asset basket from tickers (auto-fill prices/vols/divs/corr)","value":{"model":"multiasset","isCall":true,"K":100,"expiry":"2026-06-19","modelParams":{"payoffType":"basket","tickers":["SPY","QQQ","IWM"],"weights":[0.4,0.4,0.2],"method":"analytical"}}}}}}},"responses":{"200":{"description":"Computed option price","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PriceResponse"},"examples":{"bs":{"summary":"Black-Scholes response","value":{"price":10.4506,"model":"black-scholes","inputs":{"isCall":true,"S":100,"K":100,"r":0.05,"q":0,"sigma":0.2,"t":1}}},"mc":{"summary":"Monte Carlo response (with mcStats)","value":{"price":10.4612,"model":"monte-carlo","mcStats":{"stdError":0.0298,"ciLow":10.4028,"ciHigh":10.5196,"nPaths":200000},"inputs":{"isCall":true,"S":100,"K":100,"r":0.05,"q":0,"sigma":0.2,"t":1}}}}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/compute/greeks":{"post":{"operationId":"compute.greeks","summary":"Multi-model Greeks","description":"Compute all 17 Greeks for any of the 17 supported pricing models. Returns price alongside the full Greek vector. Accepts the same `modelParams` as `/v1/compute/price`, including ticker auto-fill (`symbol`, `expiry`, `modelParams.tickers`, `resolve.calibration`). Set `includeInsight: true` to attach the Strategy-page exotic insight card for supported exotic models (Barrier, Asian, Lookback, Digital, Compound, Chooser, MultiAsset).\n\n**Required tenor:** every request must specify a time-to-expiry via either `t` (numeric years) or `expiry` / `expiration` (YYYY-MM-DD). Missing both returns a `400` validation error — the API never invents a tenor.","tags":["Compute"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GreeksRequest"},"examples":{"mc":{"summary":"Monte Carlo (100K paths, seeded)","value":{"model":"mc","isCall":true,"S":100,"K":100,"r":0.05,"q":0,"sigma":0.2,"t":1,"modelParams":{"paths":100000,"seed":42,"process":"BlackScholes"}}},"heston":{"summary":"Heston stochastic volatility","value":{"model":"heston","isCall":true,"S":100,"K":100,"r":0.05,"q":0,"sigma":0.2,"t":1,"modelParams":{"v0":0.04,"kappa":2,"theta":0.04,"volOfVol":0.3,"rho":-0.7,"integrationPoints":16}}},"barrier":{"summary":"Barrier Greeks request","value":{"model":"barrier","isCall":true,"S":100,"K":100,"r":0.05,"q":0.01,"sigma":0.2,"t":1,"modelParams":{"barrierType":"up-out","barrierLevel":110,"rebate":0,"monitoringType":"continuous"}}},"asian":{"summary":"Asian Greeks request","value":{"model":"asian","isCall":true,"S":100,"K":100,"r":0.05,"q":0.01,"sigma":0.2,"t":1,"modelParams":{"averagingType":"arithmetic","strikeType":"fixed","method":"curran","numObservations":252}}},"lookback":{"summary":"Lookback Greeks request","value":{"model":"lookback","isCall":true,"S":100,"K":100,"r":0.05,"q":0.01,"sigma":0.2,"t":1,"modelParams":{"lookbackType":"floating","currentMin":92,"monitoringType":"discrete","monitoringFrequency":252}}},"digital":{"summary":"Digital Greeks request","value":{"model":"digital","isCall":true,"S":100,"K":100,"r":0.05,"q":0.01,"sigma":0.2,"t":1,"modelParams":{"type":"cash","cashAmount":1,"smoothing":0.0005}}},"compound":{"summary":"Compound Greeks request","value":{"model":"compound","isCall":true,"S":100,"K":10,"r":0.05,"q":0.01,"sigma":0.2,"t":0.25,"modelParams":{"compoundType":"call-on-call","underlyingStrike":100,"firstExpiry":0.25,"secondExpiry":1,"method":"analytical"}}},"chooser":{"summary":"Chooser Greeks request","value":{"model":"chooser","isCall":true,"S":100,"K":100,"r":0.05,"q":0.01,"sigma":0.2,"t":0.25,"modelParams":{"chooserType":"simple","choiceTime":0.25,"maturity":1,"method":"analytical"}}},"multiasset":{"summary":"Multi-asset Greeks request","value":{"model":"multiasset","isCall":true,"S":100,"K":100,"r":0.05,"q":0.01,"sigma":0.2,"t":1,"modelParams":{"payoffType":"basket","numAssets":2,"prices":[100,95],"volatilities":[0.2,0.25],"dividends":[0.01,0.015],"weights":[0.5,0.5],"correlation":0.3,"method":"analytical","mcPaths":25000,"seed":42}}},"barrierInsight":{"summary":"Barrier Greeks with insight card","value":{"model":"barrier","isCall":true,"S":100,"K":100,"r":0.05,"q":0.01,"sigma":0.2,"t":1,"includeInsight":true,"modelParams":{"barrierType":"up-out","barrierLevel":110,"rebate":0,"monitoringType":"continuous"}}},"asianInsight":{"summary":"Asian Greeks with insight card","value":{"model":"asian","isCall":true,"S":100,"K":100,"r":0.05,"q":0.01,"sigma":0.2,"t":1,"includeInsight":true,"modelParams":{"averagingType":"arithmetic","strikeType":"fixed","method":"curran","numObservations":252}}},"multiassetInsight":{"summary":"Multi-asset Greeks with insight card","value":{"model":"multiasset","isCall":true,"S":100,"K":100,"r":0.05,"q":0.01,"sigma":0.2,"t":1,"includeInsight":true,"modelParams":{"payoffType":"basket","numAssets":2,"prices":[100,95],"volatilities":[0.2,0.25],"dividends":[0.01,0.015],"weights":[0.5,0.5],"correlation":0.3,"method":"analytical","mcPaths":25000,"seed":42}}},"bsFromTicker":{"summary":"Black-Scholes from ticker (auto-fill S/σ/q/r/t)","value":{"model":"bs","isCall":true,"K":180,"symbol":"AAPL","expiry":"2026-06-19"}},"hestonFromTicker":{"summary":"Heston from ticker (auto-calibration, requires broker headers)","value":{"model":"heston","isCall":true,"K":180,"symbol":"AAPL","expiry":"2026-06-19","resolve":{"calibration":true}}},"multiassetFromTickers":{"summary":"Multi-asset basket from tickers (auto-fill prices/vols/divs/corr)","value":{"model":"multiasset","isCall":true,"K":100,"expiry":"2026-06-19","modelParams":{"payoffType":"basket","tickers":["SPY","QQQ","IWM"],"weights":[0.4,0.4,0.2],"method":"analytical"}}}}}}},"responses":{"200":{"description":"Greeks computed successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GreeksResponse"},"examples":{"mc":{"summary":"Monte Carlo Greeks (50K paths)","value":{"model":"monte-carlo","price":10.4506,"delta":0.6392,"gamma":0.0191,"vega":37.6509,"theta":-6.4365,"rho":53.4268,"inputs":{"isCall":true,"S":100,"K":100,"r":0.05,"q":0,"sigma":0.2,"t":1}}},"barrierInsight":{"summary":"Barrier Greeks with insight card","value":{"model":"barrier","price":0.1179,"delta":-0.0102,"gamma":-0.0006,"vega":0.0028,"theta":-0.0025,"rho":0.0006,"epsilon":-0.0102,"vanna":0.1269,"charm":0.0266,"vomma":0.0562,"veta":0.0012,"speed":0.0006,"zomma":0.0697,"color":-0.0001,"ultima":-1.2682,"dcharmDvol":0.9178,"lambda":-8.6499,"phi":0.0005,"exoticInsight":{"model":"Barrier","title":"Stop-Loss Level Comparison","subtitle":"Where should I set my stop-loss?","accentColor":"#F59E0B","metrics":[{"label":"Vanilla Price","value":"$9.83","rawValue":9.8263},{"label":"Current ($110.00)","value":"$0.12","rawValue":0.1179,"highlight":true},{"label":"Tighter ($105.00)","value":"$0.01","rawValue":0.0088},{"label":"Wider ($115.00)","value":"$0.48","rawValue":0.4758},{"label":"Protection Cost","value":"+$9.71","rawValue":9.7084},{"label":"Cost to Tighten 5%","value":"+$0.11","rawValue":0.1091}],"verdict":"Stop at $110.00 costs $9.71. Tightening 5% adds $0.11","verdictType":"neutral"},"inputs":{"isCall":true,"S":100,"K":100,"r":0.05,"q":0,"sigma":0.2,"t":1}}},"asianInsight":{"summary":"Asian Greeks with DCA insight","value":{"model":"asian","price":5.4172,"delta":0.5523,"gamma":0.0198,"vega":0.3221,"theta":-0.0122,"rho":0.4013,"epsilon":-0.5523,"vanna":0.0078,"charm":-0.0341,"vomma":0.8921,"veta":-0.0273,"speed":-0.0007,"zomma":-0.0411,"color":-0.0005,"ultima":0.3112,"dcharmDvol":-0.0204,"lambda":10.1942,"phi":0.9536,"exoticInsight":{"model":"Asian","title":"DCA Advantage","subtitle":"Should I DCA or lump sum? Should I keep rolling covered calls?","accentColor":"#0EA5E9","metrics":[{"label":"Lump Sum Cost","value":"$8.43","rawValue":8.43},{"label":"DCA / Avg Cost","value":"$5.42","rawValue":5.4172},{"label":"Averaging Benefit","value":"+$3.01","rawValue":3.0128,"highlight":true},{"label":"Cost Reduction","value":"+35.7%","rawValue":35.7}],"verdict":"Averaging saves $3.01 (35.7%) vs lump sum entry.","verdictType":"positive"},"inputs":{"isCall":true,"S":100,"K":100,"r":0.05,"q":0,"sigma":0.2,"t":1}}},"multiassetInsight":{"summary":"Multi-asset Greeks with correlation insight","value":{"model":"multi-asset","price":7.9184,"delta":0.4419,"gamma":0.0162,"vega":0.2874,"theta":-0.0108,"rho":0.3661,"epsilon":-0.4419,"vanna":0.0129,"charm":-0.0314,"vomma":0.7126,"veta":-0.0231,"speed":-0.0008,"zomma":-0.0483,"color":-0.0006,"ultima":0.2844,"dcharmDvol":-0.0218,"lambda":5.5801,"phi":0.808,"exoticInsight":{"model":"MultiAsset","title":"Correlation & Hedge Analysis","subtitle":"How does correlation affect value? What if correlation changes?","accentColor":"#14B8A6","metrics":[{"label":"Current Price","value":"$7.92","rawValue":7.9184},{"label":"Zero-Corr Price","value":"$6.84","rawValue":6.84},{"label":"Correlation Effect","value":"+$1.08","rawValue":1.0784,"highlight":true},{"label":"Correlation","value":"0.30","rawValue":0.3},{"label":"If Corr 0.10","value":"$7.12","rawValue":7.12},{"label":"If Corr 0.50","value":"$8.64","rawValue":8.64}],"verdict":"Correlation increases value by $1.08 (15.8%).","verdictType":"neutral"},"inputs":{"isCall":true,"S":100,"K":100,"r":0.05,"q":0,"sigma":0.2,"t":1}}}}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/compute/exposure":{"post":{"operationId":"compute.exposure","summary":"Greek exposure snapshot (GEX/DEX/VEX/Vanna/Charm/Vomma)","description":"Compute full Greek exposure from a strike list: net gamma/delta/vega/vanna/charm/vomma, call/put walls, gamma flip, abs gamma anchor, dealer positioning regime, and per-strike top contributors. Default response is the full result `{ snapshot, byStrike }`; pass `?detail=snapshot` to receive only the compact `ExposureSnapshot` directly.","tags":["Compute"],"parameters":[{"name":"detail","in":"query","required":false,"schema":{"type":"string","enum":["snapshot"]},"description":"Omit (default) for the full `{ snapshot, byStrike }` result; pass `snapshot` to receive only the compact ExposureSnapshot."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExposureRequest"},"examples":{"example":{"summary":"GEX/DEX exposure snapshot","value":{"spotPrice":655.89,"riskFreeRate":0.05,"dividendYield":0,"wallMaxDte":30,"strikes":[{"strike_cents":65000,"stk_px_cents":65589,"c_oi":12500,"p_oi":8200,"gamma":0.012,"delta":0.52,"vega":41.2,"smooth_smv_vol":0.18,"yte":0.0274},{"strike_cents":66000,"stk_px_cents":65589,"c_oi":15800,"p_oi":11200,"gamma":0.014,"delta":0.42,"vega":45.8,"smooth_smv_vol":0.185,"yte":0.0274}]}}}}}},"responses":{"200":{"description":"Exposure result. By default an `ExposureFullResult` ({ snapshot, byStrike }); when `?detail=snapshot` is passed, an `ExposureSnapshot` directly.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExposureResponse"},"examples":{"example":{"summary":"Default response: full result ({ snapshot, byStrike }). Pass ?detail=snapshot to receive only the inner snapshot directly.","value":{"snapshot":{"spotPrice":655.89,"netGamma":12500000,"netDelta":-8200000,"netVega":450000,"netVanna":125000,"netCharm":-45000,"netVomma":78000,"callWall":660,"putWall":650,"gammaFlip":655.5,"absGamma":660,"gammaConcentration":0.42,"regime":"positive","topStrikes":[{"strike":660,"callGamma":5200000,"putGamma":-200000,"netGamma":5000000,"callDelta":-3100000,"putDelta":1000000,"netDelta":-2100000,"callVega":220000,"putVega":90000,"netVega":310000,"callVanna":40000,"putVanna":-8000,"netVanna":32000,"callCharm":-12000,"putCharm":2000,"netCharm":-10000,"callVomma":18000,"putVomma":-3000,"netVomma":15000}]},"byStrike":[{"strike":655,"callGamma":3800000,"putGamma":-150000,"netGamma":3650000,"callDelta":-2400000,"putDelta":900000,"netDelta":-1500000,"callVega":180000,"putVega":70000,"netVega":250000,"callVanna":30000,"putVanna":-6000,"netVanna":24000,"callCharm":-10000,"putCharm":1500,"netCharm":-8500,"callVomma":14000,"putVomma":-2500,"netVomma":11500}]}}}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/compute/scenario":{"post":{"operationId":"compute.scenario","summary":"Spot × volatility price matrix","description":"Generate a 2D scenario matrix of option prices across spot and volatility perturbations. Useful for risk scenario analysis and heat maps.","tags":["Compute"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScenarioRequest"},"examples":{"example":{"summary":"Spot × volatility matrix","value":{"isCall":true,"S":100,"K":100,"r":0.05,"q":0,"sigma":0.2,"t":0.25,"spotChanges":[-0.1,-0.05,0,0.05,0.1],"volChanges":[-0.1,-0.05,0,0.05,0.1]}}}}}},"responses":{"200":{"description":"Spot × volatility matrix","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScenarioResponse"},"examples":{"example":{"summary":"Scenario matrix with structured cells","value":{"spotChanges":[-0.05,0],"volChanges":[-0.1,0],"matrix":[[{"spotChange":-0.05,"volChange":-0.1,"spot":95,"volatility":0.18,"price":4.95,"pnl":-5.5,"pnlPercent":-52.63},{"spotChange":-0.05,"volChange":0,"spot":95,"volatility":0.2,"price":5.35,"pnl":-5.1,"pnlPercent":-48.8}],[{"spotChange":0,"volChange":-0.1,"spot":100,"volatility":0.18,"price":10.1,"pnl":-0.35,"pnlPercent":-3.35},{"spotChange":0,"volChange":0,"spot":100,"volatility":0.2,"price":10.45,"pnl":0,"pnlPercent":0}]]}}}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/compute/sensitivity":{"post":{"operationId":"compute.sensitivity","summary":"Greeks curves vs spot/time/volatility","description":"Compute Greeks across a single axis (spot, time, or volatility). Returns arrays of {x, price, delta, gamma, vega, theta, rho} points suitable for charting.","tags":["Compute"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SensitivityRequest"},"examples":{"spot":{"summary":"Greeks vs spot price","value":{"isCall":true,"S":100,"K":100,"r":0.05,"q":0,"sigma":0.2,"t":0.25,"axis":"spot","points":50,"spotMin":80,"spotMax":120}},"volatility":{"summary":"Greeks vs volatility","value":{"isCall":true,"S":100,"K":100,"r":0.05,"q":0,"sigma":0.2,"t":0.25,"axis":"volatility","points":50,"volMin":0.1,"volMax":0.5}}}}}},"responses":{"200":{"description":"Sensitivity curve","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SensitivityResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/compute/max-pain":{"post":{"operationId":"compute.maxPain","summary":"Max pain calculation","description":"Compute the max pain strike for an options chain — the strike at which the total outstanding option value (calls + puts) is minimized. Returns the max pain strike plus the full pain distribution across all strikes.","tags":["Compute"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MaxPainRequest"},"examples":{"example":{"summary":"Max pain calculation","value":{"strikes":[{"strike":90,"callOI":1200,"putOI":3500},{"strike":95,"callOI":2800,"putOI":4100},{"strike":100,"callOI":8500,"putOI":5200},{"strike":105,"callOI":4200,"putOI":2100},{"strike":110,"callOI":1800,"putOI":900}]}}}}}},"responses":{"200":{"description":"Max pain result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MaxPainResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/compute/expected-move":{"post":{"operationId":"compute.expectedMove","summary":"Expected move (ATM straddle + 85% rule)","description":"Estimate the expected move of the underlying using the ATM straddle method with the industry-standard 85% adjustment factor. Also returns an IV-based approximation for comparison.\n\n**Field naming:** accepts either `atmIV` (uppercase V, canonical) **or** `atmIv` (lowercase v) for the ATM implied volatility input. `atmIv` matches the casing returned by `/v1/data/metrics/{symbol}` and `/v1/data/snapshot/{symbol}`, so you can pipe those outputs straight in. Both fields are equivalent; if both are supplied, `atmIV` wins.\n\n**Tip:** the `/v1/data/metrics/{symbol}` response already includes `expectedMovePct` precomputed daily — reach for this endpoint only when you need a custom `atmIV` / `daysToExpiry` / `strikePrice` combination.","tags":["Compute"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpectedMoveRequest"},"examples":{"example":{"summary":"Expected move (straddle method with 85% adjustment)","value":{"spotPrice":100,"strikePrice":100,"riskFreeRate":0.05,"dividendYield":0,"atmIV":0.2,"daysToExpiry":30}}}}}},"responses":{"200":{"description":"Expected move result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpectedMoveResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/compute/probability":{"post":{"operationId":"compute.probability","summary":"Risk-neutral + lognormal probability distributions","description":"Compute the implied probability distribution of the underlying at expiration. Returns BOTH the risk-neutral distribution (eSSVI + Breeden-Litzenberger with finite-difference fallback) AND a lognormal baseline, plus statistics (implied move, range bounds, fair value). Supports two modes:\n\n- **simple**: Pre-computed strikes + IVs (no broker needed)\n- **full**: BYOK broker credentials; API fetches live chain across multiple expirations and calibrates eSSVI\n\n### Required headers for `mode: \"full\"`\n\n- **Tradier** (1 credential header) — uses a static Production Access Token:\n  - `X-Broker-Type: tradier`\n  - `X-Tradier-Key: <your Tradier production access token>`\n- **Tastytrade** (2 credential headers) — uses OAuth 2.0 refresh-token flow. The server posts `{grant_type: \"refresh_token\", refresh_token, client_secret}` to Tastytrade's token endpoint to mint a short-lived access token, which is reused until near expiry. Both values must come from the **same Tastytrade OAuth app**:\n  - `X-Broker-Type: tastytrade`\n  - `X-Tastytrade-Refresh-Token: <OAuth refresh token from your Tastytrade OAuth app>`\n  - `X-Tastytrade-Client-Secret: <OAuth client secret from the SAME Tastytrade OAuth app>`\n\n`mode: \"simple\"` requires no headers. Public.com is not supported on the API tier.\n\nCredential sources: Tradier → https://docs.tradier.com/docs/getting-started · Tastytrade → https://developer.tastytrade.com/oauth/","tags":["Compute"],"parameters":[{"name":"X-Broker-Type","in":"header","required":false,"schema":{"type":"string","enum":["tradier","tastytrade"]},"description":"Required for `mode: full`. Public.com is not supported on the API tier (their Individual API program restricts third-party platforms)."},{"name":"X-Tradier-Key","in":"header","required":false,"schema":{"type":"string"},"description":"Required for `mode: full` with `X-Broker-Type: tradier`. Your Tradier production access token (https://docs.tradier.com/docs/getting-started)."},{"name":"X-Tastytrade-Refresh-Token","in":"header","required":false,"schema":{"type":"string"},"description":"Required for `mode: full` with `X-Broker-Type: tastytrade` (alongside `X-Tastytrade-Client-Secret`). OAuth refresh token from your Tastytrade OAuth app (https://developer.tastytrade.com/oauth/)."},{"name":"X-Tastytrade-Client-Secret","in":"header","required":false,"schema":{"type":"string"},"description":"Required for `mode: full` with `X-Broker-Type: tastytrade` (alongside `X-Tastytrade-Refresh-Token`). OAuth client secret for your Tastytrade OAuth app."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProbabilityRequest"},"examples":{"simple":{"summary":"Simple mode — pre-computed strikes + IVs","value":{"mode":"simple","spotPrice":100,"strikes":[85,90,95,100,105,110,115],"ivs":[0.28,0.25,0.22,0.2,0.22,0.25,0.28],"riskFreeRate":0.05,"dividendYield":0,"timeToExpiry":0.25}},"full":{"summary":"Full mode — fetches live chain from broker","description":"Requires broker credentials via headers (X-Broker-Type, X-Tastytrade-Refresh-Token, etc.)","value":{"mode":"full","symbol":"SPY","riskFreeRate":0.05,"dividendYield":0}}}}}},"responses":{"200":{"description":"Both risk-neutral and lognormal distributions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProbabilityResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}}}}},"/v1/compute/calibrate":{"post":{"operationId":"compute.calibrate","summary":"Auto-calibrate model parameters from live chain data","description":"Fetches the live options chain from the specified broker (BYOK credentials via headers) and calibrates model parameters. Returns fitted parameters + calibration ID for reuse in `/price` and `/greeks` via the `calibrationId` field. Supports Heston, SABR, VG, JD, and Local Volatility (eSSVI multi-expiration surface).\n\n### Required headers by broker\n\n- **Tradier** (1 credential header) — uses a static Production Access Token:\n  - `X-Broker-Type: tradier`\n  - `X-Tradier-Key: <your Tradier production access token>`\n- **Tastytrade** (2 credential headers) — uses OAuth 2.0 refresh-token flow. The server posts `{grant_type: \"refresh_token\", refresh_token, client_secret}` to `https://api.tastyworks.com/oauth/token` to mint a short-lived access token, which is reused until near expiry; separately, calibration results themselves are cached for 30 seconds. Both credential values must come from the **same Tastytrade OAuth app** — the `client_secret` identifies which app issued the refresh token, so dropping either header fails the OAuth exchange:\n  - `X-Broker-Type: tastytrade`\n  - `X-Tastytrade-Refresh-Token: <OAuth refresh token from your Tastytrade OAuth app>`\n  - `X-Tastytrade-Client-Secret: <OAuth client secret from the SAME Tastytrade OAuth app>`\n\nPublic.com is not supported on the API tier (their Individual API program restricts third-party platforms). Web-app Pro users can still use Public directly in the browser.\n\n**Quotas:** Calibrations are hard-capped at **500 per day** per user (in addition to the 120/min compute rate limit). Over-quota returns `429 Too Many Requests` with a `Retry-After` header and a `CalibrationQuotaError` body. The quota window resets at midnight UTC. Cached calibration responses (30-second TTL per `credentials.type + symbol + model + expiration + modelParams` key) still count against the quota.","tags":["Compute"],"parameters":[{"name":"X-Broker-Type","in":"header","required":true,"schema":{"type":"string","enum":["tradier","tastytrade"]},"description":"Which broker to fetch chain data from. Public.com is not supported on the API tier."},{"name":"X-Tradier-Key","in":"header","required":false,"schema":{"type":"string"},"description":"Required when `X-Broker-Type: tradier`. Your Tradier production access token (https://docs.tradier.com/docs/getting-started)."},{"name":"X-Tastytrade-Refresh-Token","in":"header","required":false,"schema":{"type":"string"},"description":"Required when `X-Broker-Type: tastytrade` (alongside `X-Tastytrade-Client-Secret`). OAuth refresh token issued by your Tastytrade OAuth app. See https://developer.tastytrade.com/oauth/ for the grant flow."},{"name":"X-Tastytrade-Client-Secret","in":"header","required":false,"schema":{"type":"string"},"description":"Required when `X-Broker-Type: tastytrade` (alongside `X-Tastytrade-Refresh-Token`). OAuth client secret for your Tastytrade OAuth app. Used with the refresh token to mint a short-lived access token per calibration."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalibrateRequest"},"examples":{"heston":{"summary":"Heston calibration on live SPY chain","value":{"model":"heston","symbol":"SPY"}},"hestonPrecise":{"summary":"Heston calibration (precise mode)","value":{"model":"heston","symbol":"SPY","modelParams":{"accuracyMode":"precise"}}},"jdMerton":{"summary":"Merton jump diffusion calibration","value":{"model":"jd","symbol":"SPY","modelParams":{"modelType":"merton"}}},"jdBates":{"summary":"Bates (Heston + jumps) calibration","value":{"model":"jd","symbol":"SPY","modelParams":{"modelType":"bates"}}},"sabrFreeBeta":{"summary":"SABR calibration with free beta","value":{"model":"sabr","symbol":"SPY","modelParams":{"fixBeta":false}}},"localvol":{"summary":"Local Vol (eSSVI) multi-expiration calibration","value":{"model":"localvol","symbol":"SPY"}}}}}},"responses":{"200":{"description":"Calibrated parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalibrateResponse"},"examples":{"heston":{"summary":"Heston calibration result","value":{"model":"heston","symbol":"SPY","expiration":"2026-04-08","params":{"v0":0.008,"kappa":3.9998,"theta":0.016,"sigma":0.2978,"rho":0.071},"fitError":{"ivRmse":0.0537,"nOptions":80},"calibrationTimeMs":6448,"calibrationId":"cal_abc123xyz","provider":"tastytrade"}}}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit OR calibration quota exceeded. Inspect the response body: if it has a `code: \"CALIBRATION_QUOTA_EXCEEDED\"` field, the user hit the daily calibration cap (500/day, resets midnight UTC). Otherwise it is a standard per-minute rate limit.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/RateLimitError"},{"$ref":"#/components/schemas/CalibrationQuotaError"}]}}},"headers":{"Retry-After":{"description":"Seconds until the client can retry (rate limit window or quota window reset)","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/regime/current":{"get":{"operationId":"data.regime.current","summary":"Current market regime","description":"Returns both daily and intraday regime classifications for major indices.","tags":["Data"],"responses":{"200":{"description":"Current regime data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegimeResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/regime/{symbol}":{"get":{"operationId":"data.regime.bySymbol","summary":"Regime history for a symbol","description":"Historical regime classifications for the given symbol.","tags":["Data"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"},"description":"Ticker symbol (e.g. \"SPY\")"},{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":30}}],"responses":{"200":{"description":"Regime history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/regime/fits/{symbol}":{"get":{"operationId":"data.regime.fits","summary":"Model fit history (8-model calibration)","description":"Historical 8-model calibration fits (BS, Heston, SABR, VG, Merton, Kou, Bates, eSSVI) for the symbol.","tags":["Data"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":30}}],"responses":{"200":{"description":"Model fit history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/regime/intraday/{symbol}":{"get":{"operationId":"data.regime.intraday","summary":"Intraday regime snapshots","description":"Intraday regime detection snapshots for the symbol.","tags":["Data"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"minimum":1,"maximum":200}}],"responses":{"200":{"description":"Intraday regime snapshots","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/snapshot/market":{"get":{"operationId":"data.snapshot.market","summary":"Daily market snapshot","description":"Aggregated market snapshot: most active, unusual volume, highest IV.","tags":["Data"],"responses":{"200":{"description":"Market snapshot","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"404":{"description":"No market snapshot found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/snapshot/{symbol}":{"get":{"operationId":"data.snapshot.bySymbol","summary":"Daily snapshot for a symbol","description":"Latest daily snapshot: spot, max pain, net GEX/DEX, ATM IV, and 20+ derived metrics.","tags":["Data"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Symbol snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SnapshotResponse"},"examples":{"example":{"summary":"EOD snapshot for SPY with full curve payloads","value":{"ticker":"SPY","date":"2026-04-25","spotPrice":655.89,"maxPain":650,"netGex":12500000,"netDex":-8200000,"atmIv":0.142,"atmIv7d":0.158,"atmIv30d":0.146,"atmIv90d":0.151,"putCallRatio":0.91,"ivSkew25d":-0.034,"dividendYield":0.0125,"totalVolume":4200000,"totalOi":18500000,"callVolume":2100000,"putVolume":2100000,"callOi":9800000,"putOi":8700000,"expectedMovePct":0.018,"ivRank":22.4,"ivPercentile":31.7,"hv20d":0.121,"hv60d":0.138,"maxPainCurve":[{"strike":640,"callPain":5200000000,"putPain":4600000000,"totalPain":9800000000},{"strike":645,"callPain":4400000000,"putPain":3800000000,"totalPain":8200000000},{"strike":650,"callPain":4000000000,"putPain":3600000000,"totalPain":7600000000},{"strike":655,"callPain":4300000000,"putPain":3800000000,"totalPain":8100000000},{"strike":660,"callPain":4900000000,"putPain":4200000000,"totalPain":9100000000}],"gexByStrike":[{"strike":650,"gex":4200000},{"strike":655,"gex":5800000},{"strike":660,"gex":5200000}],"dexByStrike":[{"strike":650,"dex":-2800000},{"strike":655,"dex":-3100000},{"strike":660,"dex":-2300000}],"vannaByStrike":[{"strike":655,"vanna":32000},{"strike":660,"vanna":28000}],"charmByStrike":[{"strike":655,"charm":-8500},{"strike":660,"charm":-10000}],"vommaByStrike":[{"strike":655,"vomma":11500},{"strike":660,"vomma":15000}],"volSkew":{"strikes":[600,625,650,675,700],"iv":[0.182,0.158,0.142,0.139,0.144]},"probabilityData":{"analyticsExpiry":"2026-05-23","stdDev":0.124},"chainData":[{"expiration":"2026-05-23","strike":655,"callIv":0.143,"putIv":0.146}],"analyticsExpiry":"2026-05-23","chainExpiry":"2026-05-23"}}}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"404":{"description":"No snapshot found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/metrics/batch":{"get":{"operationId":"data.metrics.batch","summary":"Batch metrics for multiple symbols","description":"Fetch latest metrics (ATM IV, IV rank, etc.) for multiple symbols in one request.","tags":["Data"],"parameters":[{"name":"symbols","in":"query","required":true,"schema":{"type":"string"},"description":"Comma-separated list of symbols (e.g. \"SPY,QQQ,IWM\")"}],"responses":{"200":{"description":"Batch metrics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetricsBatchResponse"},"examples":{"example":{"summary":"Batch metrics for SPY + QQQ","value":{"count":2,"data":[{"symbol":"SPY","date":"2026-04-25","atmIv":0.142,"ivRank":22.4,"ivPercentile":31.7,"hv20d":0.121,"hv60d":0.138,"putCallRatio":0.91,"totalVolume":4200000,"totalOi":18500000,"callVolume":2100000,"putVolume":2100000,"callOi":9800000,"putOi":8700000,"maxPain":650,"expectedMovePct":0.018},{"symbol":"QQQ","date":"2026-04-25","atmIv":0.179,"ivRank":38.2,"ivPercentile":44.5,"hv20d":0.156,"hv60d":0.171,"putCallRatio":0.84,"totalVolume":3100000,"totalOi":12400000,"callVolume":1700000,"putVolume":1400000,"callOi":6600000,"putOi":5800000,"maxPain":470,"expectedMovePct":0.022}]}}}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/metrics/{symbol}":{"get":{"operationId":"data.metrics.bySymbol","summary":"Latest metrics for a symbol","description":"Fetch latest metrics row for a single symbol (ATM IV, IV rank/percentile, term structure, skew).","tags":["Data"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Metrics row","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetricsResponse"},"examples":{"example":{"summary":"Per-symbol EOD metrics row","value":{"symbol":"SPY","date":"2026-04-25","atmIv":0.142,"ivRank":22.4,"ivPercentile":31.7,"hv20d":0.121,"hv60d":0.138,"putCallRatio":0.91,"totalVolume":4200000,"totalOi":18500000,"callVolume":2100000,"putVolume":2100000,"callOi":9800000,"putOi":8700000,"maxPain":650,"expectedMovePct":0.018}}}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"404":{"description":"No metrics found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/market-trends":{"get":{"operationId":"data.marketTrends","summary":"Market trends ranked by metric","description":"Top N symbols ranked by a given metric (IV rank, volume, put/call ratio, etc.)","tags":["Data"],"parameters":[{"name":"metric","in":"query","required":false,"schema":{"type":"string","enum":["iv_rank","iv_percentile","total_volume","total_oi","put_call_ratio","atm_iv"],"default":"iv_rank"}},{"name":"direction","in":"query","required":false,"schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"Ranked trends","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"404":{"description":"No market trend data found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/iv-surface/{symbol}":{"get":{"operationId":"data.ivSurface","summary":"IV surface snapshot","description":"Full implied volatility surface for the symbol: strike × expiration grid with call/put IVs and smoothed values.","tags":["Data"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"}},{"name":"date","in":"query","required":false,"schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"IV surface data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IVSurfaceResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"404":{"description":"No IV surface data found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/greeks-history/{symbol}":{"get":{"operationId":"data.greeksHistory","summary":"Historical Greeks time series","description":"Historical portfolio-level Greeks (delta, gamma, theta, vega) for the symbol.","tags":["Data"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":30}}],"responses":{"200":{"description":"Greeks history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"404":{"description":"Ticker not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/scanner/ranked":{"get":{"operationId":"data.scanner.ranked","summary":"Scanner ranked results","description":"Scanner output ranked by category (volatility, flow, unusual activity, etc.)","tags":["Data"],"parameters":[{"name":"category","in":"query","required":false,"schema":{"type":"string"}},{"name":"index","in":"query","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":20,"minimum":1,"maximum":100}}],"responses":{"200":{"description":"Scanner results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"404":{"description":"No ranked scanner data found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/fail-to-deliver/{symbol}":{"get":{"operationId":"data.failToDeliver","summary":"SEC Failure-to-Deliver (FTD) history","description":"SEC-reported failure-to-deliver settlement records for a symbol, enriched with threshold-list membership when available. Sourced from `sec_ftd` and `sec_threshold_list` tables.\n\n**Aliases** (equivalent paths — same handler, same payload): `/v1/data/failure-to-deliver/{symbol}`, `/v1/data/market-structure/ftd/{symbol}`.","tags":["Data"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"minimum":1,"maximum":500}}],"responses":{"200":{"description":"FTD records","content":{"application/json":{"schema":{"type":"object","properties":{"symbol":{"type":"string"},"count":{"type":"integer"},"thresholdDates":{"type":"array","items":{"type":"string","format":"date"}},"data":{"type":"array","items":{"type":"object","additionalProperties":true,"properties":{"onThresholdList":{"type":"boolean"}}}}},"required":["symbol","count","data","thresholdDates"]}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/short-volume/{symbol}":{"get":{"operationId":"data.shortVolume","summary":"FINRA short volume history","description":"Daily FINRA short-volume records. Sourced from `finra_short_volume` table.","tags":["Data"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"minimum":1,"maximum":500}}],"responses":{"200":{"description":"Short volume history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/market-structure/ats/{symbol}":{"get":{"operationId":"data.marketStructure.ats","summary":"FINRA ATS (Alternative Trading System) weekly data","description":"Weekly FINRA ATS trading volume per symbol. Sourced from `finra_ats_weekly` table.","tags":["Data"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":52,"minimum":1,"maximum":200}}],"responses":{"200":{"description":"ATS weekly records","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/market-structure/otc/{symbol}":{"get":{"operationId":"data.marketStructure.otc","summary":"FINRA OTC (Over-The-Counter) weekly data","description":"Weekly FINRA OTC trading volume per symbol. Sourced from `finra_otc_weekly` table.","tags":["Data"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":52,"minimum":1,"maximum":200}}],"responses":{"200":{"description":"OTC weekly records","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/market-structure/ats/{symbol}/firms":{"get":{"operationId":"data.marketStructure.atsFirms","summary":"FINRA ATS firm-level breakdown","description":"Per-venue ATS dark pool breakdown showing which venues (UBSS, CDRG, ICBX, etc.) routed volume for a symbol. Optionally filter to a single week. Rows include MPID, participant name, shares, and trades. Sourced from `finra_ats_weekly_firm` table.","tags":["Data"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"}},{"name":"week_ending","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"Filter to a specific week (YYYY-MM-DD)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"minimum":1,"maximum":500}}],"responses":{"200":{"description":"ATS firm-level records","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/market-structure/otc/{symbol}/firms":{"get":{"operationId":"data.marketStructure.otcFirms","summary":"FINRA OTC firm-level breakdown","description":"Per-dealer OTC breakdown showing which market makers (Citadel, Virtu, etc.) handled volume for a symbol. Optionally filter to a single week. Rows include MPID, participant name, shares, and trades. Sourced from `finra_otc_weekly_firm` table.","tags":["Data"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"}},{"name":"week_ending","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"Filter to a specific week (YYYY-MM-DD)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"minimum":1,"maximum":500}}],"responses":{"200":{"description":"OTC firm-level records","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/market-structure/blocks":{"get":{"operationId":"data.marketStructure.blocks","summary":"FINRA monthly dealer block-trade summary","description":"Market-wide monthly dealer block-trade summary from FINRA. Not per-symbol — each row is a dealer (`mpid`) × month × block-size bucket (`summary_type_code`). Returns shares, trades, block counts, average block size, and ATS/block percentages. Defaults to the latest month when `month` is omitted. Filter by `mpid` or `summary_type`.\n\n**Row shape note:** monthly totals (`total_trades`, `total_shares`, `avg_trade_size`, `ats_trade_pct`, `ats_share_pct`) repeat across the six size-bucket rows for the same dealer-month — that mirrors how FINRA ships the data. Bucket-specific fields (`block_count`, `block_shares`, `avg_block_size`, `block_trade_pct`, `block_share_pct`) vary per row. The `ats_otc` field is descriptive (today always `ATS`), not filterable, since it is not part of the table primary key. Sourced from `finra_blocks_monthly`.","tags":["Data"],"parameters":[{"name":"month","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"Month start (YYYY-MM-01). Defaults to latest available."},{"name":"mpid","in":"query","required":false,"schema":{"type":"string"},"description":"Filter to a single dealer (e.g. INCR, CRD149823)."},{"name":"summary_type","in":"query","required":false,"schema":{"type":"string","enum":["2K","10K","100K","200K","2K-100K","10K-200K"]},"description":"Block-size bucket: 2K = 2K–10K shares; 10K = 10K+ shares; 100K = $100K–<$200K; 200K = $200K+; combined buckets are the AND-intersection."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"minimum":1,"maximum":1000}}],"responses":{"200":{"description":"Dealer block-summary rows sorted by block_shares desc","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/market-structure/blocks/dealer/{mpid}":{"get":{"operationId":"data.marketStructure.blocksByDealer","summary":"Dealer block-summary history","description":"Monthly block-summary history for a single dealer (MPID) across block-size buckets. Default window is 12 months anchored to the dealer's most recent observation. Filter by `summary_type` to focus on one size bucket.\n\n**Row shape note:** see `/v1/data/market-structure/blocks` — monthly totals repeat across bucket rows within each month, while `block_count` / `block_shares` / `avg_block_size` / `block_trade_pct` / `block_share_pct` vary per bucket. Sourced from `finra_blocks_monthly`.","tags":["Data"],"parameters":[{"name":"mpid","in":"path","required":true,"schema":{"type":"string"}},{"name":"summary_type","in":"query","required":false,"schema":{"type":"string","enum":["2K","10K","100K","200K","2K-100K","10K-200K"]}},{"name":"months","in":"query","required":false,"schema":{"type":"integer","default":12,"minimum":1,"maximum":120},"description":"History window in calendar months, anchored to the dealer's most recent month."}],"responses":{"200":{"description":"Dealer block-summary history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/threshold-history/{symbol}":{"get":{"operationId":"data.thresholdHistory","summary":"SEC Threshold Securities list history","description":"Check whether a symbol appeared on the SEC threshold list for a specific set of dates. Sourced from `sec_threshold_list` table.","tags":["Data"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"}},{"name":"dates","in":"query","required":true,"schema":{"type":"string"},"description":"Comma-separated ISO dates, e.g. `2024-01-01,2024-01-02`."}],"responses":{"200":{"description":"Threshold history check result","content":{"application/json":{"schema":{"type":"object","properties":{"symbol":{"type":"string"},"thresholdDates":{"type":"array","items":{"type":"string","format":"date"}},"totalDatesChecked":{"type":"integer"},"datesOnThreshold":{"type":"integer"}},"required":["symbol","thresholdDates","totalDatesChecked","datesOnThreshold"]}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/economic-calendar":{"get":{"operationId":"data.economicCalendar","summary":"Economic events calendar","description":"Macro events, releases, and announcements. Maximum 90-day range. Sourced from `economic_calendar` table.","tags":["Data"],"parameters":[{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date"}},{"name":"country","in":"query","required":false,"schema":{"type":"string","description":"ISO country code (e.g. US, EU, UK)"}}],"responses":{"200":{"description":"Economic calendar events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/ipo-calendar":{"get":{"operationId":"data.ipoCalendar","summary":"IPO calendar","description":"Upcoming and recent initial public offerings. Sourced from `ipo_calendar` table.","tags":["Data"],"parameters":[{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"IPO events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/dividend-calendar":{"get":{"operationId":"data.dividendCalendar","summary":"Dividend calendar","description":"Upcoming and recent ex-dividend and payment dates. Sourced from `dividend_calendar` table.","tags":["Data"],"parameters":[{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Dividend events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/split-calendar":{"get":{"operationId":"data.splitCalendar","summary":"Stock split calendar","description":"Upcoming and recent stock splits. Sourced from `split_calendar` table.","tags":["Data"],"parameters":[{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Split events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/dividends/{symbol}":{"get":{"operationId":"data.dividends","summary":"Per-symbol dividend history","description":"Historical dividend payments for a symbol. Sourced from `stock_dividends` table.","tags":["Data"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Dividend history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/stock-splits/{symbol}":{"get":{"operationId":"data.stockSplits","summary":"Per-symbol stock split history","description":"Historical stock splits for a symbol. Sourced from `stock_splits` table.","tags":["Data"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Stock split history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/company-profile/{symbol}":{"get":{"operationId":"data.companyProfile","summary":"Company profile","description":"Company overview, sector, industry, description. Sourced from `company_profiles` table.","tags":["Data"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Company profile","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"404":{"description":"No company profile available for this symbol","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/fundamentals/{symbol}":{"get":{"operationId":"data.fundamentals","summary":"Company fundamentals","description":"Financial statements (income statement, balance sheet, cash flow) and key ratios. Sourced from `financial_statements` table.","tags":["Data"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Fundamentals data","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"404":{"description":"No fundamentals data for this symbol","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/earnings/{symbol}":{"get":{"operationId":"data.earnings","summary":"Earnings history (+ optional options analytics)","description":"Quarterly earnings history, EPS and revenue surprises, and next earnings date. Sourced from `earnings_data` table.\n\n**Options analytics (`?includeOptionsAnalytics=true`)** — attach an `optionsAnalytics` block containing realized vs implied post-earnings moves, IV crush, and aggregate stats across the last 8 quarters. Derived by joining the earnings history with `stock_prices` (close-to-close realized move) and `scan_tickers` (historical ATM IV, tenor preference 7D → 30D → generic). Adds ~2 extra database reads; the base response is unchanged when the flag is false or absent.\n\n**Windowing:** BMO (before-open) reports use prior-day close → report-day close. AMC or unknown-timing reports use report-day close → next-trading-day close. The response `quarters[].time` echoes the source `time` tag when available (currently often `null`, which falls through to AMC-style windowing).\n\n**`impliedMovePct`** is a 1-trading-day approximation: `preEventAtmIv × √(1/252) × 100`. Event vol concentrates in the event-week expiration, so this often understates what options actually priced in; use it as a lower bound. `realizedOverImplied > 1` means the stock moved more than options priced in. `ivCrushPct` is `(preIv − postIv) / preIv × 100`.","tags":["Data"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"}},{"name":"includeOptionsAnalytics","in":"query","required":false,"schema":{"type":"boolean","default":false},"description":"When `true`, attach `optionsAnalytics` with per-quarter realized/implied move, IV crush, and aggregate stats (last 8 reported quarters)."}],"responses":{"200":{"description":"Earnings data","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"properties":{"symbol":{"type":"string"},"earnings_history":{"type":"array","items":{"type":"object","additionalProperties":true}},"fetched_at":{"type":"string","format":"date-time"},"optionsAnalytics":{"type":"object","description":"Only present when `?includeOptionsAnalytics=true`.","properties":{"summary":{"type":"object","properties":{"quartersAnalyzed":{"type":"integer","minimum":0,"maximum":8},"avgAbsMovePct":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Average absolute close-to-close move, percent."},"maxAbsMovePct":{"anyOf":[{"type":"number"},{"type":"null"}]},"upPct":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Share of quarters with non-negative close-to-close move."},"upQuartersOfTotal":{"anyOf":[{"type":"string"},{"type":"null"}],"example":"5/8"}}},"quarters":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","format":"date"},"time":{"anyOf":[{"type":"string","enum":["bmo","amc"]},{"type":"null"}],"description":"Report timing if the source tagged it; unknown/unrecognized values are normalized to null (falls through to AMC-style windowing)."},"preDate":{"type":"string","format":"date"},"postDate":{"type":"string","format":"date"},"preClose":{"type":"number"},"postClose":{"type":"number"},"realizedMovePct":{"type":"number","description":"Signed close-to-close move, percent."},"absRealizedPct":{"type":"number"},"preEventAtmIv":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Decimal IV at pre-event close (e.g. 0.42 for 42%)."},"postEventAtmIv":{"anyOf":[{"type":"number"},{"type":"null"}]},"ivTenorUsed":{"anyOf":[{"type":"string","enum":["7d","30d","generic"]},{"type":"null"}],"description":"Which IV tenor satisfied the pre-event lookup."},"impliedMovePct":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"1-day approximation: preEventAtmIv × √(1/252) × 100."},"realizedOverImplied":{"anyOf":[{"type":"number"},{"type":"null"}]},"ivCrushPct":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Positive = vol collapsed (crush)."}}}},"notes":{"type":"object","properties":{"methodology":{"type":"string"},"ivTenorPreference":{"type":"string"}}}}}}}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"404":{"description":"No earnings data for this symbol","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/analysts/{symbol}":{"get":{"operationId":"data.analysts","summary":"Analyst ratings and estimates","description":"Analyst consensus ratings, price targets, EPS estimates. Sourced from `analyst_data` table.","tags":["Data"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Analyst data","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"404":{"description":"No analyst data for this symbol","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/insiders/{symbol}":{"get":{"operationId":"data.insiders","summary":"Insider trading transactions","description":"SEC Form 4 filings and insider buy/sell activity. Sourced from `insider_trading_data` table.","tags":["Data"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Insider trading data","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"404":{"description":"No insider trading data for this symbol","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/company-data/{symbol}":{"get":{"operationId":"data.companyData","summary":"Extended company data","description":"Revenue segmentation, financial health scores, peer comparison. Sourced from `company_extended_data` table.","tags":["Data"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Company extended data","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"404":{"description":"No company data for this symbol","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/news/{symbol}":{"get":{"operationId":"data.news","summary":"Stock news and press releases","description":"Recent news and press releases for a symbol, paginated. Sourced from `stock_news` table.","tags":["Data"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"minimum":1,"maximum":200}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","default":1,"minimum":1,"maximum":10000},"description":"Pagination page. Capped at 10000 (= 2M rows at max limit) as an abuse guard; no legitimate caller needs more."}],"responses":{"200":{"description":"News articles","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/history/{symbol}":{"get":{"operationId":"data.history","summary":"Historical daily market data for a symbol","description":"Daily symbol history from `scan_tickers`: spot price, call/put volume, call/put OI, put/call ratio, ATM IV (generic, 7D, 30D tenors), and volume/OI ratio. Rows are returned chronologically (oldest first). If `start` or `end` is provided, the explicit date range is used and `days` is ignored.","tags":["Data"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":30,"minimum":1,"maximum":10000}},{"name":"start","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"Start date (YYYY-MM-DD). When set, the route uses explicit date-range mode and ignores days."},{"name":"end","in":"query","required":false,"schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Historical rows (chronological, oldest first)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HistoryResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"404":{"description":"No history found for this symbol","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/fred/{seriesId}":{"get":{"operationId":"data.fred","summary":"Federal Reserve Economic Data (FRED) series","description":"Historical FRED series observations with latest value and change. Sourced from `fred_series_data` table. Supports any FRED series ID the warehouse has synced (DFF, DGS10, T10Y2Y, etc.).","tags":["Data"],"parameters":[{"name":"seriesId","in":"path","required":true,"schema":{"type":"string"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":365,"minimum":1,"maximum":3650}}],"responses":{"200":{"description":"FRED series time series + latest value","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"404":{"description":"No FRED data for this series ID","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/treasury/auctions":{"get":{"operationId":"data.treasury.auctions","summary":"US Treasury auctions","description":"Treasury Direct auction history including security type, term, offering amount, and high investment rate. Sourced from `treasury_auctions` table.","tags":["Data"],"parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":30,"minimum":1,"maximum":3650}},{"name":"type","in":"query","required":false,"schema":{"type":"string","description":"Filter by security type (partial match)"}}],"responses":{"200":{"description":"Auction history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/bonds/etf/{symbol}":{"get":{"operationId":"data.bonds.etf","summary":"Bond ETF price history","description":"Daily price history for a bond ETF (TLT, IEF, HYG, LQD, etc.). Sourced from `bond_etf_prices` table.","tags":["Data"],"parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":30,"minimum":1,"maximum":500}}],"responses":{"200":{"description":"Bond ETF price history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"404":{"description":"No bond ETF data for this symbol","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/bonds/trace/aggregates":{"get":{"operationId":"data.bonds.traceAggregates","summary":"TRACE bond market aggregate data","description":"Aggregate TRACE bond trading data by date. Sourced from `trace_aggregate_data` table.","tags":["Data"],"parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":30,"minimum":1,"maximum":365}}],"responses":{"200":{"description":"TRACE aggregates","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/data/bonds/trace/sentiment":{"get":{"operationId":"data.bonds.traceSentiment","summary":"TRACE bond market sentiment data","description":"Sentiment indicators derived from TRACE bond trading. Sourced from `trace_sentiment_data` table.","tags":["Data"],"parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","default":30,"minimum":1,"maximum":365}}],"responses":{"200":{"description":"TRACE sentiment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse"}}}},"400":{"description":"Bad request — validation failed or invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthError"}}}},"403":{"description":"API key lacks the required scope for this endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopeError"}}}},"429":{"description":"Rate limit exceeded. X-RateLimit-* headers indicate current limits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"headers":{"X-RateLimit-Limit":{"description":"Maximum requests per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests remaining in current window","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"Unix timestamp when the rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalError"}}}},"503":{"description":"Service unavailable — worker pool draining or broker connection failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUnavailableError"}}}}}}},"/v1/ws":{"get":{"operationId":"streaming.websocket","summary":"Real-time streaming WebSocket","description":"Upgrade to a WebSocket connection for real-time market data streaming. Supports three channels:\n\n- **quotes**: live bid/ask/price/volume for underlyings and options\n- **greeks**: live delta/gamma/theta/vega/rho/IV for options\n- **exposure**: computed GEX/DEX/VEX/Vanna/Charm/Vomma snapshots, pushed on significant price ticks\n\n**BYOK broker credentials** are sent via the initial `auth` message. Supported brokers: `tastytrade`, `tradier` (Public.com is not supported — no streaming API).\n\n**Wire protocol:** JSON messages with discriminated `type` field. See the [Streaming Documentation](/docs/streaming) for the full protocol reference.\n\n**Connection lifecycle:** the server's setup (API-key check, tier + `streaming` scope gates, concurrency-slot acquisition) is asynchronous, and broker authentication (Tradier/DXLink handshake) is asynchronous again. Protocol order: `welcome` → `auth` → `auth_result` → `subscribe`. Early frames that arrive before `welcome` are buffered (up to 16) and drained once the session is wired, so sending `auth` in `onopen` works in practice — but the buffer protects only the transport race; protocol ordering still applies, so don't pre-queue `subscribe` before `auth_result`. Racing past the buffer cap returns `error: PRE_WELCOME_BUFFER_FULL`.\n\n**Quick example:**\n```\nwscat -c wss://data.optionsanalysissuite.com/v1/ws?apiKey=oas_live_...\n\n< {\"type\":\"welcome\",\"sessionId\":\"ws_...\",\"serverTime\":...,\"version\":\"1.0\"}\n> {\"type\":\"auth\",\"broker\":\"tastytrade\",\"credentials\":{\"tastytradeRefreshToken\":\"...\",\"tastytradeClientSecret\":\"...\"}}\n< {\"type\":\"connection\",\"status\":\"connecting\",\"broker\":\"tastytrade\"}\n< {\"type\":\"connection\",\"status\":\"connected\",\"broker\":\"tastytrade\"}\n< {\"type\":\"auth_result\",\"success\":true,\"broker\":\"tastytrade\"}\n> {\"type\":\"subscribe\",\"channels\":[\"quotes\",\"greeks\",\"exposure\"],\"symbols\":[\"SPY\"]}\n< {\"type\":\"subscribed\",\"channels\":[\"quotes\",\"greeks\",\"exposure\"],\"symbols\":[\"SPY\"]}\n< {\"type\":\"quote\",\"symbol\":\"SPY\",\"bid\":655.61,\"ask\":656.41,...}\n```\n\n**Session auth**: API key required via `apiKey` query param, `Authorization: Bearer`, or `X-API-Key`.\n","tags":["Streaming"],"parameters":[{"name":"apiKey","in":"query","required":false,"schema":{"type":"string"},"description":"API key (alternative to Authorization header for WebSocket upgrade)"}],"responses":{"101":{"description":"WebSocket upgrade successful"},"401":{"description":"API key missing or invalid"}}}}},"components":{"schemas":{"PriceRequest":{"type":"object","properties":{"model":{"default":"bs","type":"string","enum":["bs","heston","sabr","jd","vg","binomial","pde","fft","mc","localvol","barrier","asian","lookback","digital","compound","chooser","multiasset"]},"isCall":{"type":"boolean"},"K":{"type":"number","exclusiveMinimum":0},"S":{"type":"number","exclusiveMinimum":0},"r":{"type":"number"},"q":{"type":"number"},"sigma":{"type":"number","minimum":0},"t":{"type":"number","minimum":0},"symbol":{"type":"string","minLength":1,"maxLength":10},"expiry":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"expiration":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"resolve":{"default":{"spot":true,"sigma":true,"sigmaSource":"auto","dividend":true,"rate":true,"rateMode":"matched","tenor":true,"spotSource":"snapshot","calibration":false},"type":"object","properties":{"spot":{"default":true,"type":"boolean"},"sigma":{"default":true,"type":"boolean"},"sigmaSource":{"default":"auto","type":"string","enum":["auto","atmIv","hv"]},"dividend":{"default":true,"type":"boolean"},"rate":{"default":true,"type":"boolean"},"rateMode":{"default":"matched","type":"string","enum":["matched","fixedTenor"]},"rateTenor":{"type":"string","enum":["1MO","3MO","6MO","1Y","2Y","5Y","10Y","30Y"]},"tenor":{"default":true,"type":"boolean"},"spotSource":{"default":"snapshot","type":"string","enum":["snapshot"]},"calibration":{"default":false,"type":"boolean"}}},"modelParams":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"$ref":"#/$defs/__schema0"}},"calibrationId":{"type":"string"},"steps":{"default":200,"type":"integer","minimum":10,"maximum":5000},"isAmerican":{"default":false,"type":"boolean"},"detail":{"type":"string","enum":["summary","distribution","full"]},"histogramBins":{"type":"integer","minimum":2,"maximum":200}},"required":["isCall","K"],"$defs":{"__schema0":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"},{"type":"array","items":{"$ref":"#/$defs/__schema0"}},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"$ref":"#/$defs/__schema0"}}]}},"anyOf":[{"required":["t"]},{"required":["expiry"]},{"required":["expiration"]}]},"GreeksRequest":{"type":"object","properties":{"model":{"default":"bs","type":"string","enum":["bs","heston","sabr","jd","vg","binomial","pde","fft","mc","localvol","barrier","asian","lookback","digital","compound","chooser","multiasset"]},"isCall":{"type":"boolean"},"K":{"type":"number","exclusiveMinimum":0},"S":{"type":"number","exclusiveMinimum":0},"r":{"type":"number"},"q":{"type":"number"},"sigma":{"type":"number","minimum":0},"t":{"type":"number","minimum":0},"symbol":{"type":"string","minLength":1,"maxLength":10},"expiry":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"expiration":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"resolve":{"default":{"spot":true,"sigma":true,"sigmaSource":"auto","dividend":true,"rate":true,"rateMode":"matched","tenor":true,"spotSource":"snapshot","calibration":false},"type":"object","properties":{"spot":{"default":true,"type":"boolean"},"sigma":{"default":true,"type":"boolean"},"sigmaSource":{"default":"auto","type":"string","enum":["auto","atmIv","hv"]},"dividend":{"default":true,"type":"boolean"},"rate":{"default":true,"type":"boolean"},"rateMode":{"default":"matched","type":"string","enum":["matched","fixedTenor"]},"rateTenor":{"type":"string","enum":["1MO","3MO","6MO","1Y","2Y","5Y","10Y","30Y"]},"tenor":{"default":true,"type":"boolean"},"spotSource":{"default":"snapshot","type":"string","enum":["snapshot"]},"calibration":{"default":false,"type":"boolean"}}},"modelParams":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"$ref":"#/$defs/__schema0"}},"calibrationId":{"type":"string"},"includeInsight":{"default":false,"type":"boolean"},"steps":{"default":200,"type":"integer","minimum":10,"maximum":5000},"isAmerican":{"default":false,"type":"boolean"}},"required":["isCall","K"],"$defs":{"__schema0":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"},{"type":"array","items":{"$ref":"#/$defs/__schema0"}},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"$ref":"#/$defs/__schema0"}}]}},"anyOf":[{"required":["t"]},{"required":["expiry"]},{"required":["expiration"]}]},"ExposureRequest":{"type":"object","properties":{"strikes":{"minItems":1,"maxItems":5000,"type":"array","items":{"type":"object","properties":{"strike_cents":{"type":"number"},"stk_px_cents":{"type":"number"},"c_oi":{"type":"number"},"p_oi":{"type":"number"},"gamma":{"type":"number"},"delta":{"type":"number"},"vega":{"type":"number"},"smooth_smv_vol":{"type":"number"},"c_mid_iv":{"type":"number"},"p_mid_iv":{"type":"number"},"yte":{"type":"number"},"expir_date":{"type":"string"}},"required":["strike_cents","stk_px_cents","c_oi","p_oi","gamma"]}},"spotPrice":{"type":"number","exclusiveMinimum":0},"riskFreeRate":{"default":0.05,"type":"number"},"dividendYield":{"default":0,"type":"number"},"wallMaxDte":{"type":"number"}},"required":["strikes","spotPrice"]},"ScenarioRequest":{"type":"object","properties":{"isCall":{"type":"boolean"},"S":{"type":"number","exclusiveMinimum":0},"K":{"type":"number","exclusiveMinimum":0},"r":{"type":"number"},"q":{"default":0,"type":"number"},"sigma":{"type":"number","minimum":0},"t":{"type":"number","minimum":0},"spotChanges":{"minItems":2,"maxItems":20,"type":"array","items":{"type":"number"}},"volChanges":{"minItems":2,"maxItems":20,"type":"array","items":{"type":"number"}}},"required":["isCall","S","K","r","sigma","t","spotChanges","volChanges"]},"SensitivityRequest":{"type":"object","properties":{"isCall":{"type":"boolean"},"S":{"type":"number","exclusiveMinimum":0},"K":{"type":"number","exclusiveMinimum":0},"r":{"type":"number"},"q":{"default":0,"type":"number"},"sigma":{"type":"number","minimum":0},"t":{"type":"number","minimum":0},"axis":{"type":"string","enum":["spot","time","volatility"]},"points":{"default":50,"type":"integer","minimum":5,"maximum":200},"spotMin":{"type":"number","exclusiveMinimum":0},"spotMax":{"type":"number","exclusiveMinimum":0},"daysToExpiry":{"type":"number","exclusiveMinimum":0},"volMin":{"type":"number","minimum":0},"volMax":{"type":"number","exclusiveMinimum":0},"model":{"default":"bs","type":"string","enum":["bs","heston"]},"modelParams":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"$ref":"#/$defs/__schema0"}},"greeks":{"maxItems":20,"type":"array","items":{"type":"string"}}},"required":["isCall","S","K","r","sigma","t","axis"],"$defs":{"__schema0":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"},{"type":"array","items":{"$ref":"#/$defs/__schema0"}},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"$ref":"#/$defs/__schema0"}}]}}},"MaxPainRequest":{"type":"object","properties":{"strikes":{"minItems":1,"maxItems":5000,"type":"array","items":{"type":"object","properties":{"strike":{"type":"number","exclusiveMinimum":0},"callOI":{"type":"number","minimum":0},"putOI":{"type":"number","minimum":0}},"required":["strike","callOI","putOI"]}}},"required":["strikes"]},"ExpectedMoveRequest":{"type":"object","properties":{"spotPrice":{"type":"number","exclusiveMinimum":0},"strikePrice":{"type":"number","exclusiveMinimum":0},"riskFreeRate":{"default":0.05,"type":"number"},"dividendYield":{"default":0,"type":"number"},"atmIV":{"type":"number","exclusiveMinimum":0},"daysToExpiry":{"type":"number","exclusiveMinimum":0},"atmCallPrice":{"type":"number","minimum":0},"atmPutPrice":{"type":"number","minimum":0},"atmIv":{"type":"number","exclusiveMinimum":0,"description":"Alias for `atmIV`. Accepted so callers can pipe the `atmIv` field from /v1/data/metrics/{symbol} or /v1/data/snapshot/{symbol} directly."}},"required":["spotPrice","daysToExpiry"],"anyOf":[{"required":["atmIV"]},{"required":["atmIv"]}]},"ProbabilityRequest":{"anyOf":[{"type":"object","properties":{"mode":{"default":"simple","type":"string","const":"simple"},"spotPrice":{"type":"number","exclusiveMinimum":0},"strikes":{"minItems":3,"maxItems":500,"type":"array","items":{"type":"number","exclusiveMinimum":0}},"ivs":{"minItems":3,"maxItems":500,"type":"array","items":{"type":"number","minimum":0}},"riskFreeRate":{"default":0.05,"type":"number"},"dividendYield":{"default":0,"type":"number"},"timeToExpiry":{"type":"number","exclusiveMinimum":0}},"required":["spotPrice","strikes","ivs","timeToExpiry"]},{"type":"object","properties":{"mode":{"type":"string","const":"full"},"symbol":{"type":"string","minLength":1,"maxLength":10},"expiration":{"type":"string"},"riskFreeRate":{"default":0.05,"type":"number"},"dividendYield":{"default":0,"type":"number"}},"required":["mode","symbol"]}]},"CalibrateRequest":{"type":"object","required":["model","symbol"],"properties":{"model":{"type":"string","enum":["heston","sabr","vg","jd","localvol"],"description":"Model to calibrate"},"symbol":{"type":"string","description":"Ticker symbol (e.g. \"SPY\")"},"expiration":{"type":"string","description":"Optional: specific expiration date (YYYY-MM-DD). Defaults to nearest."},"modelParams":{"type":"object","description":"Model-specific calibration options. Supported keys by model:\n\n**heston:** `accuracyMode` (\"fast\" | \"balanced\" | \"precise\", default \"balanced\")\n\n**sabr:** `fixBeta` (boolean, default true), `accuracyMode` (\"fast\" | \"balanced\" | \"precise\")\n\n**jd:** `modelType` / `jdModel` (\"kou\" | \"merton\" | \"bates\", default \"kou\")\n\n**vg / localvol:** no extra options","additionalProperties":true}}},"ResolvedInputs":{"type":"object","description":"Echo of the inputs actually used for the calculation, after ticker auto-fill and calibration resolution.","required":["isCall","S","K","r","q","sigma","t"],"properties":{"isCall":{"type":"boolean"},"S":{"type":"number","description":"Spot price"},"K":{"type":"number","description":"Strike price"},"r":{"type":"number","description":"Risk-free rate (decimal)"},"q":{"type":"number","description":"Dividend yield (decimal)"},"sigma":{"type":"number","description":"Volatility (decimal)"},"t":{"type":"number","description":"Time to expiry (years)"},"modelParams":{"type":"object","additionalProperties":true,"description":"Model-specific knobs supplied or filled in by calibration"},"calibrationId":{"type":"string","description":"30-second in-memory handle returned by /v1/compute/calibrate. Persist `modelParams` for durable reuse."}},"additionalProperties":false},"ResolvedSummary":{"type":"object","description":"Per-input resolution metadata when ticker auto-fill ran. Each entry is { value, source }.","additionalProperties":{"type":"object","properties":{"value":{"type":"number"},"source":{"type":"string"}},"required":["value","source"],"additionalProperties":true}},"PriceResponse":{"type":"object","required":["price","model","inputs"],"properties":{"price":{"type":"number","description":"Theoretical option price"},"model":{"type":"string","description":"Pricing model name (e.g. \"Black-Scholes-Merton\")"},"inputs":{"$ref":"#/components/schemas/ResolvedInputs"},"greeks":{"type":"object","additionalProperties":{"type":"number"},"description":"Per-Greek values produced as a side effect of pricing for some models (binomial returns delta/gamma; PDE production path returns delta/gamma/vega/theta/rho). Use /v1/compute/greeks for the full 17-Greek response across all models."},"mcStats":{"$ref":"#/components/schemas/McStats"},"distribution":{"$ref":"#/components/schemas/McDistribution"},"fullPaths":{"type":"array","description":"Raw simulated paths. Present only when `model: \"mc\"` and `detail: \"full\"`. Subsampled uniformly to satisfy two server-enforced caps: a max path count (default 1,000,000) and a max total numbers serialized (default 5,000,000). `fullPathsTruncated: true` flags when subsampling ran.","items":{"type":"array","items":{"type":"number"}}},"fullPathsTruncated":{"type":"boolean","description":"True when the response was uniformly subsampled because the simulated path count exceeded the cap."},"resolved":{"$ref":"#/components/schemas/ResolvedSummary"},"warnings":{"type":"array","items":{"type":"string"},"description":"Resolution warnings emitted during ticker auto-fill"}},"additionalProperties":false},"McStats":{"type":"object","description":"Monte Carlo simulation statistics. Present only when `model: \"mc\"`. Use `stdError` and the (`ciLow`, `ciHigh`) 95% confidence interval to gauge convergence — increase `nPaths` if the interval is wider than your tolerance.","required":["stdError","ciLow","ciHigh","nPaths"],"properties":{"stdError":{"type":"number","description":"Standard error of the price estimate."},"ciLow":{"type":"number","description":"Lower bound of the 95% confidence interval for the price."},"ciHigh":{"type":"number","description":"Upper bound of the 95% confidence interval for the price."},"nPaths":{"type":"integer","description":"Effective number of paths the estimate was built from. With antithetic variates enabled this is up to 2× the requested `nPaths`."}},"additionalProperties":false},"McDistribution":{"type":"object","description":"Terminal underlying-price distribution from a Monte Carlo simulation. Present only when `model: \"mc\"` and `detail: \"distribution\"` (or `\"full\"`). Computed from every simulated path — does not subsample.","required":["count","min","max","mean","percentiles","histogram"],"properties":{"count":{"type":"integer","description":"Number of simulated paths the distribution was built from."},"mean":{"type":"number","description":"Mean of the simulated terminal price."},"min":{"type":"number","description":"Minimum simulated terminal price."},"max":{"type":"number","description":"Maximum simulated terminal price."},"percentiles":{"type":"object","description":"Linearly-interpolated percentiles of the simulated terminal price.","required":["p1","p5","p10","p25","p50","p75","p90","p95","p99"],"properties":{"p1":{"type":"number"},"p5":{"type":"number"},"p10":{"type":"number"},"p25":{"type":"number"},"p50":{"type":"number","description":"Median."},"p75":{"type":"number"},"p90":{"type":"number"},"p95":{"type":"number"},"p99":{"type":"number"}},"additionalProperties":false},"histogram":{"type":"object","description":"Equal-width histogram. `binEdges` length is `counts.length + 1`; bin `i` covers `[binEdges[i], binEdges[i+1])`. Bin count is configurable up to a server-enforced cap of 200; default 50.","required":["binEdges","counts"],"properties":{"binEdges":{"type":"array","items":{"type":"number"}},"counts":{"type":"array","items":{"type":"integer"}}},"additionalProperties":false}},"additionalProperties":false},"ExoticInsightMetric":{"type":"object","properties":{"label":{"type":"string"},"value":{"type":"string"},"rawValue":{"type":"number"},"highlight":{"type":"boolean"}},"required":["label","value","rawValue"]},"ExoticInsight":{"type":"object","properties":{"model":{"type":"string"},"title":{"type":"string"},"subtitle":{"type":"string"},"accentColor":{"type":"string"},"metrics":{"type":"array","items":{"$ref":"#/components/schemas/ExoticInsightMetric"}},"verdict":{"type":"string"},"verdictType":{"type":"string","enum":["positive","negative","neutral"]}},"required":["model","title","subtitle","accentColor","metrics","verdict","verdictType"]},"GreeksResponse":{"type":"object","description":"Full 17-Greek response for all 17 pricing models. Analytical or native Greeks are used where available; finite-difference bump-and-reprice fills the remaining sensitivities. Monte Carlo Greeks use parallel bump-and-reprice over price-only Monte Carlo evaluations. Exotic models may optionally include an `exoticInsight` block when `includeInsight: true` is requested.","required":["model","price","inputs"],"properties":{"model":{"type":"string"},"price":{"type":"number"},"delta":{"type":"number","description":"dP/dS"},"vega":{"type":"number","description":"dP/dσ (per 1% vol change)"},"theta":{"type":"number","description":"dP/dt (per day)"},"rho":{"type":"number","description":"dP/dr (per 1% rate change)"},"epsilon":{"type":"number","description":"dP/dq (per 1% dividend yield change)"},"gamma":{"type":"number","description":"d²P/dS²"},"vanna":{"type":"number","description":"d²P/dSdσ"},"charm":{"type":"number","description":"d²P/dSdt (delta decay)"},"vomma":{"type":"number","description":"d²P/dσ² (vega convexity)"},"veta":{"type":"number","description":"d²P/dσdt (vega decay)"},"speed":{"type":"number","description":"d³P/dS³ (gamma sensitivity to spot)"},"zomma":{"type":"number","description":"d³P/dS²dσ (gamma sensitivity to vol)"},"color":{"type":"number","description":"d³P/dS²dt (gamma decay)"},"ultima":{"type":"number","description":"d³P/dσ³ (vomma sensitivity to vol)"},"dcharmDvol":{"type":"number","description":"d³P/dSdtdσ (charm sensitivity to vol)"},"lambda":{"type":"number","description":"Leverage: delta × S / P (also called Omega)"},"phi":{"type":"number","description":"d/d(r−q) = rho − epsilon (carry sensitivity)"},"exoticInsight":{"$ref":"#/components/schemas/ExoticInsight"},"inputs":{"$ref":"#/components/schemas/ResolvedInputs"},"resolved":{"$ref":"#/components/schemas/ResolvedSummary"},"warnings":{"type":"array","items":{"type":"string"},"description":"Resolution warnings emitted during ticker auto-fill"}},"additionalProperties":false},"ExposureStrike":{"type":"object","description":"Per-strike Greek-exposure row. Dealer-perspective dollar exposures across the full chain.","required":["strike","callGamma","putGamma","netGamma","callDelta","putDelta","netDelta","callVega","putVega","netVega","callVanna","putVanna","netVanna","callCharm","putCharm","netCharm","callVomma","putVomma","netVomma"],"properties":{"strike":{"type":"number"},"callGamma":{"type":"number"},"putGamma":{"type":"number"},"netGamma":{"type":"number"},"callDelta":{"type":"number"},"putDelta":{"type":"number"},"netDelta":{"type":"number"},"callVega":{"type":"number"},"putVega":{"type":"number"},"netVega":{"type":"number"},"callVanna":{"type":"number"},"putVanna":{"type":"number"},"netVanna":{"type":"number"},"callCharm":{"type":"number"},"putCharm":{"type":"number"},"netCharm":{"type":"number"},"callVomma":{"type":"number"},"putVomma":{"type":"number"},"netVomma":{"type":"number"}},"additionalProperties":false},"ExposureSnapshot":{"type":"object","description":"Compact exposure summary: net totals, walls, gamma flip, abs gamma anchor, regime, top-10 strikes.","required":["spotPrice","netGamma","netDelta","netVega","netVanna","netCharm","netVomma","callWall","putWall","gammaFlip","absGamma","gammaConcentration","regime","topStrikes"],"properties":{"spotPrice":{"type":"number"},"netGamma":{"type":"number"},"netDelta":{"type":"number"},"netVega":{"type":"number"},"netVanna":{"type":"number"},"netCharm":{"type":"number"},"netVomma":{"type":"number"},"callWall":{"anyOf":[{"type":"number"},{"type":"null"}]},"putWall":{"anyOf":[{"type":"number"},{"type":"null"}]},"gammaFlip":{"anyOf":[{"type":"number"},{"type":"null"}]},"absGamma":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Strike with the largest absolute net gamma in the wall/flip universe"},"gammaConcentration":{"anyOf":[{"type":"number"},{"type":"null"}]},"regime":{"type":"string","enum":["positive","negative","neutral"]},"topStrikes":{"type":"array","items":{"$ref":"#/components/schemas/ExposureStrike"},"description":"Top-10 strikes by absolute net gamma"}},"additionalProperties":false},"ExposureFullResult":{"type":"object","description":"Full result: compact snapshot plus the entire by-strike Greek-exposure array.","required":["snapshot","byStrike"],"properties":{"snapshot":{"$ref":"#/components/schemas/ExposureSnapshot"},"byStrike":{"type":"array","items":{"$ref":"#/components/schemas/ExposureStrike"}}},"additionalProperties":false},"ExposureResponse":{"oneOf":[{"$ref":"#/components/schemas/ExposureFullResult"},{"$ref":"#/components/schemas/ExposureSnapshot"}],"description":"Default: ExposureFullResult ({ snapshot, byStrike }). With ?detail=snapshot: ExposureSnapshot directly."},"ScenarioMatrixEntry":{"type":"object","description":"One cell in the scenario matrix: option value and P/L at a spot and volatility perturbation.","required":["spotChange","volChange","spot","volatility","price","pnl","pnlPercent"],"properties":{"spotChange":{"type":"number","description":"Relative spot perturbation, e.g. -0.05 for -5%."},"volChange":{"type":"number","description":"Relative volatility perturbation, e.g. 0.10 for +10%."},"spot":{"type":"number","description":"Scenario spot price after applying spotChange."},"volatility":{"type":"number","description":"Scenario volatility after applying volChange."},"price":{"type":"number","description":"Option price under this scenario."},"pnl":{"type":"number","description":"Dollar P/L versus the base option price."},"pnlPercent":{"type":"number","description":"Percent P/L versus the base option price."}},"additionalProperties":false},"ScenarioResponse":{"type":"object","required":["spotChanges","volChanges","matrix"],"properties":{"spotChanges":{"type":"array","items":{"type":"number"}},"volChanges":{"type":"array","items":{"type":"number"}},"matrix":{"type":"array","items":{"type":"array","items":{"$ref":"#/components/schemas/ScenarioMatrixEntry"}},"description":"2D matrix of structured cells indexed by [spotChange][volChange]."}},"additionalProperties":false},"SensitivityResponse":{"type":"object","description":"Per-axis sweep of Greeks. Each point carries the full 17-Greek set under Black-Scholes (model defaults to \"bs\"). When `model: \"heston\"`, points additionally carry a `modelGreeks` block with derivatives w.r.t. the Heston parameters (V0, kappa, theta, volOfVol, rho).","required":["axis","model","data"],"properties":{"axis":{"type":"string","enum":["spot","time","volatility"]},"model":{"type":"string","enum":["bs","heston"],"description":"Model used for the sweep."},"data":{"type":"array","items":{"$ref":"#/components/schemas/SensitivityPoint"}}},"additionalProperties":false},"SensitivityPoint":{"type":"object","description":"One point on a sensitivity sweep. `x` is the sweep variable (spot price for axis=\"spot\", days-to-expiry for \"time\", volatility for \"volatility\"). The standard 17 Greeks come from Black-Scholes; `modelGreeks` is present only when `model: \"heston\"`.","required":["x"],"properties":{"x":{"type":"number","description":"Sweep variable value at this point."},"price":{"type":"number"},"delta":{"type":"number"},"gamma":{"type":"number"},"vega":{"type":"number"},"theta":{"type":"number"},"rho":{"type":"number"},"epsilon":{"type":"number"},"vanna":{"type":"number"},"charm":{"type":"number"},"vomma":{"type":"number"},"veta":{"type":"number"},"speed":{"type":"number"},"zomma":{"type":"number"},"color":{"type":"number"},"ultima":{"type":"number"},"lambda":{"type":"number"},"phi":{"type":"number"},"dcharmDvol":{"type":"number"},"modelGreeks":{"$ref":"#/components/schemas/HestonModelGreeks"}},"additionalProperties":false},"HestonModelGreeks":{"type":"object","description":"Sensitivities of the Heston price to its five model parameters. Present only when `model: \"heston\"` was requested. Computed by symmetric finite-difference around the calibrated parameter point; useful for assessing exposure to a miscalibrated Heston model (vs. classic Greeks which assume the model is correct and only the market inputs vary).","required":["dV0","dKappa","dTheta","dVolOfVol","dRho"],"properties":{"dV0":{"type":"number","description":"d(price) / d(V0) — sensitivity to instantaneous variance."},"dKappa":{"type":"number","description":"d(price) / d(kappa) — mean-reversion speed."},"dTheta":{"type":"number","description":"d(price) / d(theta) — long-run variance."},"dVolOfVol":{"type":"number","description":"d(price) / d(xi) — vol-of-vol."},"dRho":{"type":"number","description":"d(price) / d(rho) — spot/vol correlation."}},"additionalProperties":false},"MaxPainResponse":{"type":"object","properties":{"maxPainStrike":{"type":"number"},"totalPainAtMaxPain":{"type":"number"},"painByStrike":{"type":"array","items":{"type":"object","properties":{"strike":{"type":"number"},"totalPain":{"type":"number"}}}}}},"ExpectedMoveResponse":{"type":"object","properties":{"spotPrice":{"type":"number"},"strikePrice":{"type":"number"},"atmIV":{"type":"number"},"daysToExpiry":{"type":"number"},"method":{"type":"string","enum":["market-straddle","bs-straddle"]},"straddle":{"type":"number"},"expectedMoveAbsolute":{"type":"number"},"expectedMovePercent":{"type":"number"},"upperBound":{"type":"number"},"lowerBound":{"type":"number"},"ivApproxMove":{"type":"number"}}},"ProbabilityResponse":{"type":"object","properties":{"riskNeutral":{"type":"object","properties":{"pdf":{"type":"array","items":{"type":"object","properties":{"strike":{"type":"number"},"density":{"type":"number"}}}},"cdf":{"type":"array","items":{"type":"object","properties":{"strike":{"type":"number"},"cumulative":{"type":"number"}}}},"stats":{"type":"object","properties":{"impliedMove":{"type":"number"},"movePercent":{"type":"number"},"lower":{"type":"number"},"upper":{"type":"number"},"fairValue":{"type":"number"},"stdDev":{"type":"number"}}},"method":{"type":"string","enum":["essvi","finite-diff"]},"methodLabel":{"type":"string"},"quality":{"type":"string","enum":["high","medium","low"]},"fallbackReason":{"anyOf":[{"type":"string"},{"type":"null"}]}}},"lognormal":{"type":"object","properties":{"pdf":{"type":"array","items":{"type":"object"}},"cdf":{"type":"array","items":{"type":"object"}},"stats":{"type":"object","properties":{"move":{"type":"number"},"movePercent":{"type":"number"},"lower":{"type":"number"},"upper":{"type":"number"},"expectedValue":{"type":"number"}}}}},"spotPrice":{"type":"number"},"expiration":{"anyOf":[{"type":"string"},{"type":"null"}]},"timeToExpiry":{"type":"number"},"riskFreeRate":{"type":"number"},"dividendYield":{"type":"number"}}},"CalibrateResponse":{"type":"object","required":["model","symbol","expiration","params","fitError","calibrationTimeMs","calibrationId","provider"],"properties":{"model":{"type":"string"},"symbol":{"type":"string"},"expiration":{"type":"string"},"params":{"type":"object","additionalProperties":{"anyOf":[{"type":"number"},{"type":"string"}]}},"fitError":{"type":"object","required":["ivRmse","nOptions"],"properties":{"ivRmse":{"type":"number","description":"Aggregate IV RMSE across all options used for the fit."},"nOptions":{"type":"integer","description":"Number of options included in the fit."}},"additionalProperties":false},"fitDiagnostics":{"$ref":"#/components/schemas/FitDiagnostics"},"calibrationTimeMs":{"type":"number"},"calibrationId":{"type":"string"},"provider":{"type":"string"}},"additionalProperties":false},"FitDiagnostics":{"type":"object","description":"Per-moneyness-bucket fit-quality diagnostics. Computed by re-pricing each market option with the calibrated parameters. Currently emitted for `model: \"heston\"` only; other models will gain support as their public price functions are exposed.","required":["residuals","bucketRmse","bucketCount","worstFitOption"],"properties":{"residuals":{"type":"array","description":"Per-option residuals (model price − market mid). Capped at 100, sorted by descending |residual| so the worst fits survive the cap.","items":{"$ref":"#/components/schemas/FitResidual"}},"bucketRmse":{"type":"object","description":"RMSE of price residuals within each moneyness bucket. Null when the bucket has no eligible options.","required":["atm","otm_call","otm_put","deep_otm"],"properties":{"atm":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"|moneyness − 1| < 0.05."},"otm_call":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"moneyness > 1.05."},"otm_put":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"moneyness < 0.95."},"deep_otm":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"|moneyness − 1| > 0.20."}},"additionalProperties":false},"bucketCount":{"type":"object","description":"Number of options included in each moneyness bucket, mirrors `bucketRmse`.","required":["atm","otm_call","otm_put","deep_otm"],"properties":{"atm":{"type":"integer"},"otm_call":{"type":"integer"},"otm_put":{"type":"integer"},"deep_otm":{"type":"integer"}},"additionalProperties":false},"worstFitOption":{"anyOf":[{"$ref":"#/components/schemas/FitResidual"},{"type":"null"}],"description":"Single worst-fitting option in absolute residual terms. Null if no options were re-priceable."}},"additionalProperties":false},"FitResidual":{"type":"object","required":["strike","type","moneyness","priceResidual"],"properties":{"strike":{"type":"number"},"type":{"type":"string","enum":["call","put"]},"moneyness":{"type":"number","description":"K / S at the time of calibration."},"priceResidual":{"type":"number","description":"Model price − market mid (in price units, NOT IV units — aggregate `fitError.ivRmse` is the IV-space companion)."}},"additionalProperties":false},"RegimeResponse":{"type":"object","description":"Latest market regime. Both `daily` and `intraday` are raw rows from the regime_daily / regime_intraday warehouse tables. Field set is owned by the data-pipeline team and may evolve over time — access defensively. Either field may be null when no row is available.","properties":{"daily":{"anyOf":[{"type":"object","additionalProperties":true},{"type":"null"}],"description":"Latest row from regime_daily for symbol=MARKET, scope=market, ordered by market_date desc. Null when no row exists."},"intraday":{"anyOf":[{"type":"object","additionalProperties":true},{"type":"null"}],"description":"Latest row from regime_intraday for symbol=MARKET, scope=market, ordered by (market_date, scan_time) desc. Null when no row exists."}},"additionalProperties":false},"MaxPainCurveRow":{"type":"object","description":"One per-strike row of the max-pain curve. Pain values are dollar-weighted aggregate OI × distance × multiplier.","required":["strike","callPain","putPain","totalPain"],"properties":{"strike":{"type":"number"},"callPain":{"type":"number"},"putPain":{"type":"number"},"totalPain":{"type":"number"}},"additionalProperties":false},"SnapshotResponse":{"type":"object","description":"EOD options snapshot: spot, IV term structure, GEX/DEX/HV, max pain, plus opaque curve payloads consumed by the web app charts.","required":["ticker","date","spotPrice","maxPain","netGex","netDex","atmIv","atmIv7d","atmIv30d","atmIv90d","putCallRatio","ivSkew25d","dividendYield","totalVolume","totalOi","callVolume","putVolume","callOi","putOi","expectedMovePct","ivRank","ivPercentile","hv20d","hv60d","maxPainCurve","gexByStrike","dexByStrike","vannaByStrike","charmByStrike","vommaByStrike","volSkew","probabilityData","chainData","analyticsExpiry","chainExpiry"],"properties":{"ticker":{"type":"string"},"date":{"type":"string","format":"date"},"spotPrice":{"anyOf":[{"type":"number"},{"type":"null"}]},"maxPain":{"anyOf":[{"type":"number"},{"type":"null"}]},"netGex":{"anyOf":[{"type":"number"},{"type":"null"}]},"netDex":{"anyOf":[{"type":"number"},{"type":"null"}]},"atmIv":{"anyOf":[{"type":"number"},{"type":"null"}]},"atmIv7d":{"anyOf":[{"type":"number"},{"type":"null"}]},"atmIv30d":{"anyOf":[{"type":"number"},{"type":"null"}]},"atmIv90d":{"anyOf":[{"type":"number"},{"type":"null"}]},"putCallRatio":{"anyOf":[{"type":"number"},{"type":"null"}]},"ivSkew25d":{"anyOf":[{"type":"number"},{"type":"null"}]},"dividendYield":{"anyOf":[{"type":"number"},{"type":"null"}]},"totalVolume":{"anyOf":[{"type":"number"},{"type":"null"}]},"totalOi":{"anyOf":[{"type":"number"},{"type":"null"}]},"callVolume":{"anyOf":[{"type":"number"},{"type":"null"}]},"putVolume":{"anyOf":[{"type":"number"},{"type":"null"}]},"callOi":{"anyOf":[{"type":"number"},{"type":"null"}]},"putOi":{"anyOf":[{"type":"number"},{"type":"null"}]},"expectedMovePct":{"anyOf":[{"type":"number"},{"type":"null"}]},"ivRank":{"anyOf":[{"type":"number"},{"type":"null"}]},"ivPercentile":{"anyOf":[{"type":"number"},{"type":"null"}]},"hv20d":{"anyOf":[{"type":"number"},{"type":"null"}]},"hv60d":{"anyOf":[{"type":"number"},{"type":"null"}]},"maxPainCurve":{"anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/MaxPainCurveRow"}},{"type":"null"}],"description":"Max-pain curve series for the chart UI: per-strike rows of { strike, callPain, putPain, totalPain }."},"gexByStrike":{"anyOf":[{"type":"array","items":{"type":"object","additionalProperties":true}},{"type":"null"}],"description":"GEX-by-strike series; opaque payload"},"dexByStrike":{"anyOf":[{"type":"array","items":{"type":"object","additionalProperties":true}},{"type":"null"}],"description":"DEX-by-strike series; opaque payload"},"vannaByStrike":{"anyOf":[{"type":"array","items":{"type":"object","additionalProperties":true}},{"type":"null"}],"description":"Vanna-by-strike series; opaque payload"},"charmByStrike":{"anyOf":[{"type":"array","items":{"type":"object","additionalProperties":true}},{"type":"null"}],"description":"Charm-by-strike series; opaque payload"},"vommaByStrike":{"anyOf":[{"type":"array","items":{"type":"object","additionalProperties":true}},{"type":"null"}],"description":"Vomma-by-strike series; opaque payload"},"volSkew":{"anyOf":[{"type":"object","additionalProperties":true},{"type":"null"}],"description":"Vol-skew curve; opaque payload"},"probabilityData":{"anyOf":[{"type":"object","additionalProperties":true},{"type":"null"}],"description":"Risk-neutral probability data; opaque payload"},"chainData":{"anyOf":[{"type":"array","items":{"type":"object","additionalProperties":true}},{"type":"null"}],"description":"Recent option chain rows; opaque payload"},"analyticsExpiry":{"anyOf":[{"type":"string"},{"type":"null"}]},"chainExpiry":{"anyOf":[{"type":"string"},{"type":"null"}]}},"additionalProperties":false},"MetricsResponse":{"type":"object","description":"Per-symbol EOD metrics row. Sourced from option_ticker_snapshots.","required":["symbol","date","atmIv","ivRank","ivPercentile","hv20d","hv60d","putCallRatio","totalVolume","totalOi","callVolume","putVolume","callOi","putOi","maxPain","expectedMovePct"],"properties":{"symbol":{"type":"string"},"date":{"type":"string","format":"date"},"atmIv":{"anyOf":[{"type":"number"},{"type":"null"}]},"ivRank":{"anyOf":[{"type":"number"},{"type":"null"}]},"ivPercentile":{"anyOf":[{"type":"number"},{"type":"null"}]},"hv20d":{"anyOf":[{"type":"number"},{"type":"null"}]},"hv60d":{"anyOf":[{"type":"number"},{"type":"null"}]},"putCallRatio":{"anyOf":[{"type":"number"},{"type":"null"}]},"totalVolume":{"anyOf":[{"type":"number"},{"type":"null"}]},"totalOi":{"anyOf":[{"type":"number"},{"type":"null"}]},"callVolume":{"anyOf":[{"type":"number"},{"type":"null"}]},"putVolume":{"anyOf":[{"type":"number"},{"type":"null"}]},"callOi":{"anyOf":[{"type":"number"},{"type":"null"}]},"putOi":{"anyOf":[{"type":"number"},{"type":"null"}]},"maxPain":{"anyOf":[{"type":"number"},{"type":"null"}]},"expectedMovePct":{"anyOf":[{"type":"number"},{"type":"null"}]}},"additionalProperties":false},"IVSurfaceResponse":{"type":"object","description":"Strike × expiration grid of implied volatility for the symbol. Each row carries the smoothed value (`smv`), the call-side and put-side mid IVs, and a unified `iv` that falls back through smv → callIV → putIV. Any of the IV fields may be null when source data is missing.","required":["ticker","date","spotPrice","expirations","rowCount","data"],"properties":{"ticker":{"type":"string","description":"Underlying symbol echoed from the request (uppercased)."},"date":{"type":"string","format":"date","description":"Market date the surface snapshot applies to."},"spotPrice":{"type":"number","description":"Spot price observed for this surface, in dollars."},"expirations":{"type":"array","items":{"type":"string","format":"date"},"description":"Sorted list of distinct expiration dates present in `data`."},"rowCount":{"type":"integer","description":"Number of strike × expiration rows returned."},"data":{"type":"array","items":{"$ref":"#/components/schemas/IVSurfacePoint"}}},"additionalProperties":false},"IVSurfacePoint":{"type":"object","required":["strike","expiration","yte"],"properties":{"strike":{"type":"number","description":"Strike price in dollars."},"expiration":{"type":"string","format":"date","description":"Option expiration date."},"yte":{"type":"number","description":"Years to expiration as a decimal (calendar-day fraction)."},"iv":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Unified IV — smv → callIV → putIV fallback. Null only if all three sources are missing."},"callIV":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Call-side mid IV."},"putIV":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Put-side mid IV."},"smv":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Smoothed surface IV (warehouse-derived)."}},"additionalProperties":false},"ListResponse":{"type":"object","properties":{"count":{"type":"number"},"data":{"type":"array","items":{"type":"object","additionalProperties":true}}}},"MetricsBatchResponse":{"type":"object","required":["count","data"],"properties":{"count":{"type":"number"},"data":{"type":"array","items":{"$ref":"#/components/schemas/MetricsResponse"}}},"additionalProperties":false},"HistoryRow":{"type":"object","properties":{"market_date":{"type":"string","format":"date"},"spot_price":{"anyOf":[{"type":"number"},{"type":"null"}]},"call_volume":{"anyOf":[{"type":"number"},{"type":"null"}]},"put_volume":{"anyOf":[{"type":"number"},{"type":"null"}]},"call_oi":{"anyOf":[{"type":"number"},{"type":"null"}]},"put_oi":{"anyOf":[{"type":"number"},{"type":"null"}]},"put_call_ratio":{"anyOf":[{"type":"number"},{"type":"null"}]},"atm_iv":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Generic ATM IV (all expirations blended)."},"atm_iv_7d":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"7-day tenor ATM IV — closest persisted proxy to event-week vol around earnings."},"atm_iv_30d":{"anyOf":[{"type":"number"},{"type":"null"}]},"volume_oi_ratio":{"anyOf":[{"type":"number"},{"type":"null"}]}},"additionalProperties":false},"HistoryResponse":{"type":"object","properties":{"symbol":{"type":"string"},"count":{"type":"number"},"data":{"type":"array","items":{"$ref":"#/components/schemas/HistoryRow"}}},"additionalProperties":false},"HealthResponse":{"type":"object","properties":{"status":{"type":"string","example":"ok"},"service":{"type":"string","example":"data-api"},"version":{"type":"string","example":"v1"},"uptime":{"type":"number","example":12345.67},"timestamp":{"type":"string","format":"date-time"}}},"ValidationError":{"type":"object","properties":{"error":{"type":"string","example":"Validation failed"},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"array","items":{}},"message":{"type":"string"},"code":{"type":"string"}}}}},"required":["error"]},"AuthError":{"type":"object","properties":{"error":{"type":"string","example":"API key required"},"message":{"type":"string","example":"Provide an API key via Authorization: Bearer oas_live_... or X-API-Key header"}},"required":["error"]},"ScopeError":{"type":"object","properties":{"error":{"type":"string","example":"Insufficient API key scope"},"requiredScope":{"type":"string","enum":["compute","data","streaming"]}},"required":["error"]},"RateLimitError":{"type":"object","properties":{"error":{"type":"string","example":"Rate limit exceeded"},"limit":{"type":"number","example":120},"retryAfter":{"type":"number","description":"Seconds until rate limit resets","example":42}},"required":["error","limit"]},"CalibrationQuotaError":{"type":"object","description":"Returned by /v1/compute/calibrate when the user exceeds the per-day calibration cap. Separate from the general rate limit — calibrations are hard-capped because each run can consume 5-60 seconds of CPU.","properties":{"error":{"type":"string","example":"Daily calibration quota exceeded"},"code":{"type":"string","example":"CALIBRATION_QUOTA_EXCEEDED"},"scope":{"type":"string","enum":["day"],"description":"Which quota window was exceeded"},"limit":{"type":"number","description":"Hard cap for the scope (500 per day)"},"used":{"type":"number","description":"Number of successful calibrations the user has made in the scope window"},"resetsAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp when the quota window resets (UTC)"}},"required":["error","code","scope","limit","used","resetsAt"]},"NotFoundError":{"type":"object","properties":{"error":{"type":"string","example":"No data found for this symbol"}},"required":["error"]},"InternalError":{"type":"object","properties":{"error":{"type":"string","example":"Internal server error"}},"required":["error"]},"ServiceUnavailableError":{"type":"object","properties":{"error":{"type":"string","example":"Worker pool draining; service unavailable"},"code":{"type":"string","example":"WORKER_POOL_UNAVAILABLE"}},"required":["error"]}},"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","bearerFormat":"oas_live_...","description":"API key authentication. Pass via `Authorization: Bearer oas_live_...` or `X-API-Key` header."},"ApiKeyHeader":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Alternative: pass API key via `X-API-Key` header instead of `Authorization`."}}},"security":[{"ApiKeyAuth":[]},{"ApiKeyHeader":[]}]}