Volatility
IV metrics, the term structure, the backwardation summary, and call/put skew.
Symbol-level IV regime, the per-expiry IVx curve, the largest weekly and monthly IVx fall, and call/put skew per expiry.
These lists do not carry a price. IV rank 0 is kept. An IVx average of 0, an IVx 5-day change of 99, and a zero skew ratio are null. A synthetic copies the mapped symbol and is not scaled.
term-structure is the IV curve: per expiry ivx (in percent) and the weekly and monthly backwardation blocks with vs_expiration_date, vs_ivx, change_pct, and strength from 0 to 1. Weekly compares the previous listed expiry. Monthly compares the previous monthly and is null on a non-monthly row. backwardation-summary is one row per symbol with the largest fall between neighbouring expiries whose front DTE is above 5, or null. call-put-skew is per expiry, with is_optimal on the generator’s optimal expiry. A fall is always a negative change_pct, rounded to 4 decimal places. On per-expiry rows snapshot_at is when that expiry’s chain row was updated, or null when the source has no time.
Lists IV rank, IV percentile, average IVx, the 5-day IVx change, and the liquidity rating. The MCP tool is list_volatility_iv_metrics. The arguments are this same JSON body. The bearer token stays on the HTTP header.
Parameters · IV metrics
| Name | Type | Required | Values |
|---|---|---|---|
symbols | array of strings | No | Up to 300 tickers. Unknown names are left out. Order in the response is symbol ascending. |
cursor | string | No | Previous meta.next_cursor. Omit it on the first page. |
Page size is fixed at 400 rows. The caller does not set it. The response cache refreshes in 180 seconds (rc_ttl).
Valid bodies, from the minimal to the one the sample answers:
{}{"symbols":["SPX"]}
curl --compressed \ --request POST \ --url "${TANUKI_BASE_URL}/api/v1/volatility/iv-metrics" \ --header "Authorization: Bearer 12345.YOUR_API_KEY" \ --header "Content-Type: application/json" \ --header "Accept: application/json" \ --data '{"symbols":["SPX"]}'
Live builder output for the request in this file. The row list was short enough to keep. built_at is the builder health clock of this capture.
{ "ok": true, "data": { "items": [ { "symbol": "SPX", "type": "INDEX", "is_synthetic": false, "mapped_from": null, "snapshot_type": "latest", "snapshot_at": "2026-10-21T16:01:44.000-04:00", "liquidity_rating": 5, "iv_rank": 35.11, "iv_percentile": 32.4696, "ivx_avg": 16.85, "ivx_5d_change_pct": -2.8 } ] }, "meta": { "request": { "symbols": [ "SPX" ] }, "count": 1, "total": 1, "page": 1, "page_count": 1, "next_cursor": null, "generation": "dd5e362e22d5", "as_of": {}, "built_at": "2026-10-23T01:08:02-04:00", "omitted": [], "docs": { "reference": "https://tanukitrade.com/docs/api/volatility#list_volatility_iv_metrics", "glossary": "https://tanukitrade.com/docs/api/glossary" } } }
Response fields · IV metrics
| Field | Type | Meaning |
|---|---|---|
symbol | string | Canonical ticker. Copy it from list_symbols. Letter case folds to uppercase. |
type | string | STOCK, ETF, INDEX, FUTURES, or CFD_CRYPTO. |
is_synthetic | boolean | True when the ticker is mapped from another symbol. False is a listed underlying. |
mapped_from | string or null | The symbol a synthetic is mapped from. Null on a listed underlying. A micro names the optionable base, not its parent future. |
snapshot_type | string | latest on a current row. history on a stored day. |
snapshot_at | datetime ET or null | When the source row was captured. ISO 8601 with an ET offset, to milliseconds. |
liquidity_rating | integer or null | Clamped to 0–5. 5 only for the five-star set. |
iv_rank | number or null | IV rank. 0 is a real value. Rounded to 4 decimal places. |
iv_percentile | number or null | IV percentile. Rounded to 4 decimal places. |
ivx_avg | number or null | symbol IVx average, annualized volatility in percent, no unit suffix. 0 is stored as null. Rounded to 4 decimal places. |
ivx_5d_change_pct | number or null | Five-day IVx change in percent, rounded to 4 decimal places. 99 is stored as null. |
Errors on this route · IV metrics
| HTTP | Code | When |
|---|---|---|
422 | VALIDATION_ERROR | Unknown field, nested value, repeated key, bad JSON, a bad alias, or a cursor that does not match this request. |
413 | PAYLOAD_TOO_LARGE | The JSON body is larger than 4 KiB. |
503 | DATA_WARMING | The datapoint is not built yet. Wait Retry-After seconds (1). |
422 | RESULT_TOO_LARGE | The uncompressed JSON would exceed 512 KiB. Narrow the filter. |
Auth, rate limit, and the other shared failures are on Errors.
Lists per-expiry IVx and the weekly and monthly backwardation blocks on the discovery expiry frame. The MCP tool is list_volatility_term_structure. The arguments are this same JSON body. The bearer token stays on the HTTP header.
Parameters · Term structure
One of Required: at least one of symbol or expiry. Sending both is fine.
| Name | Type | Required | Values |
|---|---|---|---|
symbol | string | One of | One ticker. Letter case folds to uppercase. |
expiry | string | One of | YYYY-MM-DD, or an alias 0, 1, w1–w4, M1–M3, ALL. Alias case folds onto that canonical form. |
cursor | string | No | Previous meta.next_cursor. Omit it on the first page. |
Page size is fixed at 400 rows. The caller does not set it. The response cache refreshes in 180 seconds (rc_ttl).
Valid bodies, from the minimal to the one the sample answers:
{"symbol":"SPX"}{"expiry":"w1"}{"symbol":"SPX","expiry":"w1"}
curl --compressed \ --request POST \ --url "${TANUKI_BASE_URL}/api/v1/volatility/term-structure" \ --header "Authorization: Bearer 12345.YOUR_API_KEY" \ --header "Content-Type: application/json" \ --header "Accept: application/json" \ --data '{"symbol":"SPX","expiry":"w1"}'
Live builder output for the request in this file. The row list was short enough to keep. built_at is the builder health clock of this capture.
{ "ok": true, "data": { "items": [ { "symbol": "SPX", "is_synthetic": false, "mapped_from": null, "expiration_date": "2026-10-23", "dte": 0, "aliases": [ "0", "w1" ], "is_monthly": false, "snapshot_type": "latest", "snapshot_at": "2026-10-21T16:01:44.000-04:00", "ivx": 14.255, "backwardation": { "weekly": null, "monthly": null } } ] }, "meta": { "request": { "symbol": "SPX", "expiry": "w1" }, "count": 1, "total": 1, "page": 1, "page_count": 1, "next_cursor": null, "generation": "934247a0818e.dd5e362e22d5", "as_of": {}, "built_at": "2026-10-23T01:08:02-04:00", "omitted": [], "docs": { "reference": "https://tanukitrade.com/docs/api/volatility#list_volatility_term_structure", "glossary": "https://tanukitrade.com/docs/api/glossary" } } }
Response fields · Term structure
| Field | Type | Meaning |
|---|---|---|
symbol | string | Canonical ticker. Copy it from list_symbols. Letter case folds to uppercase. |
is_synthetic | boolean | True when the ticker is mapped from another symbol. False is a listed underlying. |
mapped_from | string or null | The symbol a synthetic is mapped from. Null on a listed underlying. A micro names the optionable base, not its parent future. |
expiration_date | date | Calendar expiry, YYYY-MM-DD, ET. |
dte | integer | Days to that expiry, as stored for the row. |
aliases | array of strings | 0, 1, w1–w4, M1–M3, ALL. Weekly aliases use a lowercase w. Monthly aliases and ALL stay uppercase. |
is_monthly | boolean | True on the monthly expiry date. Same rule as discovery expiries. |
snapshot_type | string | Always latest on this route. |
snapshot_at | datetime ET or null | When this expiry's chain row was updated, ISO 8601 with an ET offset, or null when the source has no time. |
ivx | number or null | IVx of this expiry, in percent. Rounded to 4 decimal places. |
backwardation | object | weekly compares the previous listed expiry. monthly compares the previous monthly and is null on a non-monthly row. change_pct is negative. strength is 0 to 1 against the largest fall on the symbol, before the expiry filter. |
Errors on this route · Term structure
| HTTP | Code | When |
|---|---|---|
422 | VALIDATION_ERROR | Unknown field, nested value, repeated key, bad JSON, a bad alias, or a cursor that does not match this request. |
413 | PAYLOAD_TOO_LARGE | The JSON body is larger than 4 KiB. |
503 | DATA_WARMING | The datapoint is not built yet. Wait Retry-After seconds (1). |
422 | RESULT_TOO_LARGE | The uncompressed JSON would exceed 512 KiB. Narrow the filter. |
422 | UNKNOWN_SYMBOL | Required symbol is not in the universe. |
422 | UNKNOWN_EXPIRY | Expiry does not resolve for that symbol. details lists up to 20 available dates. Expiry alone, with no symbol, is an empty 200 instead. |
Auth, rate limit, and the other shared failures are on Errors.
Lists each symbol's largest weekly and monthly IVx fall from the chain, counting a pair only when the front DTE is greater than 5. The MCP tool is list_volatility_backwardation_summary. The arguments are this same JSON body. The bearer token stays on the HTTP header.
Parameters · Backwardation summary
| Name | Type | Required | Values |
|---|---|---|---|
symbols | array of strings | No | Up to 300 tickers. Unknown names are left out. Order in the response is symbol ascending. |
cursor | string | No | Previous meta.next_cursor. Omit it on the first page. |
Page size is fixed at 400 rows. The caller does not set it. The response cache refreshes in 180 seconds (rc_ttl).
Valid bodies, from the minimal to the one the sample answers:
{}{"symbols":["SPX"]}
curl --compressed \ --request POST \ --url "${TANUKI_BASE_URL}/api/v1/volatility/backwardation-summary" \ --header "Authorization: Bearer 12345.YOUR_API_KEY" \ --header "Content-Type: application/json" \ --header "Accept: application/json" \ --data '{"symbols":["SPX"]}'
Live builder output for the request in this file. The row list was short enough to keep. built_at is the builder health clock of this capture.
{ "ok": true, "data": { "items": [ { "symbol": "SPX", "type": "INDEX", "is_synthetic": false, "mapped_from": null, "snapshot_type": "latest", "snapshot_at": "2026-10-21T16:01:44.000-04:00", "weekly": { "front_expiration_date": "2026-10-30", "front_dte": 7, "front_ivx": 15.596, "back_expiration_date": "2026-11-02", "back_dte": 10, "back_ivx": 14.5698, "change_pct": -6.5799 }, "monthly": { "front_expiration_date": "2030-12-20", "front_dte": 1519, "front_ivx": 22.2395, "back_expiration_date": "2031-12-19", "back_dte": 1883, "back_ivx": 20.9891, "change_pct": -5.6224 } } ] }, "meta": { "request": { "symbols": [ "SPX" ] }, "count": 1, "total": 1, "page": 1, "page_count": 1, "next_cursor": null, "generation": "dd5e362e22d5", "as_of": {}, "built_at": "2026-10-23T01:08:02-04:00", "omitted": [], "docs": { "reference": "https://tanukitrade.com/docs/api/volatility#list_volatility_backwardation_summary", "glossary": "https://tanukitrade.com/docs/api/glossary" } } }
Response fields · Backwardation summary
| Field | Type | Meaning |
|---|---|---|
symbol | string | Canonical ticker. Copy it from list_symbols. Letter case folds to uppercase. |
type | string | STOCK, ETF, INDEX, FUTURES, or CFD_CRYPTO. |
is_synthetic | boolean | True when the ticker is mapped from another symbol. False is a listed underlying. |
mapped_from | string or null | The symbol a synthetic is mapped from. Null on a listed underlying. A micro names the optionable base, not its parent future. |
snapshot_type | string | latest on a current row. history on a stored day. |
snapshot_at | datetime ET or null | When the symbol's volatility row was built, ISO 8601 with an ET offset. The IVx pair comes from the chain of the same build. |
weekly | object or null | Largest fall between neighbouring listed expiries with front DTE greater than 5. front_expiration_date, front_dte, front_ivx, back_expiration_date, back_dte, back_ivx, change_pct. Null when there is no fall. |
monthly | object or null | Same shape as weekly, between neighbouring monthly expiries, or null. |
Errors on this route · Backwardation summary
| HTTP | Code | When |
|---|---|---|
422 | VALIDATION_ERROR | Unknown field, nested value, repeated key, bad JSON, a bad alias, or a cursor that does not match this request. |
413 | PAYLOAD_TOO_LARGE | The JSON body is larger than 4 KiB. |
503 | DATA_WARMING | The datapoint is not built yet. Wait Retry-After seconds (1). |
422 | RESULT_TOO_LARGE | The uncompressed JSON would exceed 512 KiB. Narrow the filter. |
Auth, rate limit, and the other shared failures are on Errors.
Lists per-expiry call/put skew and whether that expiry is the generator's optimal expiry. The MCP tool is list_volatility_call_put_skew. The arguments are this same JSON body. The bearer token stays on the HTTP header.
Parameters · Call/put skew
One of Required: at least one of symbol or expiry. Sending both is fine.
| Name | Type | Required | Values |
|---|---|---|---|
symbol | string | One of | One ticker. Letter case folds to uppercase. |
expiry | string | One of | YYYY-MM-DD, or an alias 0, 1, w1–w4, M1–M3, ALL. Alias case folds onto that canonical form. |
cursor | string | No | Previous meta.next_cursor. Omit it on the first page. |
Page size is fixed at 400 rows. The caller does not set it. The response cache refreshes in 180 seconds (rc_ttl).
Valid bodies, from the minimal to the one the sample answers:
{"symbol":"SPX"}{"expiry":"M1"}{"symbol":"SPX","expiry":"M1"}
curl --compressed \ --request POST \ --url "${TANUKI_BASE_URL}/api/v1/volatility/call-put-skew" \ --header "Authorization: Bearer 12345.YOUR_API_KEY" \ --header "Content-Type: application/json" \ --header "Accept: application/json" \ --data '{"symbol":"SPX","expiry":"M1"}'
Live builder output for the request in this file. The row list was short enough to keep. built_at is the builder health clock of this capture.
{ "ok": true, "data": { "items": [ { "symbol": "SPX", "is_synthetic": false, "mapped_from": null, "expiration_date": "2026-11-20", "dte": 28, "aliases": [ "M1" ], "is_monthly": true, "snapshot_type": "latest", "snapshot_at": "2026-10-21T16:01:44.000-04:00", "call_put_skew": -54.47, "is_optimal": false } ] }, "meta": { "request": { "symbol": "SPX", "expiry": "M1" }, "count": 1, "total": 1, "page": 1, "page_count": 1, "next_cursor": null, "generation": "934247a0818e.dd5e362e22d5", "as_of": {}, "built_at": "2026-10-23T01:08:02-04:00", "omitted": [], "docs": { "reference": "https://tanukitrade.com/docs/api/volatility#list_volatility_call_put_skew", "glossary": "https://tanukitrade.com/docs/api/glossary" } } }
Response fields · Call/put skew
| Field | Type | Meaning |
|---|---|---|
symbol | string | Canonical ticker. Copy it from list_symbols. Letter case folds to uppercase. |
is_synthetic | boolean | True when the ticker is mapped from another symbol. False is a listed underlying. |
mapped_from | string or null | The symbol a synthetic is mapped from. Null on a listed underlying. A micro names the optionable base, not its parent future. |
expiration_date | date | Calendar expiry, YYYY-MM-DD, ET. |
dte | integer | Days to that expiry, as stored for the row. |
aliases | array of strings | 0, 1, w1–w4, M1–M3, ALL. Weekly aliases use a lowercase w. Monthly aliases and ALL stay uppercase. |
is_monthly | boolean | True on the monthly expiry date. Same rule as discovery expiries. |
snapshot_type | string | Always latest on this route. |
snapshot_at | datetime ET or null | When this expiry's chain row was updated, ISO 8601 with an ET offset, or null when the source has no time. |
call_put_skew | number or null | Call/put skew ratio of this expiry times 100. A zero ratio is null. Rounded to 4 decimal places. |
is_optimal | boolean | True on the generator's optimal expiry (the session date plus its optimal DTE) while that date is still listed. Otherwise false. |
Errors on this route · Call/put skew
| HTTP | Code | When |
|---|---|---|
422 | VALIDATION_ERROR | Unknown field, nested value, repeated key, bad JSON, a bad alias, or a cursor that does not match this request. |
413 | PAYLOAD_TOO_LARGE | The JSON body is larger than 4 KiB. |
503 | DATA_WARMING | The datapoint is not built yet. Wait Retry-After seconds (1). |
422 | RESULT_TOO_LARGE | The uncompressed JSON would exceed 512 KiB. Narrow the filter. |
422 | UNKNOWN_SYMBOL | Required symbol is not in the universe. |
422 | UNKNOWN_EXPIRY | Expiry does not resolve for that symbol. details lists up to 20 available dates. Expiry alone, with no symbol, is an empty 200 instead. |
Auth, rate limit, and the other shared failures are on Errors.
TanukiTrade API and MCP. Derived options analytics for your code and for agents. Not investment advice. tanukitrade.com