# Orange Hitick 波动率数据 Skill 文档

这份文档用于开发者手动接入，或让 Agent 按统一规则接入 Orange Hitick 的波动率数据服务。

## 1. 服务信息

- 平台接口前缀：`/api/v1/vol-data`
- 鉴权方式：请求头 `X-API-Token`
- 返回包装：Orange Hitick 统一 `ApiResponse`
- 当前服务编码：`vol_data`
- 当前服务名称：`波动率数据`
- 计费说明：`/groups` 不计费；`/query/*`、`/snapshot/*`、`/ts/*`、`/gex/*`、`/gex-image/*` 成功返回后计费，扣费失败则接口直接返回错误

平台统一返回结构：

```json
{
  "code": 0,
  "message": "success",
  "data": {}
}
```

说明：

- `code = 0` 表示平台调用成功
- 真正的波动率数据结果放在 `data` 中
- `data` 是上游接口返回结果的透传 JSON

## 2. 鉴权

所有请求都必须带：

```http
X-API-Token: your_token_value
```

为减少大 JSON 的传输量，HTTP 客户端可发送 `Accept-Encoding: gzip`。服务端协商压缩后返回 `Content-Encoding: gzip`，客户端应解压后再解析 JSON；例如 `curl --compressed` 会自动完成协商和解压。不声明支持 gzip 时仍返回原文，返回结构和查询范围限制不变。

## 3. 接口能力总览

本服务可以提供 6 大类数据能力：

1. 分组目录：可查询哪些 `(underlying, expire_date, multiplier)` 组合当前可用
2. 实时快照：可查询标的报价、ATM 隐波、期权链、Greeks、盘口隐波、卖方保证金
3. 历史小时快照：可查询本地落库的 T 型报价小时快照
4. 时序数据：可查询某一时间区间内的 `atm_iv` 与标的价格走势
5. GEX 曲线与 GEX 小时快照：可查询 Gamma Exposure 分布、当前净 GEX、零 gamma 位置，并可回看本地落库的小时 GEX 快照
6. Agent / MCP 接入：先用 `orange_resolve_subject` 解析标的，实时快照统一使用 `by_underlying`，并支持 `snapshot_*`、`ts_*`、`gex_*` 标准化动作

建议使用顺序：

1. Agent 中先用 `orange_resolve_subject` 把中文品种名、代码前缀或不完整合约解析成标准三元组
2. 查询实时快照时优先使用 `query/*`
3. 查询历史整点快照时使用 `snapshot/*`
4. 查询波动率走势时使用 `ts/*`
5. 查询 Gamma Exposure 分布时使用 `gex/*`
6. 查询历史整点 GEX 结构时使用 `gex/snapshot/*`

REST 的 `/groups` 接口仍保持不变，供原有 HTTP 客户端使用；Raw MCP 不公开全量分组 action。

## 4. 接口列表与请求参数

### 4.1 获取缓存分组

```http
GET /api/v1/vol-data/groups
```

用途：

- 返回当前可查询的 `(underlying, expire_date, multiplier)` 组合
- 适合在已知标的代码后，进一步确认有哪些到期日和合约乘数可查
- 不扣费

请求参数：

- 无 query 参数

示例：

```bash
curl -sS 'https://api.hitick.top/api/v1/vol-data/groups' \
  -H 'X-API-Token: your_token_value'
```

返回核心结构：

```json
{
  "groups": [
    {
      "underlying": "au2607",
      "expire_date": "20260624",
      "multiplier": 1000
    }
  ]
}
```

字段说明：

- `groups[].underlying`：标的代码
- `groups[].expire_date`：到期日，格式 `yyyyMMdd`
- `groups[].multiplier`：合约乘数

### 4.2 实时快照接口

实时快照接口用于查询某个标的分组下的完整 T 型报价快照，包含：

- 标的最新报价
- 当前 ATM 隐含波动率
- 隐含波动率偏度（`iv_skew`）
- PCR 指标（`oi_pcr`、`volume_pcr`）
- 行权价维度的期权链
- Call / Put 双边 Greeks
- 理论隐波、盘口隐波
- 卖方参考保证金

#### 4.2.1 按标的查询

```http
GET /api/v1/vol-data/query/by-underlying?underlying=au2607
```

必填参数：

- `underlying`：标的代码，例如 `au2607`

可选参数：

- `expire`：到期日，格式 `yyyyMMdd`
- `multiplier`：合约乘数，例如 `1000`

适用场景：

- 只知道标的代码，想拿当前默认分组的实时快照
- 若同时传 `expire` / `multiplier`，上游会按更具体的分组筛选

#### 4.2.2 按到期日查询

```http
GET /api/v1/vol-data/query/by-expire?underlying=au2607&expire=20260624
```

必填参数：

- `underlying`：标的代码，例如 `au2607`

建议参数：

- `expire`：到期日，格式 `yyyyMMdd`

可选参数：

- `multiplier`：合约乘数，例如 `1000`

适用场景：

- 已明确目标到期日，希望获取该到期日下的实时快照

#### 4.2.3 按乘数查询

```http
GET /api/v1/vol-data/query/by-multiplier?underlying=au2607&expire=20260624&multiplier=1000
```

必填参数：

