Crunching numbers. Please wait...

Trading Volatility API v2

Our version 2 API is built for AI-native development and LLM agents. This is not a traditional market data feed.

Most financial APIs expose raw quotes, trades, and loosely structured analytics. Trading Volatility exposes derived market structure — deterministic, schema-defined intelligence designed for machine reasoning.

  • Derived structure, not raw feeds — gamma support/resistance, flip levels, structural bands
  • Options-specific regime intelligence — positioning context, skew diagnostics, call pressure
  • Deterministic interpretation layers — structured summaries with defined semantics
  • Agent-readable schemas — explicit fields, predictable outputs, no ambiguity
  • Built for AI-led workflows — designed for Claude and other LLM agents

Instead of forcing agents to reverse-engineer meaning from unstructured fields, this API delivers structured financial intelligence ready for reasoning systems.

For v1 docs, see /api/v1/docs

Demo mode is available below, but to use the full API you need to subscribe to a plan and get an API key.

LLM / Agent Instructions

Claude (and other LLM agents) can automatically learn what this API offers (endpoints, parameters, and response schemas). Just provide them with the following link (or copy/paste the spec contents) which contains our agent-readable spec:

https://stocks.tradingvolatility.net/api/v2/llm-spec

Authentication

Paste your API key. We'll send Authorization: Bearer <key>.

Your personal API key is available once you subscribe

Core Endpoints

GET /api/v2/tickers/<ticker>

Compact metrics snapshot from our database.
`trade_recommendation` is excluded unless `trade_recommendation=true` is supplied.

GET /api/v2/tickers/<ticker>/market-structure

AI-generated market structure analysis including headline signal, regime classification, expected behavior, key levels, and supporting metrics. Designed for agent-led workflows and trading dashboards.

GET /api/v2/tickers/<ticker>/explain

State + deterministic interpretation scaffold.

GET /api/v2/tickers/<ticker>/series

Downsampled daily series (latest per day). Combine multiple metrics via comma-separated keys.

Available metrics (loaded from /api/v2/llm-spec)
Click a metric to add it to the metrics input.
GET /api/v2/tickers/<ticker>/curves/gex_by_strike

Net GEX strike curve with call/put contributions. Best for finding key strikes (peaks/valleys), call-vs-put dominance, and mapping GEX zones around price.

GET /api/v2/tickers/<ticker>/curves/gamma

Gamma strike curve (net gamma per strike). Supports per-expiration data pulls during market hours.

GET /api/v2/tickers/<ticker>/curves/gamma/expirations

Strike-aligned gamma decomposition by expiration bucket. Each strike includes nearest, first_weekly, first_monthly, and all_other_expiries, which together reconcile to combined.

GET /api/v2/tickers/<ticker>/levels

Levels in JSON or plain text (TradingView/TOS).

GET /api/v2/tickers/<ticker>/options/volume

Real-time-ish options volume aggregated by strike for a specific expiration (exp required).

Note: requires exp and uses extra per-endpoint rate limiting.

GET /api/v2/agent/trade-setup/<ticker>

[ BETA ] Compact agent-oriented payload: latest snapshot's key market-state fields plus the deterministic trade recommendation projections (regime, tier, trade type, direction, opportunity score). Read-only; no re-interpretation.

GET /api/v2/top-setups

Cross-ticker ranking of the most recent TickerSnapshot per ticker (within the last 36h), sorted by opportunity_score desc. Each item carries the full deterministic trade_setup blob. Filterable on 9 attributes; sort is fixed.

Query parameters

limit                    int,   default 20, range 1-200
min_score                float, default 0.0, range 0-10
regime                   CSV of RegimeLabel (IN)        
recommended_direction    CSV of long|short|neutral (IN)
trade_bias               CSV of string (IN)
trend_state              CSV of string (IN)
momentum_state           CSV of string (IN)
extension_state          CSV of string (IN)
realized_vol_state       CSV of string (IN)
price_min / price_max                float, inclusive
iv_rank_min / iv_rank_max            float, 0-100 inclusive
ivAtMaxDelta_min / ivAtMaxDelta_max  float, inclusive
ttl                      int,   cache TTL seconds, 0-1800 (default 900)

