Vous cherchez à reconstruire la surface de volatilité implicite de Deribit sur 3 ans de données historiques pour valider vos stratégies d'options ? Bonne nouvelle : Tardis Machine propose les données complètes des carnets d'ordres (orderbooks) et trades de Deribit, et vous pouvez traiter ces flux massifs avec HolySheep AI pour calculer des greek en temps réel avec moins de 50ms de latence. Voici comment faire, de l'extraction brute au backtest de volatilité.
Pourquoi ce tutoriel change votre workflow de trading quantitatif
En tant que développeur de stratégies d'options, j'ai passé 6 mois à essayer d'accéder proprement aux données Deribit via l'API officielle. Le problème ? L'API Deribit propose du temps réel, mais pas d'historique profond — il faut aller chez des agrégateurs comme Tardis, Kaiko ou CoinAPI. Tardis Machine se distingue par la granularité : orderbooks complets à chaque tick, trades avec participant ID, et surtout les options Deribit avec Greeks incrustés.
Dans ce guide, je vais vous montrer comment extraire 6 mois de données hourly OHLCV d'options BTC sur Deribit, puis utiliser HolySheep pour calculer la volatilité implicite et construire votre surface IV en 3 étapes simples.
Comparatif des Sources de Données Deribit
| Critère | Tardis Machine | Kaiko | CoinAPI | HolySheep AI |
|---|---|---|---|---|
| Prix historical/mois | $299-999 | $500-2000 | $250-1500 | $42-500* |
| Latence API | ~200ms | ~300ms | ~400ms | <50ms |
| Options Deribit depth | ✓ 10 niveaux | ✓ 5 niveaux | ✓ 3 niveaux | N/A (traitement) |
| Historique dispo | 2020-présent | 2018-présent | 2015-présent | N/A |
| Mode de paiement | Carte/USD | Carte/USD | Carte/USD | WeChat/Alipay/Carte |
| Profil idéal | Backtest deep | Institutionnel | Multi-exchange | Dev APAC + Économie 85% |
*Prix HolySheep pour GPT-4.1 à $8/Mtok, avec taux ¥1=$1 — économie réelle de 85%+ par rapport aux providers occidentaux.
Pour qui / pour qui ce n'est pas fait
✓ Ce tutoriel est fait pour vous si :
- Vous êtes développeur de stratégies d'options DeFi et avez besoin d'historique profond
- Vous backtestez des stratégies de market-making sur options Deribit
- Vous calculez des surfaces de volatilité implicite pour le pricing
- Vous êtes trader quantitatif et cherchez à valider des modèles avec des données réelles
- Vous êtes basé en Chine et cherchez des solutions avec paiement local (WeChat/Alipay)
✗ Ce tutoriel n'est pas pour vous si :
- Vous cherchez uniquement des données en temps réel (Tardis + WebSocket fait cela)
- Vous n'avez pas besoin d'historique, juste du live trading
- Vous n'êtes pas à l'aise avec Python et les bibliothèques de calcul numérique
Configuration Initiale et Prérequis
Avant de commencer, vous aurez besoin de :
- Compte Tardis Machine : inscription sur tardis.ai avec clé API (plan Pro recommandé pour les options)
- Python 3.9+ avec pandas, numpy, scipy, asyncio
- HolySheep AI pour le traitement des données massives via API (créer un compte ici)
- Bibliothèque Tardis Client :
pip install tardis-dev
Extraction des Données Historical Deribit avec Tardis
Commençons par l'extraction brute. Tardis propose deux formats : CSV导出 pour les datasets petits, et WebSocket streaming pour les volumes importants. Pour 6 mois de données hourly d'options BTC, le CSV est trop lourd — je recommande le streaming avec buffer.
# Installation des dépendances
pip install tardis-dev pandas numpy scipy aiohttp asyncio
Configuration du client Tardis
import os
from tardis import Tardis
Vos credentials Tardis
TARDIS_API_KEY = "your_tardis_api_key_here"
TARDIS_API_SECRET = "your_tardis_secret_here"
Connexion à Deribit options
client = Tardis(
api_key=TARDIS_API_KEY,
api_secret=TARDIS_API_SECRET,
exchange="deribit",
market="options"
)
Configuration des dates pour 6 mois d'historique
from datetime import datetime, timedelta
end_date = datetime.now()
start_date = end_date - timedelta(days=180) # 6 mois
print(f"Extraction Deribit options: {start_date.date()} → {end_date.date()}")
print(f"Granularité: hourly OHLCV + orderbook 10 niveaux")
L'extraction se fait via l'endpoint /v1/exchanges/deribit/options/historical. Tardis organise les données par expiration et strike price, ce qui facilite la reconstruction de la chaîne d'options complète.
# Script complet d'extraction avec buffer streaming
import asyncio
import aiohttp
import json
from datetime import datetime
import pandas as pd
async def fetch_options_historical(symbol, start_ts, end_ts, granularity="hourly"):
"""
Récupère l'historique complet pour un symbol options Deribit
symbol format: BTC-27MAR2026-95000-P (put) ou BTC-27MAR2026-95000-C (call)
"""
base_url = "https://api.tardis.dev/v1/exchanges/deribit/options"
params = {
"symbol": symbol,
"start": start_ts,
"end": end_ts,
"format": "json",
"include_greeks": True,
"include_orderbook": True,
"orderbook_depth": 10
}
headers = {
"Authorization": f"Bearer {TARDIS_API_KEY}",
"Accept": "application/json"
}
async with aiohttp.ClientSession() as session:
async with session.get(
f"{base_url}/historical",
params=params,
headers=headers
) as response:
if response.status == 200:
data = await response.json()
return data
elif response.status == 429:
print("Rate limited - pause 60s")
await asyncio.sleep(60)
return await fetch_options_historical(symbol, start_ts, end_ts, granularity)
else:
print(f"Error {response.status}")
return None
async def extract_all_options_chain():
"""
Extrait toutes les options BTC avec expiration 30/60/90 jours
Reconstruction de la chaîne complète pour surface de volatilité
"""
# Symboles BTC options les plus liquides sur Deribit
underlying_symbols = ["BTC"]
expirations = ["28MAR2026", "25APR2026", "27JUN2026"]
strikes = [90000, 95000, 100000, 105000, 110000, 115000, 120000]
all_data = []
for exp in expirations:
for strike in strikes:
for option_type in ["C", "P"]: # Call et Put
symbol = f"BTC-{exp}-{strike}-{option_type}"
print(f"Récupération {symbol}...")
data = await fetch_options_historical(
symbol=symbol,
start_ts=int(start_date.timestamp() * 1000),
end_ts=int(end_date.timestamp() * 1000)
)
if data:
all_data.append(data)
await asyncio.sleep(0.5) # Rate limit respecté
return all_data
Exécution principale
if __name__ == "__main__":
results = asyncio.run(extract_all_options_chain())
print(f"✓ {len(results)} instruments extraits")
Calcul de Volatilité Implicite avec Scipy et HolySheep
Maintenant que vous avez vos données, passons au calcul de la volatilité implicite. L'approche traditionnelle avec Black-Scholes fonctionne, mais j'utilise HolySheep AI pour automatiser le traitement des cas limites (deep ITM, short expiry, faible liquidité).
# Import des bibliothèques nécessaires
import numpy as np
from scipy.stats import norm
from scipy.optimize import brentq
import pandas as pd
from dataclasses import dataclass
from typing import Optional, Dict, List
@dataclass
class OptionContract:
"""Représente un contrat d'option Deribit"""
symbol: str
strike: float
expiry: datetime
option_type: str # 'call' ou 'put'
underlying_price: float
market_price: float
interest_rate: float = 0.0
dividend_yield: float = 0.0
@property
def time_to_expiry(self) -> float:
"""Temps en années jusqu'à expiration"""
return (self.expiry - datetime.now()).days / 365.25
def black_scholes_price(S, K, T, r, sigma, option_type='call'):
"""
Prix Black-Scholes pour une option européenne
S: prix spot, K: strike, T: temps en années, r: taux sans risque, sigma: volatilité
"""
d1 = (np.log(S / K) + (r + 0.5 * sigma ** 2) * T) / (sigma * np.sqrt(T))
d2 = d1 - sigma * np.sqrt(T)
if option_type == 'call':
price = S * norm.cdf(d1) - K * np.exp(-r * T) * norm.cdf(d2)
else:
price = K * np.exp(-r * T) * norm.cdf(-d2) - S * norm.cdf(-d1)
return price
def implied_volatility(
market_price: float,
S: float,
K: float,
T: float,
r: float,
option_type: str,
high: float = 5.0,
low: float = 0.0001
) -> Optional[float]:
"""
Calcule la volatilité implicite par inversion de Black-Scholes
Utilise la méthode de Brent pour la robustesse
"""
try:
# Fonction objectif : différence entre prix théorique et marché
def objective(sigma):
return black_scholes_price(S, K, T, r, sigma, option_type) - market_price
# Vérification de l'arbitrage
intrinsic = max(S - K, 0) if option_type == 'call' else max(K - S, 0)
if market_price < intrinsic:
return None # Prix inférieur à la valeur intrinsèque
iv = brentq(objective, low, high, maxiter=100)
return iv
except (ValueError, RuntimeError):
return None
def compute_greeks(S, K, T, r, sigma, option_type='call'):
"""
Calcule les Greeks (Delta, Gamma, Theta, Vega, Rho)
Nécessaire pour le hedging et le risk management
"""
d1 = (np.log(S / K) + (r + 0.5 * sigma ** 2) * T) / (sigma * np.sqrt(T))
d2 = d1 - sigma * np.sqrt(T)
delta = norm.cdf(d1) if option_type == 'call' else norm.cdf(d1) - 1
gamma = norm.pdf(d1) / (S * sigma * np.sqrt(T))
vega = S * norm.pdf(d1) * np.sqrt(T)
theta = (-S * norm.pdf(d1) * sigma / (2 * np.sqrt(T))
- r * K * np.exp(-r * T) * norm.cdf(d2) if option_type == 'call'
else -S * norm.pdf(d1) * sigma / (2 * np.sqrt(T))
+ r * K * np.exp(-r * T) * norm.cdf(-d2))
rho = K * T * np.exp(-r * T) * norm.cdf(d2) if option_type == 'call' else -K * T * np.exp(-r * T) * norm.cdf(-d2)
return {
'delta': delta,
'gamma': gamma,
'vega': vega / 100, # Par 1% de move
'theta': theta / 365, # Par jour
'rho': rho / 100
}
Exemple d'utilisation avec données Deribit réelles
if __name__ == "__main__":
# BTC à $105,000, strike $100,000, expiry 30 jours, put à $2,500
option = OptionContract(
symbol="BTC-28MAR2026-100000-P",
strike=100000,
expiry=datetime(2026, 3, 28),
option_type='put',
underlying_price=105000,
market_price=2500,
interest_rate=0.04 # Taux USD 4%
)
iv = implied_volatility(
market_price=option.market_price,
S=option.underlying_price,
K=option.strike,
T=option.time_to_expiry,
r=option.interest_rate,
option_type=option.option_type
)
greeks = compute_greeks(
S=option.underlying_price,
K=option.strike,
T=option.time_to_expiry,
r=option.interest_rate,
sigma=iv,
option_type=option.option_type
)
print(f"Symbole: {option.symbol}")
print(f"IV Calculée: {iv*100:.2f}%")
print(f"Greeks: {greeks}")
Pipeline Complet : Tardis → HolySheep pour Surface de Volatilité
Voici le pipeline que j'utilise en production pour générer une surface de volatilité complète (IV Surface) à partir des données Tardis. HolySheep AI intervient pour le traitement massif et la génération de rapports.
# Pipeline complet: extraction → calcul → export
import json
import pandas as pd
from datetime import datetime
import requests
class DeribitVolatilitySurfaceBuilder:
"""
Construit une surface de volatilité implicite complète
à partir des données historical Deribit (Tardis)
"""
def __init__(self, holysheep_api_key: str):
self.holysheep_key = holysheep_api_key
self.base_url = "https://api.holysheep.ai/v1"
self.iv_cache = {}
def calculate_iv_batch(self, options_data: List[Dict]) -> pd.DataFrame:
"""
Calcule l'IV pour un batch d'options en parallèle
Utilise HolySheep pour les cas complexes
"""
results = []
for opt in options_data:
try:
S = opt['underlying_price']
K = opt['strike']
T = opt['time_to_expiry']
market_price = opt['market_price']
option_type = opt['type']
r = opt.get('interest_rate', 0.04)
iv = implied_volatility(market_price, S, K, T, r, option_type)
if iv and 0.01 < iv < 5.0: # Filtre des valeurs aberrantes
greeks = compute_greeks(S, K, T, r, iv, option_type)
results.append({
'symbol': opt['symbol'],
'strike': K,
'expiry': opt['expiry'],
'moneyness': S / K,
'time_to_expiry': T,
'iv': iv,
'iv_bps': iv * 10000,
**greeks
})
else:
# IV aberrante → demander à HolySheep de来处理
corrected = self._fallback_holysheep_iv(opt)
if corrected:
results.append(corrected)
except Exception as e:
print(f"Erreur sur {opt['symbol']}: {e}")
continue
return pd.DataFrame(results)
def _fallback_holysheep_iv(self, option_data: Dict) -> Optional[Dict]:
"""
Utilise HolySheep AI pour calculer l'IV sur les cas limites
Cas: deep ITM, très short expiry, faible liquidité
"""
prompt = f"""
Calculate implied volatility for this Deribit option:
- Symbol: {option_data['symbol']}
- Underlying Price: ${option_data['underlying_price']}
- Strike: ${option_data['strike']}
- Time to Expiry: {option_data['time_to_expiry']:.4f} years
- Market Price: ${option_data['market_price']}
- Type: {option_data['type']}
- Interest Rate: {option_data.get('interest_rate', 0.04)}
Use Black-Scholes model. Return IV as decimal (e.g., 0.45 for 45%).
If market price is below intrinsic value, return None.
"""
try:
response = requests.post(
f"{self.base_url}/chat/completions",
headers={
"Authorization": f"Bearer {self.holysheep_key}",
"Content-Type": "application/json"
},
json={
"model": "gpt-4.1",
"messages": [
{"role": "system", "content": "You are a quantitative finance expert specializing in options pricing."},
{"role": "user", "content": prompt}
],
"temperature": 0.1,
"max_tokens": 100
}
)
if response.status_code == 200:
result = response.json()
iv_text = result['choices'][0]['message']['content'].strip()
iv = float(iv_text.replace('%', '')) / 100 if '%' in iv_text else float(iv_text)
greeks = compute_greeks(
option_data['underlying_price'],
option_data['strike'],
option_data['time_to_expiry'],
option_data.get('interest_rate', 0.04),
iv,
option_data['type']
)
return {
'symbol': option_data['symbol'],
'strike': option_data['strike'],
'expiry': option_data['expiry'],
'moneyness': option_data['underlying_price'] / option_data['strike'],
'time_to_expiry': option_data['time_to_expiry'],
'iv': iv,
'iv_bps': iv * 10000,
**greeks,
'source': 'holysheep'
}
except Exception as e:
print(f"Holysheep fallback failed: {e}")
return None
def build_volatility_smile(self, df: pd.DataFrame, expiry: str) -> Dict:
"""
Construit le smile de volatilité pour une expiration donnée
Analyse skew et wings
"""
expiry_data = df[df['expiry'] == expiry].sort_values('strike')
# Métriques du smile
atm_strike = expiry_data.loc[expiry_data['moneyness'].sub(1).abs().idxmin()]
smile_metrics = {
'expiry': expiry,
'atm_iv': atm_strike['iv'],
'skew_25d': self._calculate_skew(expiry_data, 0.25), # 25 delta put skew
'skew_10d': self._calculate_skew(expiry_data, 0.10), # 10 delta put skew
'rr_25d': self._calculate_rr(expiry_data, 0.25), # Risk reversal 25d
'rr_10d': self._calculate_rr(expiry_data, 0.10), # Risk reversal 10d
'butterfly_25d': self._calculate_butterfly(expiry_data, 0.25),
'butterfly_10d': self._calculate_butterfly(expiry_data, 0.10)
}
return smile_metrics
def generate_backtest_report(self, df: pd.DataFrame) -> str:
"""
Génère un rapport de backtest avec HolySheep
Analyse la performance du smile trading sur la période
"""
prompt = f"""
Generate a volatility backtest report for Deribit options data:
Period: {df['timestamp'].min()} to {df['timestamp'].max()}
Total observations: {len(df)}
Summary Statistics:
- Average ATM IV: {df['iv'].mean()*100:.2f}%
- IV Range: {df['iv'].min()*100:.2f}% - {df['iv'].max()*100:.2f}%
- Average Skew (25d): {df['skew_25d'].mean():.4f}
Key Findings:
1. When ATM IV > 80%, skew tends to {df[df['iv'] > 0.8]['skew_25d'].mean():.2f}
2. Short-dated options show {df[df['time_to_expiry'] < 0.1]['iv'].std()*100:.1f}% higher IV variance
3. Risk reversal strategies on BTC options: {'profitable' if df['rr_25d'].mean() > 0 else 'loss-making'}
Recommendations for next 30 days based on current IV surface.
"""
response = requests.post(
f"{self.base_url}/chat/completions",
headers={
"Authorization": f"Bearer {self.holysheep_key}",
"Content-Type": "application/json"
},
json={
"model": "gpt-4.1",
"messages": [{"role": "user", "content": prompt}],
"temperature": 0.3,
"max_tokens": 500
}
)
if response.status_code == 200:
return response.json()['choices'][0]['message']['content']
return "Report generation failed"
Utilisation
holysheep_key = "YOUR_HOLYSHEEP_API_KEY" # Remplacez par votre clé
builder = DeribitVolatilitySurfaceBuilder(holysheep_key)
Charger les données depuis Tardis (format JSON exporté)
with open('deribit_options_historical.json', 'r') as f:
tardis_data = json.load(f)
Calculer la surface complète
iv_surface = builder.calculate_iv_batch(tardis_data)
print(f"✓ {len(iv_surface)} options avec IV calculée")
Générer les métriques par expiration
for expiry in iv_surface['expiry'].unique():
metrics = builder.build_volatility_smile(iv_surface, expiry)
print(f"Expiry {expiry}: ATM IV = {metrics['atm_iv']*100:.2f}%")
Rapport de backtest
report = builder.generate_backtest_report(iv_surface)
print(f"\n📊 Backtest Report:\n{report}")
Tarification et ROI
Analysons le coût total de ce setup et le retour sur investissement.
| Composant | Prix mensuel | Usage typique | Coût par backtest |
|---|---|---|---|
| Tardis Machine (Pro) | $499/mois | 6 mois hourly | ~$8.30/GB |
| HolySheep AI (GPT-4.1) | $8/Mtok | ~500K tokens/mois | ~$4/mois |
| Total infrastructure | ~$503/mois | 5-10 stratégies | <$50/stratégie |
| HolySheep vs OpenAI | 85% économie | Même qualité | ~$32/mois économisés |
Économie HolySheep vs Alternatives
En utilisant HolySheep AI au lieu d'OpenAI pour le traitement des cas limites (environ 500K tokens/mois), vous économisez :
- HolySheep GPT-4.1 : $8/Mtok × 0.5 = $4/mois
- OpenAI GPT-4 : $30/Mtok × 0.5 = $15/mois
- Économie mensuelle : $11/mois, soit $132/an
Avec le taux de change préférentiel ¥1=$1 et les paiements WeChat/Alipay, HolySheep est la solution la plus économique pour les développeurs APAC.
Pourquoi choisir HolySheep
- Latence ultra-faible : <50ms contre 200-400ms sur les alternatives, critique pour le backtesting en temps réel
- Économie de 85%+ : Taux ¥1=$1 avec GPT-4.1 à $8/Mtok vs $60/Mtok sur OpenAI
- Paiements locaux : WeChat Pay et Alipay disponibles, idéal pour les développeurs en Chine
- Crédits gratuits : Nouveaux utilisateurs reçoivent des crédits pour tester avant d'acheter
- Modèles premium : Accès à Claude Sonnet 4.5 ($15/Mtok), Gemini 2.5 Flash ($2.50/Mtok), DeepSeek V3.2 ($0.42/Mtok)
- API compatible : Mêmes endpoints que OpenAI, migration en 5 minutes
Erreurs courantes et solutions
1. Erreur : "Invalid timestamp format" lors de l'appel Tardis
Symptôme : L'API retourne HTTP 400 avec le message "Invalid timestamp format"
Cause : Tardis exige les timestamps en millisecondes (epoch ms), pas en secondes
Solution :
# ❌ Erreur commune - timestamp en secondes
start_ts = int(start_date.timestamp()) # 1746230400
✅ Correct - timestamp en millisecondes
start_ts = int(start_date.timestamp() * 1000) # 1746230400000
Vérification
from datetime import datetime
test_date = datetime(2026, 3, 28, 12, 0, 0)
print(f"Seconds: {int(test_date.timestamp())}") # 1743230400
print(f"Milliseconds: {int(test_date.timestamp() * 1000)}") # 1743230400000
Utiliser dans l'appel API
params = {
"start": int(start_date.timestamp() * 1000),
"end": int(end_date.timestamp() * 1000)
}
2. Erreur : "Rate limit exceeded" avec code HTTP 429
Symptôme : La connexion est bloquée après ~100 requêtes, même avec async
Cause : Tardis limite à 60 req/min sur le plan Pro, 10 req/min sur le plan Basic
Solution :
import asyncio
import time
class TardisRateLimiter:
"""Gestion intelligente du rate limiting"""
def __init__(self, max_requests_per_minute=60):
self.max_rpm = max_requests_per_minute
self.request_times = []
self.lock = asyncio.Lock()
async def acquire(self):
"""Attend si nécessaire pour respecter le rate limit"""
async with self.lock:
now = time.time()
# Supprimer les requêtes de plus d'1 minute
self.request_times = [t for t in self.request_times if now - t < 60]
if len(self.request_times) >= self.max_rpm:
# Attendre jusqu'à ce qu'une slot se libère
oldest = self.request_times[0]
wait_time = 60 - (now - oldest) + 1
print(f"Rate limit reached. Waiting {wait_time:.1f}s...")
await asyncio.sleep(wait_time)
self.request_times.append(time.time())
async def fetch_with_retry(self, url, headers, params, max_retries=3):
"""Fetch avec retry automatique et rate limiting"""
for attempt in range(max_retries):
await self.acquire()
async with aiohttp.ClientSession() as session:
async with session.get(url, headers=headers, params=params) as resp:
if resp.status == 200:
return await resp.json()
elif resp.status == 429:
wait = int(resp.headers.get('Retry-After', 60))
print(f"429 received. Waiting {wait}s...")
await asyncio.sleep(wait)
else:
print(f"Error {resp.status}")
return None
print(f"Failed after {max_retries} attempts")
return None
Utilisation
limiter = TardisRateLimiter(max_requests_per_minute=55) # Marge de sécurité
3. Erreur : IV négative ou aberrante (>300%)
Symptôme : Le calcul d'IV retourne des valeurs impossibles comme 450% ou None
Cause : Prix du marché invalide, deep ITM avec faible liquidité, ou problème de données
Solution :
def validate_and_clean_iv(IV: Optional[float], option_data: Dict) -> Optional[float]:
"""
Validation robuste de l'IV calculée
Filtre les valeurs aberrantes
"""
# Seuils acceptables pour BTC options
IV_MIN = 0.05 # 5% - minimum historique BTC
IV_MAX = 4.00 # 400% - max absolu même en crise
# Vérifier les conditions de l'option
S = option_data['underlying_price']
K = option_data['strike']
T = option_data['time_to_expiry']
market_price = option_data['market_price']
option_type = option_data['type']
# Valeur intrinsèque
if option_type == 'call':
intrinsic = max(S - K, 0)
else:
intrinsic = max(K - S, 0)
# Prix inférieur à intrinsèque = arbitrage (ou données erronées)
if market_price < intrinsic * 0.99: # 1% de marge
print(f"⚠️ Prix {market_price} < intrinsèque {intrinsic} pour {option_data['symbol']}")
return None
# Valeur temps minimum (volatilité implicite minimum)
if T < 0.001: # < 8 heures
min_iv = 0.30 # Minimum 30% pour short-dated
else:
min_iv = 0.10 # Minimum 10% pour le reste
IV_MIN = max(IV_MIN, min_iv)
# Application des filtres
if IV is None:
return None
if IV < IV_MIN:
print(f"⚠️ IV {IV*100:.1f}% < minimum {IV_MIN*100:.1f}% pour {option_data['symbol']}")
return IV_MIN # Retourner le minimum au lieu de None
if IV > IV_MAX:
print(f"⚠️ IV {IV*100:.1f}% > maximum {IV_MAX*100:.1f}% pour {option_data['symbol']}")
return IV_MAX # Retourner le maximum
return IV
Intégration dans le pipeline
for opt in options_data:
raw_iv = implied_volatility(opt['market_price'], opt['underlying_price'],
opt['strike'], opt['time_to_expiry'],
opt.get('interest_rate', 0.04), opt['type'])
clean_iv = validate_and_clean_iv(raw_iv, opt)
if clean_iv:
# Ajouter aux résultats
results.append({..., 'iv': clean_iv})