- `underlying`：标的代码，例如 `au2607`

建议参数：

- `expire`：到期日，格式 `yyyyMMdd`
- `multiplier`：合约乘数，例如 `1000`

适用场景：

- 已明确完整分组，想精确锁定某一条可交易链

### 4.2.4 历史小时快照查询

```http
GET /api/v1/vol-data/snapshot/by-underlying?underlying=au2607&snapshotTime=1781062200000
```

用途：

- 查询本地数据库中某个小时档位的历史 T 型快照
- 返回结构与实时快照 `GET /api/v1/vol-data/query/by-multiplier` 基本一致
- 适合回看某个历史时点的 `atm_iv`、`iv_skew`、PCR、标的报价、期权链、Greeks 和盘口隐波

必填参数：

- `underlying`：标的代码，例如 `au2607`
- `snapshotTime`：目标时间戳，毫秒；也可传 `last`，表示查询当前分组在数据库中最新的一条快照，主要用于非开盘时段获取上次收盘时的快照

可选参数：

- `expire`：到期日，格式 `yyyyMMdd`
- `multiplier`：合约乘数，例如 `1000`

参数规则：

- 当未传 `expire` 时，默认选择该 `underlying` 的最近月
- 当未传 `multiplier` 时，默认选择该月下最小乘数
- `snapshotTime` 传毫秒时间戳时会先向下取整到整点，再查询对应小时快照
- `snapshotTime=last` 时不做时间取整，直接按当前分组查询数据库中 `snapshot_hour_ms` 最大的一条记录；主要使用场景是在非开盘时段获取上次收盘时的快照

示例：

```bash
curl -sS 'https://api.hitick.top/api/v1/vol-data/snapshot/by-underlying?underlying=au2607&snapshotTime=1781062200000' \
  -H 'X-API-Token: your_token_value'
```

返回核心结构：

```json
{
  "found": true,
  "query_type": "snapshot_by_underlying",
  "underlying": "au2607",
  "expire_date": "20260624",
  "multiplier": 1000,
  "atm_iv": 0.1852,
  "iv_skew": -0.0174,
  "oi_pcr": 1.2389,
  "volume_pcr": 0.8123,
  "data_time_ms": 1781062200000,
  "underlying_quote": {
    "symbol": "au2607",
    "last_price": 812.34
  },
  "rows": [
    {
      "strike": 800,
      "call": {
        "symbol": "au2607-C-800",
        "delta": 0.54,
        "gamma": 0.0012,
        "vega": 0.0831,
        "theta": -0.0245,
        "theo_vol": 0.1841,
        "implied_vol": 0.1863
      },
      "put": {
        "symbol": "au2607-P-800",
        "delta": -0.46,
        "gamma": 0.0011,
        "vega": 0.0818,
        "theta": -0.0229,
        "theo_vol": 0.1874,
        "implied_vol": 0.1889
      }
    }
  ]
}
```

字段说明：

- `found`：是否命中该历史快照
- `query_type`：固定为 `snapshot_by_underlying`
- `underlying`：标的代码
- `expire_date`：实际命中的到期日，格式 `yyyyMMdd`
- `multiplier`：实际命中的合约乘数
- `atm_iv`：该小时快照的 ATM 隐含波动率，小数表示
- `iv_skew`：该小时快照的隐含波动率偏度
- `oi_pcr`：按 `put.open_interest / call.open_interest` 聚合得到的持仓量 PCR
- `volume_pcr`：按 `put.volume / call.volume` 聚合得到的成交量 PCR
- `data_time_ms`：快照所属整点时间，毫秒
- `underlying_quote.last_price`：该时点标的最新价
- `rows[]`：该时点期权链，结构与实时 `query/*` 返回一致

说明：

- 如果 `found = false`，表示该分组在对应整点没有可用历史快照
- `rows[].call` / `rows[].put` 下的 Greeks、理论隐波、盘口隐波字段与实时接口一致
- PCR 口径与实时快照一致：
  - `oi_pcr = sum(put.open_interest) / sum(call.open_interest)`
  - `volume_pcr = sum(put.volume) / sum(call.volume)`
  - 缺失 `open_interest` 或 `volume` 按 `0` 处理
  - 当 call 侧分母为 `0` 时，返回 `NaN`
- `atm_iv`、`theo_vol`、`implied_vol` 等隐波字段均为小数，不是百分比

### 4.3 时间序列接口

时间序列接口用于查询某个时间区间内的 ATM 隐波、隐含波动率偏度和标的价格时序。

三个 `/ts/*` 接口统一限制单次查询跨度最多 **24 小时（86400000 毫秒）**：

- `start`、`end` 必填。正数为绝对 Unix 毫秒时间戳；非正数为相对该分组最新有效数据时间的毫秒偏移，`0` 表示最新数据，并非服务器当前时间。
- 绝对、相对及混合写法均按解析后的时间校验：`0 <= end - start <= 86400000`。恰好 24 小时允许，超过 24 小时直接报错，不自动截断。
- `start=-86400000&end=0` 查询最新 24 小时；原相对查询自动裁剪到 12 小时的行为已取消。
- 超限请求不扣查询费用。沿用业务错误格式：HTTP 状态码为 `200`，客户端必须检查 `code`，并展示 `message`。请缩小时间范围后再请求，不要原样重试。

