教程

用 Python 获取美股期权链和希腊值

三步拉取一只股票某个到期日的整条期权链,并取出价格、隐含波动率和希腊值。只用 requests,完整代码可直接运行。

读完这篇,你会得到一个 Python 脚本:输入股票代码和到期日,输出这样一张期权链表格(AAPL 实际运行结果,节选):

到期日: ['2026-10-19', '2026-10-21', '2026-10-23', '2026-10-26', ...]
2026-10-21 到期,共 34 个合约
合约                   类型   行权价  最新价   买价   卖价     IV   Delta   Gamma   Theta    Vega  未平仓
O:AAPL261021C00340000  call     340    6.00   0.00   0.00  42.0%   0.586  0.0327  -0.945   0.113     522
O:AAPL261021C00342500  call   342.5    4.49   0.00   0.00  39.7%   0.503  0.0359  -0.926   0.113     454
O:AAPL261021C00345000  call     345    3.08   0.00   0.00  37.3%   0.410  0.0368  -0.836   0.114    2606
...
O:AAPL261021P00345000  put      345    4.32   0.00   0.00  25.8%  -0.637  0.0524  -0.538   0.110    1029
O:AAPL261021P00347500  put    347.5    5.55   0.00   0.00  22.2%  -0.789  0.0468  -0.345   0.077    3472
O:AAPL261021P00350000  put      350    8.36   0.00   0.00      -       -       -       -       -    1366

准备

  • 一个开通了期权套餐的 API Key(查看套餐)。期权套餐可以单独购买,也可以叠加在股票套餐上,共用同一个 Key。
  • Python 3.8 以上,安装 requests:pip install requests

先写一个通用的翻页函数。列表类接口一次最多返回一页,响应里的 next_url 指向下一页,并且已经带上了全部查询条件,顺着它请求直到为空即可:

import requests

BASE = "https://marilux.dev"
API_KEY = "mh_live_your_key"   # 换成你的 API Key
H = {"Authorization": f"Bearer {API_KEY}"}


def get_all(url, params=None):
    """请求一个列表接口,顺着 next_url 翻页,直到取完。"""
    rows = []
    while url:
        r = requests.get(url, headers=H, params=params, timeout=30)
        r.raise_for_status()
        data = r.json()
        rows.extend(data.get("results", []))
        url, params = data.get("next_url"), None  # next_url 已经带上了全部查询条件
    return rows

第 1 步:查有哪些到期日

用合约列表接口 /v3/reference/options/contracts 查出某个标的在一段时间内的所有合约,再取出不重复的到期日:

contracts = get_all(f"{BASE}/v3/reference/options/contracts", {
    "underlying_ticker": "AAPL",
    "expiration_date.gte": "2026-10-19",
    "expiration_date.lte": "2026-11-30",
    "limit": 1000,
})
expirations = sorted({c["expiration_date"] for c in contracts})
print("到期日:", expirations)

默认只返回还没到期的合约;要查已经到期的历史合约,加上 "expired": "true"。

第 2 步:拉某个到期日的期权链

期权链快照接口 /v3/snapshot/options/{标的} 一次返回整条链上每个合约的最新价格、隐含波动率、希腊值和未平仓量。用 expiration_date 指定到期日,用 strike_price.gte / strike_price.lte 只取平值附近的行权价,可以少翻很多页:

expiry = expirations[1]
chain = get_all(f"{BASE}/v3/snapshot/options/AAPL", {
    "expiration_date": expiry,
    "strike_price.gte": 320,
    "strike_price.lte": 360,
    "limit": 250,
})
print(f"{expiry} 到期,共 {len(chain)} 个合约")

只要看涨或只要看跌,再加 "contract_type": "call" 或 "put"。limit 最大 250,设大一点翻页次数少,整体快得多。

第 3 步:取出价格、隐含波动率和希腊值

期权链里每个合约是一个对象,常用字段如下:

字段含义
details.ticker期权代码,如 O:AAPL261021C00345000(格式说明)
details.contract_type / strike_price / expiration_date看涨或看跌、行权价、到期日
day.close当日最新成交价(盘前为上一交易日收盘价)
last_quote.bid / last_quote.ask最新买一价、卖一价
implied_volatility隐含波动率,0.373 表示 37.3%(什么是隐含波动率)
greeks.delta / gamma / theta / vega希腊值(各自的含义)
open_interest未平仓量(合约数)
underlying_asset.price标的股票的最新价格

有些合约没有希腊值和隐含波动率(见下面常见问题),所以取值时用 .get(),缺失的显示成 "-",不要当成 0:

def fmt(v, width, spec=""):
    """接口没返回的字段显示成 -,不要当成 0。"""
    return ("-" if v is None else format(v, spec)).rjust(width)


print("合约                   类型   行权价  最新价   买价   卖价     IV   Delta   Gamma   Theta    Vega  未平仓")
for c in sorted(chain, key=lambda c: (c["details"]["contract_type"], c["details"]["strike_price"])):
    d = c["details"]
    day, quote, g = c.get("day", {}), c.get("last_quote", {}), c.get("greeks", {})
    print(f"{d['ticker']:<22} {d['contract_type']:<5}"
          f"{d['strike_price']:>7} {fmt(day.get('close'), 7, '.2f')}"
          f"{fmt(quote.get('bid'), 7, '.2f')}{fmt(quote.get('ask'), 7, '.2f')}"
          f"{fmt(c.get('implied_volatility'), 7, '.1%')}"
          f"{fmt(g.get('delta'), 8, '.3f')}{fmt(g.get('gamma'), 8, '.4f')}"
          f"{fmt(g.get('theta'), 8, '.3f')}{fmt(g.get('vega'), 8, '.3f')}"
          f"{fmt(c.get('open_interest'), 8)}")

把上面三段代码按顺序放进一个 .py 文件就是完整脚本,运行后输出文章开头那张表。

常见问题

买价、卖价都是 0?

美股期权只在常规交易时段(美东 9:30–16:00)有报价,休市和盘前盘后时段 last_quote 的买卖价会是 0。需要价格时可以改用 day.close(最新成交价),或等开盘后再取。

有些合约没有希腊值和隐含波动率?

深度实值、长时间没有成交或报价的合约,算不出可靠的隐含波动率,接口就不返回 greeks 和 implied_volatility 字段。上面示例里行权价 350 以上的看跌期权就是这种情况。

只想查一个合约?

用 /v3/snapshot/options/{标的}/{期权代码},返回结构和期权链里的单个元素一样:

r = requests.get(f"{BASE}/v3/snapshot/options/AAPL/O:AAPL261023C00345000", headers=H, timeout=30)
print(r.json()["results"]["greeks"])

怎么存成表格或 CSV?

装了 pandas 的话,json_normalize 会把嵌套字段展开成 greeks.delta 这样的列:

import pandas as pd

df = pd.json_normalize(chain)
df.to_csv("aapl_chain.csv", index=False)

能用 Polygon SDK 写吗?

可以,SDK 会自动翻页,代码更短。见 用 Polygon SDK 接入美股数据。

开始使用:注册账号后用兑换码激活,API Key 立即生成;股票入门版 ¥39 起,期权套餐 ¥99 起,人民币付款。查看套餐 →