Unknown params are ignored. Empty strings are treated as unset. All supplied filters are AND'd together. Responses ship with ETag and Cache-Control: private, max-age=<ttl>, stale-while-revalidate=30; clients may send If-None-Match for a 304.

Curl

curl -H "Authorization: Bearer $TV_API_KEY" \
  "https://stocks.tradingvolatility.net/api/v2/top-setups?limit=20®ime=trending_low_vol,range_bound&recommended_direction=long&price_min=20&iv_rank_min=30&iv_rank_max=80"

Errors: 401 (missing/invalid token), 304 (conditional GET match), 500 (upstream failure).

GET /api/v2/top-setups/screener/<name>

Named screener presets over the same ranking as /top-setups. Each preset encodes a thesis-specific filter combination from docs/screener_spec.md (v1.0 / 2026-04-17). Query params on the request override preset values per-key, so you can tweak limit, min_score, or any filter without losing the rest of the preset.

Presets

momentum_breakout       Clean aligned uptrend, fresh momentum, not extended
capitulation_reversal   Panic flush with exhausting downside + bloated IV
range_premium_seller    Sideways chop, neutral extension, elevated IV
trend_pullback          Intact uptrend with short-term pullback*
highvol_breakdown       Fresh aligned breakdown with room to fall*

* trend_alignment_state=aligned is deferred (not yet an API filter);
  v1 results for these two screeners are noisier than the spec's
  refined version. See docs/screener_build_plan.md.

Exact URLs per preset

GET /api/v2/top-setups/screener/momentum_breakout
    equivalent: /api/v2/top-setups?regime=trending_low_vol
                &recommended_direction=long&trend_state=up
                &momentum_state=strong,improving&extension_state=neutral
                &realized_vol_state=subdued,contracting
                &iv_rank_max=40&price_min=20&min_score=7.0

GET /api/v2/top-setups/screener/capitulation_reversal
    equivalent: /api/v2/top-setups?regime=flush_panic,trending_down_high_vol
                &extension_state=oversold
                &realized_vol_state=expanding,elevated
                &momentum_state=fading&recommended_direction=long
                &iv_rank_min=60&min_score=5.0

GET /api/v2/top-setups/screener/range_premium_seller
    equivalent: /api/v2/top-setups?regime=range_bound
                &trend_state=sideways&extension_state=neutral
                &recommended_direction=neutral
                &iv_rank_min=50&price_min=25&min_score=4.0

GET /api/v2/top-setups/screener/trend_pullback
    equivalent: /api/v2/top-setups?trend_state=up&momentum_state=fading
                &extension_state=oversold
                &realized_vol_state=subdued,contracting
                &recommended_direction=long
                &iv_rank_min=30&min_score=5.0

GET /api/v2/top-setups/screener/highvol_breakdown
    equivalent: /api/v2/top-setups
                ?regime=trending_down_low_vol,trending_down_high_vol
                &trend_state=down&momentum_state=strong,improving
                &extension_state=neutral&recommended_direction=short
                &iv_rank_min=30&min_score=6.0

Response shape is identical to /top-setups, with an extra meta.extra.screener field naming the preset. Unknown preset names return 404 with an available list.

Code Example

Python Example

Fetch the gamma curve for a ticker and inspect the strike points returned by the API.

import os
import requests

API_BASE = "https://stocks.tradingvolatility.net"
API_KEY = os.environ["TV_API_KEY"]

ticker = "SPY"
url = f"{API_BASE}/api/v2/tickers/{ticker}/curves/gamma"
params = {"exp": "combined"}
headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Accept": "application/json",
}

resp = requests.get(url, params=params, headers=headers, timeout=20)
resp.raise_for_status()

payload = resp.json()
print(payload["meta"]["ticker"])
print(payload["data"]["expiry"])
print(payload["data"]["points"][0])