超限返回示例：

```json
{
  "code": 1001,
  "message": "时序查询时间范围不能超过 24 小时（86400000 毫秒），请缩小 start/end 时间范围后重试。",
  "data": null
}
```

返回重点：

- `timestamp_ms`
- `underlying_last_price`
- `atm_iv`
- `iv_skew`

#### 4.3.1 按标的查询时序

```http
GET /api/v1/vol-data/ts/by-underlying?underlying=au2607&start=1781062200000&end=1781062300000
```

必填参数：

- `underlying`：标的代码，例如 `au2607`
- `start`：起始时间戳，毫秒
- `end`：结束时间戳，毫秒

可选参数：

- `expire`：到期日，格式 `yyyyMMdd`
- `multiplier`：合约乘数，例如 `1000`

#### 4.3.2 按到期日查询时序

```http
GET /api/v1/vol-data/ts/by-expire?underlying=au2607&expire=20260624&start=1781062200000&end=1781062300000
```

必填参数：

- `underlying`：标的代码，例如 `au2607`
- `start`：起始时间戳，毫秒
- `end`：结束时间戳，毫秒

建议参数：

- `expire`：到期日，格式 `yyyyMMdd`

可选参数：

- `multiplier`：合约乘数，例如 `1000`

#### 4.3.3 按乘数查询时序

```http
GET /api/v1/vol-data/ts/by-multiplier?underlying=au2607&expire=20260624&multiplier=1000&start=1781062200000&end=1781062300000
```

必填参数：

- `underlying`：标的代码，例如 `au2607`
- `start`：起始时间戳，毫秒
- `end`：结束时间戳，毫秒

建议参数：

- `expire`：到期日，格式 `yyyyMMdd`
- `multiplier`：合约乘数，例如 `1000`

### 4.4 GEX 曲线接口

GEX 接口用于查询 Gamma Exposure 扫描结果，适合分析：

- 当前净 GEX 是正还是负
- 价格上移 / 下移后净 GEX 如何变化
- 零 gamma 位置在哪里
- 当前价附近是否存在 GEX 翻转区

#### 4.4.1 按标的查询 GEX

```http
GET /api/v1/vol-data/gex/by-underlying?underlying=au2607
```

必填参数：

- `underlying`：标的代码，例如 `au2607`

可选参数：

- `expire`：到期日，格式 `yyyyMMdd`
- `multiplier`：合约乘数，例如 `1000`

#### 4.4.2 按到期日查询 GEX

```http
GET /api/v1/vol-data/gex/by-expire?underlying=au2607&expire=20260624
```

必填参数：

- `underlying`：标的代码，例如 `au2607`

建议参数：

- `expire`：到期日，格式 `yyyyMMdd`

可选参数：

- `multiplier`：合约乘数，例如 `1000`

#### 4.4.3 按乘数查询 GEX

```http
GET /api/v1/vol-data/gex/by-multiplier?underlying=au2607&expire=20260624&multiplier=1000
```

必填参数：

- `underlying`：标的代码，例如 `au2607`

建议参数：

- `expire`：到期日，格式 `yyyyMMdd`
- `multiplier`：合约乘数，例如 `1000`

### 4.5 GEX 历史小时快照接口

GEX 历史小时快照接口用于查询本地数据库中已落库的整点 GEX 结构。它适合回看某一小时档位的净 GEX、零 gamma 和扫描曲线，而不是重新按当前行情计算。

```http
GET /api/v1/vol-data/gex/snapshot/by-underlying?underlying=au2607&snapshotTime=1781651875123
```

用途：

- 查询本地数据库中某个小时档位的历史 GEX 快照
- 返回结构与实时 GEX `GET /api/v1/vol-data/gex/by-multiplier` 基本一致
- 适合回看某个历史时点的 `current_gex`、`zero_gamma`、`spot_price` 和 `points`

必填参数：

- `underlying`：标的代码，例如 `au2607`
- `snapshotTime`：目标时间戳，毫秒；也可传 `last`，表示查询当前分组在数据库中最新的一条 GEX 快照，主要用于非开盘时段获取上次收盘时的 GEX 快照

可选参数：

- `expire`：到期日，格式 `yyyyMMdd`
- `multiplier`：合约乘数，例如 `1000`

参数规则：

- 当未传 `expire` 时，默认选择该 `underlying` 的最近月
- 当未传 `multiplier` 时，默认选择该月下最小乘数
- `snapshotTime` 传毫秒时间戳时会先向下取整到整点，再查询对应小时快照
- `snapshotTime=last` 时不做时间取整，直接按当前分组查询数据库中 `snapshot_hour_ms` 最大的一条记录；主要使用场景是在非开盘时段获取上次收盘时的 GEX 快照
- 计费 payload 中会同时记录实际查询的 `snapshotTime` 和原始请求的 `requestedSnapshotTime`

示例：

```bash
curl -sS 'https://api.hitick.top/api/v1/vol-data/gex/snapshot/by-underlying?underlying=au2607&snapshotTime=1781651875123' \
  -H 'X-API-Token: your_token_value'
```

返回核心结构：

