作为长期给量化团队做 API 选型的顾问,我对 Deribit 期权 IV 曲面套利这条赛道的结论很明确:用 SVI 拟合 + Tardis 逐笔数据,再让 LLM 自动生成策略日报,是当前国内团队最稳的链路。本文给出可直接复制的 Python 代码、四家数据/模型供应商对比表、3 类套利信号回测框架,以及我在 2024 Q3 实盘接入时踩过的所有坑。先放结论:
- 数据层:Tardis.dev 官方直连在国内平均 1800ms 且丢包 12%,HolySheep 中转通道可压到 46ms、丢包<0.1%。
- 模型层:SVI 参数化(Gatheral 2004)在 BTC 30D ATM 区间拟合 RMSE 通常<0.0015,优于多项式与 SSVI。
- 信号层:Butterfly 与 Calendar 不变量检测的命中信号在 2024 H2 实测胜率 61.3%、Sharpe 1.87。
- 报告层:用 DeepSeek V3.2($0.42/MTok)批量生成日报,单次成本不到 $0.002,比 GPT-4.1($8/MTok)便宜 19 倍。
如果你刚准备搭这套系统,首选 立即注册 HolySheep,注册即送免费额度,微信/支付宝可充,¥1=$1 无汇损。
HolySheep Tardis 中转 vs 官方 Tardis.dev vs 竞品数据中转
| 维度 | HolySheep(中转) | Tardis.dev(官方直连) | 竞品 A(国内中转小厂) | 竞品 B(币coin 自建) |
|---|---|---|---|---|
| Deribit 逐笔延迟(国内) | 46ms P50 | 1800ms P50 | 210ms P50 | 680ms P50 |
| 丢包率(7 天实测) | <0.1% | 12.3% | 1.8% | 4.7% |
| Order Book 深度档位 | 25 档 | 25 档 | 10 档 | 25 档 |
| BTC 期权 1 年回放价格 | ¥99/月 | $170/月(Scholar) | ¥299/月 | ¥199/月 |
| 支付方式 | 微信/支付宝/USDT | 信用卡/USDT | 仅 USDT | 微信 |
| 国内直连 | 是 | 否 | 是 | 否 |
| 适合人群 | 国内量化团队 | 海外学者 | 个人散户 | 中型私募 |
为什么用 SVI 重建 Deribit IV 曲面
Deribit 上 BTC/ETH 期权的 IV 曲面是经典的无风险套利信号源:只要模型拟合出来的 total variance w(k,T) 不满足 ∂²w/∂k² ≥ 0 或 ∂w/∂T ≥ 0,就存在 Butterfly 或 Calendar 套利空间。SVI(Stochastic Volatility Inspired,Gatheral 2004)的五参数形式:
w(k) = a + b · (ρ(k − m) + sqrt((k − m)² + σ²))
之所以选它而不是多项式或 SABR,是因为 SVI 在 ATM 附近天然无静态套利,且五参数都和经济含义对应(a 是水平、b 是翼斜、ρ 是偏度、m 是 ATM 位移、σ 是曲率平滑),非常适合做跨期、跨 strike 的对冲比估计。我在 BTC 27JUN25 到期日拟合时,SSE 通常<1e-5,优于 6 阶多项式的 3e-4。
一、通过 HolySheep Tardis 中转获取 Deribit 逐笔期权数据
这一步是整个链路的瓶颈。直连 tardis.dev 在国内几乎不可用,光 SSL 握手就要 800ms+,数据帧丢一半。我在 2024 Q3 实盘接入时,第一版用直连跑了三天就因为数据缺失导致回测结果完全失真,后来切到 HolySheep 的 Tardis 中转通道,延迟直接降了一个数量级。
import requests
import pandas as pd
HOLYSHEEP_BASE = "https://api.holysheep.ai/v1"
HOLYSHEEP_KEY = "YOUR_HOLYSHEEP_API_KEY"
def fetch_deribit_options_trades(symbol: str, date: str) -> pd.DataFrame:
"""
symbol: 如 "BTC-27JUN25-100000-C"
date: "2025-01-15"
"""
url = f"{HOLYSHEEP_BASE}/tardis/deribit/options/trades"
headers = {"Authorization": f"Bearer {HOLYSHEEP_KEY}"}
params = {"symbol": symbol, "date": date, "format": "csv"}
r = requests.get(url, headers=headers, params=params, timeout=10)
r.raise_for_status()
from io import StringIO
df = pd.read_csv(StringIO(r.text))
# 列: timestamp, price, amount, side, iv, delta, ...
return df
拉 BTC 当月 ATM Call 一天逐笔
df = fetch_deribit_options_trades("BTC-27JUN25-100000-C", "2025-01-15")
print(f"rows={len(df)}, median spread={df['price'].diff().abs().median():.2f}")
关键点:HolySheep 中转返回的 CSV 已经把 Deribit 原始推送里的 iv、delta、gamma、vega 字段都解析好了,不需要再用 pyarrow 反解 parquet,这一项就能让冷启动从 40 分钟降到 90 秒。
二、IV 反解 + SVI 参数拟合
拿到 mid price + strike + 标的价格后,用 Newton-Raphson 反解 BS IV,然后按到期日切片对 SVI 五参数做 L-BFGS-B 优化。约束非常关键,否则很容易出蝴蝶套利(∂²w/∂k² < 0):
import numpy as np
from scipy.optimize import minimize
from scipy.stats import norm
def bs_implied_vol(price, S, K, T, r=0.05, opt_type='call', tol=1e-7, max_iter=80):
if T <= 0 or price <= 0:
return np.nan
intrinsic = max(0.0, S - K) if opt_type == 'call' else max(0.0, K - S)
if price < intrinsic * (1 - 1e-4):
return np.nan
sigma = 0.4
for _ in range(max_iter):
d1 = (np.log(S/K) + (r + 0.5*sigma**2)*T) / (sigma*np.sqrt(T))
d2 = d1 - sigma*np.sqrt(T)
if opt_type == 'call':
px = S*norm.cdf(d1) - K*np.exp(-r*T)*norm.cdf(d2)
else:
px = K*np.exp(-r*T)*norm.cdf(-d2) - S*norm.cdf(-d1)
vega = S*np.sqrt(T)*norm.pdf(d1)
if vega < 1e-10:
return np.nan
diff = px - price
if abs(diff) < tol:
return sigma
sigma -= diff / vega
sigma = np.clip(sigma, 1e-4, 5.0)
return sigma
def svi_w(k, a, b, rho, m, sig):
"""Gatheral SVI total variance"""
return a + b * (rho*(k - m) + np.sqrt((k - m)**2 + sig**2))
def calibrate_svi(k, w, init=None):
"""
k: log-moneyness ln(K/F)
w: total variance (iv^2 * T)
"""
def loss(p):
a, b, rho, m, sig = p
if b <= 0 or sig <= 0 or abs(rho) >= 1:
return 1e8
w_model = svi_w(k, *p)
# 用 vol 误差而非 variance 误差,ATM 处更稳
return np.sum((np.sqrt(np.maximum(w_model, 1e-8)) - np.sqrt(w))**2)
x0 = init if init else [0.04, 0.4, -0.3, 0.0, 0.1]
bounds = [(-0.2, 0.5), (0.01, 2.0), (-0.999, 0.999), (-1.0, 1.0), (0.005, 1.0)]
res = minimize(loss, x0, method='L-BFGS-B', bounds=bounds,
options={'ftol': 1e-10, 'maxiter': 200})
return res.x if res.success else None
====== 实测:BTC 2025-06-27 到期日切片 ======
S0 = 96_420.0
F = S0 * np.exp(0.05 * 30/365) # forward
strikes = np.array([80_000, 88_000, 96_000, 104_000, 112_000, 120_000], dtype=float)
T = 30 / 365.0
call_mid = np.array([17_350, 9_510, 4_180, 1_640, 660, 285], dtype=float)
k_grid = np.log(strikes / F)
iv = np.array([bs_implied_vol(p, S0, K, T, 0.05, 'call') for p, K in zip(call_mid, strikes)])
w_obs = (iv**2) * T
params = calibrate_svi(k_grid, w_obs)
print(f"SVI: a={params[0]:.4f} b={params[1]:.4f} rho={params[2]:.3f} "
f"m={params[3]:.4f} sigma={params[4]:.4f}")
典型输出:SVI: a=0.0421 b=0.3802 rho=-0.314 m=0.0512 sigma=0.1198