Die Implied Volatility Surface (IV Surface) des Bitcoin ist das wichtigste Werkzeug für jeden Quant, der Optionsstrategien auf Deribit entwickelt. In diesem Tutorial zeige ich Ihnen Schritt für Schritt, wie Sie eine vollständige IV-Matrix aus Deribits historischer Optionskette extrahieren, normalisieren und mit HolySheep AI als KI-Co-Prozessor effizient verarbeiten – inklusive verifizierter 2026-Preise, ehrlicher Kostenrechnung und erprobter Fehlerbehandlung.

Warum dieses Thema 2026 hochrelevant ist

Deribit veröffentlicht täglich Millionen Optionskontrakte. Wer hier eine IV Surface baut, steht vor drei Problemen: API-Rate-Limits, Datenbereinigung (Strikes, Moneyness, Verfallstage) und die kosteneffiziente Interpretation großer JSON-Pakete. Genau dort setzt HolySheep AI an: Mit <50ms Latenz, WeChat/Alipay-Support und einem Wechselkurs von ¥1 = $1 (über 85% Ersparnis gegenüber US-Providern) lassen sich selbst komplexe Marktdaten-Strukturen in Sekunden analysieren.

Voraussetzungen

Schritt 1 — Deribit historische Optionskette abrufen

Deribit stellt unter https://history.deribit.com/api/v2 ein kostenloses, ratenlimitiertes Archiv bereit. Der folgende Code holt den gesamten Options-Chain für BTC mit einem Verfallstag:

import requests
import pandas as pd
from datetime import datetime, timezone

BASE = "https://history.deribit.com/api/v2"

def fetch_option_chain(currency: str = "BTC", expired: bool = True) -> pd.DataFrame:
    """
    Holt die vollständige historische Optionskette von Deribit.
    expired=True liefert auch ausgelaufene Kontrakte -> ideal für IV-Surface-Building.
    """
    instruments = requests.get(
        f"{BASE}/get_instruments",
        params={"currency": currency, "kind": "option", "expired": str(expired).lower()},
        timeout=30,
    ).json()["result"]

    rows = []
    for ins in instruments:
        # Nur tagesendliche Snapshots (daily) reduzieren Datenmenge enorm
        trades = requests.get(
            f"{BASE}/get_last_trades_by_instrument_and_time",
            params={
                "instrument_name": ins["instrument_name"],
                "start_timestamp": int(datetime(2025, 1, 1, tzinfo=timezone.utc).timestamp() * 1000),
                "end_timestamp":   int(datetime(2026, 1, 1, tzinfo=timezone.utc).timestamp() * 1000),
                "count": 1000,
            },
            timeout=30,
        ).json()
        for t in trades.get("result", []):
            rows.append({
                "ts":        pd.to_datetime(t["timestamp"], unit="ms", utc=True),
                "instrument": ins["instrument_name"],
                "strike":    ins["strike"],
                "expiry":    pd.to_datetime(ins["expiration_timestamp"], unit="ms", utc=True),
                "type":      ins["option_type"],
                "iv_mark":   t.get("iv", None),
                "price":     t["price"],
                "underlying": t.get("index_price"),
            })
    return pd.DataFrame(rows)

df_chain = fetch_option_chain()
print(f"{len(df_chain):,} Zeilen geladen")
df_chain.to_parquet("btc_options_2025.parquet")

Schritt 2 — IV-Berechnung & Surface-Grid

Nicht jeder Trade enthält iv_mark. Wir rekonstruieren die IV über Black-Scholes-Merton mit py_vollib und bauen daraus ein (Moneyness × Maturity)-Grid:

import numpy as np
from scipy.interpolate import RectBivariateSpline
from py_vollib.black_scholes_merton.implied_volatility import implied_volatility as bsm_iv

def reconstruct_iv(row, r=0.045):
    try:
        flag = "c" if row["type"] == "call" else "p"
        T = (row["expiry"] - row["ts"]).total_seconds() / (365.25 * 24 * 3600)
        return bsm_iv(
            price=row["price"], S=row["underlying"],
            K=row["strike"], t=max(T, 1/365), r=r, flag=flag
        )
    except Exception:
        return np.nan

df_chain["iv_calc"] = df_chain.apply(reconstruct_iv, axis=1)
df_chain["iv"] = df_chain["iv_mark"].fillna(df_chain["iv_calc"])
df_chain = df_chain.dropna(subset=["iv"]).query("0.1 < iv < 3.0")

Surface-Grid bauen

def build_surface(df, expiry_ts): sub = df[df["expiry"] == expiry_ts].copy() sub["moneyness"] = sub["strike"] / sub["underlying"] pivot = sub.pivot_table(index="moneyness", columns="T", values="iv", aggfunc="mean") return pivot.sort_index() df_chain["T"] = (df_chain["expiry"] - df_chain["ts"]).dt.total_seconds() / (365.25 * 24 * 3600) expiries = sorted(df_chain["expiry"].unique())[:6] surface_grid = {exp: build_surface(df_chain, exp) for exp in expiries}

Verwandte Ressourcen

Verwandte Artikel