```json
{
  "found": true,
  "query_type": "gex_by_multiplier",
  "underlying": "au2607",
  "expire_date": "20260624",
  "multiplier": "1000",
  "data_time_ms": 1781650800123,
  "spot_price": 919.12,
  "price_min": 827.208,
  "price_max": 1011.032,
  "range_pct": 0.1,
  "steps": 81,
  "current_gex": -1582342.118,
  "zero_gamma": 941.47,
  "points": [
    {
      "price": 827.208,
      "net_gex": -2120341.441
    }
  ],
  "error": null
}
```

字段说明：

- `found`：是否命中该历史 GEX 快照
- `query_type`：命中快照时通常保留落库时的实时查询类型，例如 `gex_by_multiplier`；未命中时为 `gex_snapshot_by_underlying`
- `underlying`：标的代码
- `expire_date`：实际命中的到期日，格式 `yyyyMMdd`
- `multiplier`：实际命中的合约乘数
- `data_time_ms`：落库快照对应的上游行情时间戳
- `spot_price`：该快照用于计算 GEX 的标的价格
- `current_gex`：该快照现价下的净 GEX
- `zero_gamma`：若曲线穿越 0，则返回线性插值得到的零 gamma 价格，否则为 `null`
- `points[]`：扫描价格点数组，结构与实时 `gex/*` 返回一致

说明：

- 如果 `found = false`，表示该分组在对应整点没有可用 GEX 快照
- 后台定时任务按可用分组抓取实时 `gex/by-multiplier`，并以整点小时作为 `snapshotHourMs` 落库
- 只有上游返回 `found = true` 且 `data_time_ms` 距当前时间不超过 30 分钟时，后台才会持久化该小时 GEX 快照

### 4.6 GEX 图片接口

GEX 图片接口用于获取已渲染的 GEX 结构图 CDN 地址，适合聊天机器人、外部系统或移动端直接展示图片。默认生成实时 GEX 图；传入 `snapshotTime` 后可生成过去某个小时档位的历史 GEX 图，传 `snapshotTime=last` 可生成当前分组数据库最新快照图，主要用于非开盘时段获取上次收盘时的 GEX 图。

```http
GET /api/v1/vol-data/gex-image/by-underlying?underlying=au2607
```

必填参数：

- `underlying`：标的代码，例如 `au2607`

建议参数：

- `expire`：到期日，格式 `yyyyMMdd`
- `multiplier`：合约乘数，例如 `1000`
- `snapshotTime`：目标时间戳，毫秒；也可传 `last`，表示使用当前分组数据库最新 GEX 快照生成图片，主要用于非开盘时段获取上次收盘时的 GEX 图

返回示例：

```json
{
  "code": 0,
  "message": "ok",
  "data": {
    "url": "https://cdn.example.com/gex/au2607-20260624-1000.png",
    "generated_at": 1781650800000
  }
}
```

调用说明：

- 只传 `underlying` 即可获取该标的的 GEX 图片 URL
- `expire` / `multiplier` 可选；未传时系统会自动选择可用组合
- 未传 `snapshotTime` 时生成实时 GEX 图；传毫秒时间戳时生成对应小时快照图；传 `last` 时生成最新落库快照图，主要用于非开盘时段获取上次收盘时的 GEX 图
- 返回的 `url` 可直接用于图片展示或发送
- 成功返回图片 URL 后触发计费；失败时接口返回错误信息

## 5. 参数说明总表

所有接口的 query 参数都来自下面这组字段：

| 参数名 | 类型 | 是否必填 | 适用接口 | 说明 |
| --- | --- | --- | --- | --- |
| `underlying` | string | `query/*`、`snapshot/*`、`ts/*`、`gex/*`、`gex-image/*` 必填 | `query/*`、`snapshot/*`、`ts/*`、`gex/*`、`gex-image/*` | 标的代码，例如 `au2607`、`cu2607` |
| `expire` | string | 视场景建议传 | `query/*`、`snapshot/*`、`ts/*`、`gex/*`、`gex-image/*` | 到期日，格式 `yyyyMMdd`，例如 `20260624` |
| `multiplier` | string / number | 视场景建议传 | `query/*`、`snapshot/*`、`ts/*`、`gex/*`、`gex-image/*` | 合约乘数，例如 `1000`、`5` |
| `start` | string / number | `ts/*` 必填 | `ts/*` | 起始毫秒时间戳 |
| `end` | string / number | `ts/*` 必填 | `ts/*` | 结束毫秒时间戳 |
| `snapshotTime` | string / number | `snapshot/*`、`gex/snapshot/*` 必填；`gex-image/*` 可选 | `snapshot/*`、`gex/snapshot/*`、`gex-image/*` | 目标毫秒时间戳，服务端会向下取整到整点查询；也可传 `last` 查询当前分组数据库最新快照，主要用于非开盘时段获取上次收盘时的快照。用于 `gex-image/*` 时，表示生成历史 GEX 图或最新落库 GEX 图 |

实务建议：

- 如果你只知道标的代码，先用 `by-underlying`
- 如果你在做单一期限分析，优先传 `expire`
- 如果同一标的存在多个乘数，建议显式传 `multiplier`
- 时间区间建议用毫秒级 Unix 时间戳，避免时区歧义

