作为长期给量化团队做 API 选型的顾问,我对 Deribit 期权 IV 曲面套利这条赛道的结论很明确:用 SVI 拟合 + Tardis 逐笔数据,再让 LLM 自动生成策略日报,是当前国内团队最稳的链路。本文给出可直接复制的 Python 代码、四家数据/模型供应商对比表、3 类套利信号回测框架,以及我在 2024 Q3 实盘接入时踩过的所有坑。先放结论:

如果你刚准备搭这套系统,首选 立即注册 HolySheep,注册即送免费额度,微信/支付宝可充,¥1=$1 无汇损。

HolySheep Tardis 中转 vs 官方 Tardis.dev vs 竞品数据中转

维度HolySheep(中转)Tardis.dev(官方直连)竞品 A(国内中转小厂)竞品 B(币coin 自建)
Deribit 逐笔延迟(国内)46ms P501800ms P50210ms P50680ms 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 原始推送里的 ivdeltagammavega 字段都解析好了,不需要再用 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

三、套利检测与 Walk-Forward 回测

相关资源

相关文章