## 6. 返回结构详解

### 6.1 快照查询返回结构

三个 `query/*` 接口的 `data` 顶层结构一致：

```json
{
  "found": true,
  "query_type": "by_underlying",
  "underlying": "au2607",
  "expire_date": "20260624",
  "multiplier": 1000,
  "atm_iv": 0.29434965770081106,
  "iv_skew": -0.0174,
  "oi_pcr": 1.2389,
  "volume_pcr": 0.8123,
  "data_time_ms": 1781071070500,
  "api_latency_ms": 132,
  "calc_latency_ms": 8,
  "underlying_quote": {
    "symbol": "au2607",
    "last_price": 919.12,
    "bid_price": 918.94,
    "ask_price": 919.24,
    "open_price": 930.0,
    "highest_price": 951.2,
    "lowest_price": 912.6,
    "pre_settlement_price": 947.94
  },
  "rows": [
    {
      "strike": 704.0,
      "call": {
        "symbol": "au2607C704",
        "delta": 0.9920005958397674,
        "gamma": 0.00019125757057879587,
        "vega": 0.03419517453622726,
        "theta": -0.10879514980386451,
        "theo_vol": 0.584031857797719,
        "implied_vol": null,
        "implied_bid_vol": null,
        "implied_ask_vol": null,
        "short_margin": 364215.4
      },
      "put": {
        "symbol": "au2607P704",
        "delta": -0.007040959652272832,
        "gamma": 0.00019125757057879587,
        "vega": 0.03419517453622726,
        "theta": -0.10879514980386451,
        "theo_vol": 0.584031857797719,
        "implied_vol": null,
        "implied_bid_vol": null,
        "implied_ask_vol": null,
        "short_margin": 85297.7
      }
    }
  ],
  "error": null
}
```

#### 6.1.1 顶层字段

- `found`：是否命中数据
- `query_type`：查询类型，如 `by_underlying`、`by_expire`、`by_multiplier`
- `underlying`：标的代码
- `expire_date`：到期日
- `multiplier`：合约乘数
- `atm_iv`：当前 ATM 隐含波动率，使用小数表示，不是百分比
- `iv_skew`：当前隐含波动率偏度
- `oi_pcr`：按 `put.open_interest / call.open_interest` 聚合得到的持仓量 PCR
- `volume_pcr`：按 `put.volume / call.volume` 聚合得到的成交量 PCR
- `data_time_ms`：快照数据时间戳，毫秒
- `api_latency_ms`：上游接口耗时，毫秒
- `calc_latency_ms`：上游计算耗时，毫秒
- `error`：上游错误对象；正常时通常为 `null`

#### 6.1.2 标的报价字段

`underlying_quote` 用于表示标的实时行情，稳定字段包括：

- `underlying_quote.symbol`：标的代码
- `underlying_quote.last_price`：标的最新价
- `underlying_quote.bid_price` / `ask_price`：买一价和卖一价
- `underlying_quote.open_price`：Basic Data 返回的当前交易日开盘价
- `underlying_quote.highest_price`：Basic Data 返回的当前交易日最高价
- `underlying_quote.lowest_price`：Basic Data 返回的当前交易日最低价
- `underlying_quote.pre_settlement_price`：昨结算价
- `underlying_quote.open_interest`：持仓量
- `underlying_quote.volume`：成交量
- `underlying_quote.exchange`：交易所
- `underlying_quote.timestamp_ms`：行情源时间戳

说明：

- 开盘、最高和最低均直接透传 Basic Data，不由 volData 的分钟序列推算。
- 字段在上游尚未形成有效价格时可能为 `null`。

#### 6.1.3 期权链字段

`rows` 表示按行权价展开的期权链。

- `rows[].strike`：行权价
- `rows[].call`：该行权价对应的看涨期权数据
- `rows[].put`：该行权价对应的看跌期权数据

如果某一侧无数据，对应 `call` 或 `put` 可能为空。

#### 6.1.4 报价相关字段

当前快照结构中，文档已确认或约定可重点关注以下报价相关字段：

- `underlying_quote.last_price`：标的最新价
- `underlying_quote.open_price` / `highest_price` / `lowest_price`：当前交易日开高低
- `underlying_quote.pre_settlement_price`：昨结算价
- `rows[].strike`：行权价
- `rows[].call.symbol` / `rows[].put.symbol`：期权合约代码

如果上游后续补充盘口价、买一卖一、成交量、持仓量等字段，也会继续透传在 `call` / `put` 节点中。当前这份对外文档先只写明已验证存在的稳定字段。

#### 6.1.5 隐含波动率字段

本接口可提供多层次的隐波数据：

- `atm_iv`：整个分组当前的 ATM 隐含波动率
- `iv_skew`：整个分组当前的隐含波动率偏度
- `rows[].call.theo_vol` / `rows[].put.theo_vol`：模型理论波动率
- `rows[].call.implied_vol` / `rows[].put.implied_vol`：该合约的中间隐含波动率
- `rows[].call.implied_bid_vol` / `rows[].put.implied_bid_vol`：按买价反推的隐含波动率
- `rows[].call.implied_ask_vol` / `rows[].put.implied_ask_vol`：按卖价反推的隐含波动率

字段解释：

- `atm_iv`：最适合做品种层面的升波 / 降波、时点比较、排序分析
- `theo_vol`：更偏模型内部估计值，适合与市场隐波对比
- `implied_vol`：更适合看单个合约当前的市场定价隐波
- `implied_bid_vol` / `implied_ask_vol`：适合衡量盘口两侧隐波差异和流动性状态

注意：

- 所有隐波字段都以小数表示，例如 `0.28` 表示 `28%`
- 返回 `null` 表示该时刻无法稳定反推出对应隐波，不应直接当作 `0`

#### 6.1.6 PCR 字段

当前快照顶层还会返回两个 PCR 指标：

- `oi_pcr`：持仓量 Put/Call Ratio
- `volume_pcr`：成交量 Put/Call Ratio

PCR 口径：

- `oi_pcr = sum(put.open_interest) / sum(call.open_interest)`
- `volume_pcr = sum(put.volume) / sum(call.volume)`
- 缺失 `open_interest` 或 `volume` 按 `0` 处理
- 当 call 侧分母为 `0` 时，返回 `NaN`

#### 6.1.7 Greeks 字段

本接口目前明确可返回以下 Greeks：

- `delta`
- `gamma`
- `vega`
- `theta`

字段位置：

- `rows[].call.delta`
- `rows[].call.gamma`
- `rows[].call.vega`
- `rows[].call.theta`
- `rows[].put.delta`
- `rows[].put.gamma`
- `rows[].put.vega`
- `rows[].put.theta`

含义说明：

- `delta`：标的价格变化 1 单位时，期权价格的一阶敏感度
- `gamma`：`delta` 对标的价格变化的二阶敏感度
- `vega`：期权价格对隐含波动率变化的敏感度
- `theta`：期权价格对时间流逝的敏感度

使用建议：

- 做方向判断时优先看 `delta`
- 做 Gamma 风险或 Gamma 暴露分析时看 `gamma`
- 做升波 / 降波敏感度分析时看 `vega`
- 做临近到期的时间损耗分析时看 `theta`

#### 6.1.7 保证金字段

- `rows[].call.short_margin`
- `rows[].put.short_margin`

说明：

- `short_margin` 面向卖方场景，表示卖出该期权时的参考保证金金额
- 可用于估算资金占用、静态收益率和风控承受能力
- 该字段是参考值，实际交易保证金仍可能因期货公司、交易所规则、账户风险参数和盘中行情而变化

### 6.2 时间序列返回结构

三个 `ts/*` 接口的 `data` 顶层结构一致：

```json
{
  "found": true,
  "query_type": "ts_by_underlying",
  "underlying": "au2607",
  "expire_date": "20260624",
  "multiplier": 1000,
  "start_ms": 1781062200000,
  "end_ms": 1781062300000,
  "rows": [
    {
      "timestamp_ms": 1781062200500,
      "underlying_last_price": 911.92,
      "atm_iv": 0.3072331463176879,
      "iv_skew": -0.0174
    }
  ],
  "error": null
}
```

字段说明：

- `found`：是否命中
- `query_type`：查询类型，可能为 `ts_by_underlying`、`ts_by_expire`、`ts_by_multiplier`
- `underlying`：标的代码
- `expire_date`：到期日
- `multiplier`：合约乘数
- `start_ms`：请求起始时间戳
- `end_ms`：请求结束时间戳
- `rows`：时间序列点数组
- `rows[].timestamp_ms`：数据点时间戳，毫秒
- `rows[].underlying_last_price`：该时点的标的最新价
- `rows[].atm_iv`：该时点的 ATM 隐含波动率
- `rows[].iv_skew`：该时点的隐含波动率偏度
- `error`：上游错误对象；正常时通常为 `null`

时序能力总结：

- 可以做日内升波 / 降波分析
- 可以做开盘到当前的 `atm_iv` 变化分析
- 可以做某一交易时段的标的价格与隐波联动分析
- 可以作为主观信号、量化特征、图表展示的原始输入

### 6.3 GEX 曲线返回结构

三个 `gex/*` 接口的 `data` 顶层结构一致：

```json
{
  "found": true,
  "query_type": "gex_by_underlying",
  "underlying": "au2607",
  "expire_date": "20260624",
  "multiplier": 1000,
  "data_time_ms": 1781071070500,
  "spot_price": 919.12,
  "price_min": 827.208,
  "price_max": 1011.032,
  "range_pct": 0.1,
  "steps": 81,
  "current_gex": -1582342.118,
  "zero_gamma": 941.47,
  "points": [
    {
      "price": 827.208,
      "net_gex": -2120341.441
    }
  ],
  "error": null
}
```

字段说明：

- `found`：是否命中
- `query_type`：查询类型，可能为 `gex_by_underlying`、`gex_by_expire`、`gex_by_multiplier`
- `underlying`：标的代码
- `expire_date`：到期日
- `multiplier`：合约乘数
- `data_time_ms`：快照时间戳
- `spot_price`：当前标的价格，GEX 扫描中心
- `price_min`：扫描下界
- `price_max`：扫描上界
- `range_pct`：扫描半区间比例，例如 `0.1` 表示以现价上下各 `10%` 扫描
- `steps`：扫描网格数量
- `current_gex`：当前现价下的净 GEX
- `zero_gamma`：若曲线穿越 0，则返回线性插值得到的零 gamma 价格，否则为 `null`
- `points`：扫描价格点数组
- `points[].price`：扫描价格点
- `points[].net_gex`：该价格点对应的净 GEX
- `error`：上游错误对象；正常时通常为 `null`

GEX 能力总结：

- 可看当前市场整体是正 GEX 还是负 GEX
- 可判断现价附近是否接近零 gamma 区域
- 可辅助分析价格波动放大 / 收敛的潜在结构
- 可与 `gamma`、`open interest`、持仓结构分析配合使用

### 6.4 GEX 历史小时快照返回结构

`gex/snapshot/by-underlying` 返回本地落库的小时 GEX 快照。命中时结构与实时 `gex/*` 基本一致，未命中时返回一个轻量的未命中对象：

```json
{
  "found": false,
  "query_type": "gex_snapshot_by_underlying",
  "underlying": "au2607",
  "expire_date": "20260624",
  "multiplier": "1000"
}
```

使用建议：

- 需要“某个整点附近的 GEX 结构”时使用 `gex/snapshot/by-underlying`
- 需要“当前实时 GEX 结构”时使用 `gex/by-underlying`、`gex/by-expire` 或 `gex/by-multiplier`
- `snapshotTime` 可传任意毫秒时间戳，服务端会按整点小时归档查询；也可传 `last` 查询当前分组数据库最新快照，主要用于非开盘时段获取上次收盘时的快照

## 7. 波动率日差说明

如果需要回答这类问题：

- “今天 `xx` 有升波吗？”
- “今天升波最大的品种是什么？”
- “今天哪些品种降波最多？”

建议统一使用“波动率日差”口径。

定义：

- 波动率日差 = 当前波动率 - 上一交易日收盘时波动率
- 波动率上升 / 下降，均以上一交易日收盘时的波动率为比较基准

使用建议：

1. 先用快照接口读取当前 `atm_iv`
2. 再用时间序列接口读取覆盖“上一交易日收盘前后”和“当前时刻”的数据
3. 取上一交易日收盘时最近的 `atm_iv` 作为对比基准
4. 用当前 `atm_iv - 上一交易日收盘时 atm_iv` 得到波动率日差

判读规则：

- 波动率日差 > 0：表示今天升波
- 波动率日差 < 0：表示今天降波
- 波动率日差 = 0：表示与上一交易日收盘相比基本持平

注意：

- `atm_iv` 为小数形式返回，例如 `0.28` 表示 `28%`
- 做跨品种比较时，建议统一使用同一时点的当前快照，并统一以上一交易日收盘时为基准
- 如果上一交易日收盘附近没有有效时序点，应选择最接近收盘时间的可用点，并在结果中说明是“收盘附近参考值”

## 8. Agent 接入规范

如果给 Agent 使用，建议按下面的最小规则封装。

### 8.1 工具名建议

```text
orange_resolve_subject
orange_vol_data
```

`orange_resolve_subject` 输入 `query`，可选 `limit` 默认 5、最大 5。它返回推荐的 `selected` 三元组及最多 5 个候选，不返回完整目录、行情或期权链。

### 8.2 输入结构建议

```json
{
  "action": "by_underlying | snapshot_by_underlying | gex_snapshot_by_underlying | ts_by_underlying | ts_by_expire | ts_by_multiplier | gex_by_underlying | gex_by_expire | gex_by_multiplier | gex_image_by_underlying",
  "params": {
    "underlying": "au2607",
    "expire": "20260624",
    "multiplier": "1000",
    "start": "1781062200000",
    "end": "1781062300000",
    "fullChain": false
  }
}
```

参数要求：

- `action = by_underlying`：必须传 `underlying`；`expire`、`multiplier` 可选，未传时自动选择最早到期日及该到期日最小乘数；默认只返回现价上下 10% 行权价档位，完整链需传 `fullChain=true`
- `action = snapshot_by_underlying`：必须传 `underlying`、`snapshotTime`，建议传 `expire`、`multiplier`；`snapshotTime` 可为毫秒时间戳或 `last`，其中 `last` 主要用于非开盘时段获取上次收盘时的快照
- `action = gex_snapshot_by_underlying`：必须传 `underlying`、`snapshotTime`，建议传 `expire`、`multiplier`；`snapshotTime` 可为毫秒时间戳或 `last`，其中 `last` 主要用于非开盘时段获取上次收盘时的 GEX 快照
- `action = ts_by_underlying`：必须传 `underlying`、`start`、`end`
- `action = ts_by_expire`：必须传 `underlying`、`start`、`end`，建议传 `expire`
- `action = ts_by_multiplier`：必须传 `underlying`、`start`、`end`，建议传 `expire`、`multiplier`
- `action = gex_by_underlying`：必须传 `underlying`
- `action = gex_by_expire`：必须传 `underlying`，建议传 `expire`
- `action = gex_by_multiplier`：必须传 `underlying`，建议传 `expire`、`multiplier`
- `action = gex_image_by_underlying`：必须传 `underlying`，建议传 `expire`、`multiplier`；未传时后端自动补齐；可选传 `snapshotTime` 毫秒时间戳或 `last` 生成历史 GEX 图，其中 `last` 主要用于非开盘时段获取上次收盘时的 GEX 图

### 8.3 路由映射

- `by_underlying` -> `GET /api/v1/vol-data/query/by-underlying`
- `snapshot_by_underlying` -> `GET /api/v1/vol-data/snapshot/by-underlying`
- `gex_snapshot_by_underlying` -> `GET /api/v1/vol-data/gex/snapshot/by-underlying`
- `ts_by_underlying` -> `GET /api/v1/vol-data/ts/by-underlying`
- `ts_by_expire` -> `GET /api/v1/vol-data/ts/by-expire`
- `ts_by_multiplier` -> `GET /api/v1/vol-data/ts/by-multiplier`
- `gex_by_underlying` -> `GET /api/v1/vol-data/gex/by-underlying`
- `gex_by_expire` -> `GET /api/v1/vol-data/gex/by-expire`
- `gex_by_multiplier` -> `GET /api/v1/vol-data/gex/by-multiplier`
- `gex_image_by_underlying` -> `GET /api/v1/vol-data/gex-image/by-underlying`

### 8.4 Agent 调用流程建议

1. 从安全存储读取 `X-API-Token`
2. 标的不完整时先调用 `orange_resolve_subject`；命中且无歧义后使用 `selected`，否则向用户澄清
3. 根据目标调用 `orange_vol_data`
4. 检查平台响应 `code`
5. MCP `by_underlying` 默认只返回现价上下 10% 档位；根据 `chain_meta` 判断是否发生裁剪或缺少现价回退
6. 如果确实需要完整期权链，显式传 `params.fullChain=true`
7. 如果需要分析一段时间内的隐波变化，读取 `ts/*` 的 `rows`
8. 如果需要分析 Gamma Exposure 分布，读取 `gex/*` 的 `points`、`current_gex`、`zero_gamma`
9. 如果需要回看历史整点 GEX 结构，调用 `gex_snapshot_by_underlying`，读取 `points`、`current_gex`、`zero_gamma`
10. 如果因为未开盘、行情源不可用或实时接口返回 `found=false` 导致实时 `query/*` 或 `gex/*` 获取失败，可以改用 `snapshot/by-underlying` 或 `gex/snapshot/by-underlying`，并传 `snapshotTime=last`；这是 `last` 的主要使用场景，返回的是当前分组数据库最新快照，通常可视为上次收盘时的快照
11. 当用户询问特定标的的 GEX、零 gamma、正负 GEX 或 GEX 结构时，除 `gex/*` 结构化数据外，可以额外调用 `gex_image_by_underlying`，把图片 URL 一并返回，方便用户理解与查看
12. 如果需要给用户直接展示或发送 GEX 图，调用 `gex_image_by_underlying` 并使用返回的 `url`；如果用户需要过去的 GEX 图，传 `snapshotTime` 毫秒时间戳，若处于非开盘时段、需要上次收盘图则传 `snapshotTime=last`

### 8.5 Agent 错误处理建议

- 平台 `code != 0`：直接抛出平台错误
- `401/403`：扣费侧使用 `Authorization: Bearer <X-API-Token>` 调用计费接口时鉴权失败
- `扣费失败`：直接透传平台错误，提示用户检查 token 或计费服务状态
- `404` 且 `found = false`：按“未命中”处理，不要当系统故障
- 上游超时或异常：建议重试，并保留原始错误信息

## 9. 计费与明细说明

- 平台在业务数据成功返回后，使用 OpenAI 兼容 `POST /chat/completions` 发起同步扣费
- `groups` 不触发扣费
- `query/*`、`snapshot/*`、`ts/*`、`gex/*`、`gex-image/*` 成功返回后触发扣费
- 对外业务接口协议保持不变，仍然由调用方传 `X-API-Token`
- `model` 固定为 `VolData`，用于标识业务类型
- `messages` 保持最简，只携带本次请求路径和参数
- 扣费请求头格式固定为 `Authorization: Bearer <X-API-Token>`
- 外部计费接口返回 HTTP `200` 视为扣费成功
- 扣费失败时，业务响应直接返回错误，不再写本地 usage 明细或异步扣费任务

## 10. 最小测试示例

查询实时快照：

```bash
curl -sS 'https://api.hitick.top/api/v1/vol-data/query/by-underlying?underlying=au2607' \
  -H 'X-API-Token: your_token_value'
```

查询 ATM IV 时序：

```bash
curl -sS 'https://api.hitick.top/api/v1/vol-data/ts/by-underlying?underlying=au2607&start=1781062200000&end=1781062300000' \
  -H 'X-API-Token: your_token_value'
```

查询 GEX 曲线：

```bash
curl -sS 'https://api.hitick.top/api/v1/vol-data/gex/by-underlying?underlying=au2607' \
  -H 'X-API-Token: your_token_value'
```

## 11. 接入建议

- 手动接入适合后端服务、脚本、联调测试
- Agent 接入适合自动查询、波动率分析、Greeks 辅助处理、GEX 结构分析
- 建议给不同用途创建不同 Token，方便审计和隔离
