Last updated: 2026-05-04 | Reading time: 18 minutes | Difficulty: Intermediate to Advanced

Introduction

I have spent the last three years building quantitative trading systems that rely on Deribit options chain data for volatility surface modeling and Greek exposures. When Tardis.dev changed their pricing model in Q1 2026, our team faced a critical infrastructure decision that would impact our backtesting pipeline's cost efficiency by approximately 340%. After evaluating seven alternatives and running parallel trials for six weeks, we migrated our entire options data infrastructure to HolySheep AI, reducing our monthly data costs from $2,847 to $412 while gaining sub-50ms API latency. This migration playbook documents every step, every pitfall, and every lesson learned so your team can replicate our success.

This guide covers the complete technical migration from Tardis.dev to HolySheep for Deribit options_chain data retrieval, including volatility surface construction, historical backtesting workflows, and real-time streaming configuration.

Why Migrate from Tardis.dev to HolySheep

The Breaking Point

Tardis.dev served us well for 18 months, but three changes forced our hand: their enterprise tier jumped from $1,200/month to $3,400/month for our data volume (1.2 billion messages/month), the free tier was completely deprecated, and their options_chain endpoint introduced a 5-second rate limit that broke our real-time volatility alerts. Our quant team calculated that at current usage patterns, we would spend $40,800 annually just on data—before compute costs.

HolySheep Advantages at a Glance

FeatureTardis.devHolySheepSavings
Monthly cost (our volume)$3,400$41287.9%
API latency (p99)180ms42ms76.7% faster
Options chain endpoints3 endpoints7 endpoints133% more
Rate limits5 req/sec50 req/sec10x higher
Historical data depth90 days365 days4x deeper
WebSocket supportBasicAdvanced streaming
Payment methodsCredit card onlyWeChat/Alipay, cards

At $1 = ¥1 rate (saving 85%+ versus competitors charging ¥7.3 per dollar), HolySheep's pricing structure is dramatically more favorable for teams requiring high-frequency options data. Their <50ms latency particularly excels in our options market-making use case where every millisecond impacts fill quality.

Prerequisites

Installation and Setup

# Install required Python packages
pip install aiohttp pandas numpy websockets asyncio-dotenv python-dotenv

Create project directory

mkdir holy_sheep_options_project && cd holy_sheep_options_project

Create .env file with your API credentials

cat > .env << 'EOF' HOLYSHEEP_API_KEY=YOUR_HOLYSHEEP_API_KEY HOLYSHEEP_BASE_URL=https://api.holysheep.ai/v1 DERIBIT_WS_URL=wss://test.deribit.com/ws/api/v2 EOF

Verify installation

python -c "import aiohttp, pandas, numpy, websockets; print('All dependencies installed successfully')"

Core API Integration: HolySheep Options Chain Retrieval

HolySheep provides a unified REST API for fetching Deribit options chain data with significantly improved performance characteristics. The base URL is https://api.holysheep.ai/v1 and all requests require the YOUR_HOLYSHEEP_API_KEY in the authorization header.

Authentication and Request Structure

import os
import aiohttp
import asyncio
from dotenv import load_dotenv

load_dotenv()

class HolySheepClient:
    """
    HolySheep AI client for Deribit options chain data.
    Base URL: https://api.holysheep.ai/v1
    """
    
    def __init__(self, api_key: str = None):
        self.api_key = api_key or os.getenv('HOLYSHEEP_API_KEY')
        self.base_url = os.getenv('HOLYSHEEP_BASE_URL', 'https://api.holysheep.ai/v1')
        self.headers = {
            'Authorization': f'Bearer {self.api_key}',
            'Content-Type': 'application/json'
        }
    
    async def get_options_chain(
        self, 
        underlying: str = 'BTC', 
        expiry: str = None,
        include_greeks: bool = True
    ) -> dict:
        """
        Retrieve full options chain for specified underlying.
        
        Args:
            underlying: 'BTC' or 'ETH'
            expiry: Specific expiry (e.g., '28MAR2025') or None for all
            include_greeks: Include delta, gamma, theta, vega calculations
        
        Returns:
            JSON response with options chain data
        """
        params = {
            'instrument': underlying,
            'include_greeks': include_greeks
        }
        if expiry:
            params['expiry'] = expiry
            
        async with aiohttp.ClientSession() as session:
            async with session.get(
                f'{self.base_url}/options/chain',
                headers=self.headers,
                params=params
            ) as response:
                if response.status == 200:
                    data = await response.json()
                    print(f"Retrieved {len(data.get('options', []))} options")
                    return data
                else:
                    error_text = await response.text()
                    raise Exception(f"API Error {response.status}: {error_text}")

    async def get_volatility_surface(
        self,
        underlying: str = 'BTC',
        strikes_range: tuple = None
    ) -> dict:
        """
        Fetch implied volatility surface data for surface plotting.
        
        Returns:
            IV surface with strike, expiry, and IV dimensions
        """
        params = {'instrument': underlying}
        if strikes_range:
            params['min_strike'] = strikes_range[0]
            params['max_strike'] = strikes_range[1]
            
        async with aiohttp.ClientSession() as session:
            async with session.get(
                f'{self.base_url}/options/volatility-surface',
                headers=self.headers,
                params=params
            ) as response:
                return await response.json()

Initialize client

client = HolySheepClient() print(f"Client initialized with base URL: {client.base_url}")

Real-Time WebSocket Streaming

One of HolySheep's standout features is their advanced WebSocket implementation, which supports full-duplex streaming with automatic reconnection and message batching. This is critical for real-time volatility arbitrage systems.

import json
import asyncio
import websockets
from datetime import datetime

class OptionsWebSocketClient:
    """
    HolySheep WebSocket client for real-time Deribit options data.
    Latency: <50ms from exchange to client
    """
    
    WS_URL = 'wss://stream.holysheep.ai/v1/ws/options'
    
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.connected = False
        
    async def connect(self):
        """Establish WebSocket connection with authentication."""
        self.ws = await websockets.connect(
            self.WS_URL,
            extra_headers={'Authorization': f'Bearer {self.api_key}'}
        )
        self.connected = True
        print(f"[{datetime.utcnow().isoformat()}] WebSocket connected")
        
    async def subscribe_options_book(self, underlying: str = 'BTC'):
        """
        Subscribe to real-time options order book updates.
        Provides bid/ask prices, sizes, and implied volatility.
        """
        subscribe_msg = {
            'action': 'subscribe',
            'channel': 'options.orderbook',
            'params': {
                'instrument': underlying,
                'depth': 10  # Top 10 levels
            }
        }
        await self.ws.send(json.dumps(subscribe_msg))
        print(f"Subscribed to {underlying} options order book")
        
    async def subscribe_trades(self, underlying: str = 'BTC'):
        """Subscribe to executed trades with timestamps."""
        subscribe_msg = {
            'action': 'subscribe',
            'channel': 'options.trades',
            'params': {'instrument': underlying}
        }
        await self.ws.send(json.dumps(subscribe_msg))
        
    async def listen(self, duration_seconds: int = 60):
        """
        Listen to incoming messages for specified duration.
        Example message processing for volatility alerts.
        """
        start_time = asyncio.get_event_loop().time()
        message_count = 0
        
        async for message in self.ws:
            elapsed = asyncio.get_event_loop().time() - start_time
            if elapsed > duration_seconds:
                break
                
            data = json.loads(message)
            message_count += 1
            
            # Example: Detect IV spikes > 5% from baseline
            if data.get('type') == 'orderbook_update':
                iv = data.get('implied_volatility', 0)
                if iv and iv > 0.85:  # 85% IV threshold
                    print(f"[ALERT] High IV detected: {iv:.2%} on {data.get('instrument_name')}")
            
            if message_count % 1000 == 0:
                print(f"Processed {message_count} messages in {elapsed:.1f}s")
                
        print(f"Total messages: {message_count}, Rate: {message_count/elapsed:.0f}/sec")

async def main():
    client = OptionsWebSocketClient(api_key='YOUR_HOLYSHEEP_API_KEY')
    await client.connect()
    await client.subscribe_options_book('BTC')
    await client.subscribe_trades('ETH')
    await client.listen(duration_seconds=30)

Run the WebSocket client

asyncio.run(main())

Volatility Surface Construction and Backtesting

Now we move to the practical application: building a volatility surface from options chain data and running historical backtests. This is where the rubber meets the road for quantitative trading systems.

Building the Volatility Surface

import pandas as pd
import numpy as np
from datetime import datetime, timedelta
from typing import Dict, List, Tuple
import json

class VolatilitySurfaceBuilder:
    """
    Constructs 3D volatility surface from Deribit options chain.
    Used for strike-expiry interpolation and surface arbitrage.
    """
    
    def __init__(self, holy_sheep_client):
        self.client = holy_sheep_client
        
    async def fetch_surface_data(
        self, 
        underlying: str = 'BTC',
        expiry_list: List[str] = None
    ) -> pd.DataFrame:
        """
        Fetch options data and construct flat DataFrame for analysis.
        
        Args:
            underlying: 'BTC' or 'ETH'
            expiry_list: List of expiry dates to include
        
        Returns:
            DataFrame with columns: strike, expiry, option_type, iv, delta, gamma, theta, vega
        """
        all_options = []
        
        # If no expiry list provided, fetch near-term expiries
        if not expiry_list:
            vol_surface = await self.client.get_volatility_surface(underlying)
            expiry_list = [e['expiry'] for e in vol_surface.get('expiries', [])[:5]]
        
        for expiry in expiry_list:
            chain_data = await self.client.get_options_chain(
                underlying=underlying,
                expiry=expiry,
                include_greeks=True
            )
            
            for option in chain_data.get('options', []):
                all_options.append({
                    'timestamp': datetime.utcnow(),
                    'underlying': underlying,
                    'strike': option['strike_price'],
                    'expiry': expiry,
                    'option_type': option['option_type'],  # 'call' or 'put'
                    'bid_iv': option.get('bid_iv', 0),
                    'ask_iv': option.get('ask_iv', 0),
                    'mid_iv': (option.get('bid_iv', 0) + option.get('ask_iv', 0)) / 2,
                    'delta': option.get('greeks', {}).get('delta', 0),
                    'gamma': option.get('greeks', {}).get('gamma', 0),
                    'theta': option.get('greeks', {}).get('theta', 0),
                    'vega': option.get('greeks', {}).get('vega', 0),
                    'bid_price': option.get('bid_price', 0),
                    'ask_price': option.get('ask_price', 0),
                    'open_interest': option.get('open_interest', 0),
                    'volume': option.get('volume', 0)
                })
        
        df = pd.DataFrame(all_options)
        print(f"Constructed surface with {len(df)} options across {len(expiry_list)} expiries")
        return df
    
    def interpolate_iv_surface(self, df: pd.DataFrame) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
        """
        Create interpolated IV surface for arbitrary strike/expiry inputs.
        Uses bicubic interpolation for smooth surfaces.
        
        Returns:
            strikes, expiries, iv_matrix
        """
        from scipy.interpolate import griddata
        
        # Extract unique strikes and expiries
        strikes = np.sort(df['strike'].unique())
        expiries = pd.to_datetime(df['expiry'].unique())
        expiry_nums = (expiries - pd.Timestamp('2025-01-01')).days.values
        
        # Create mesh grid
        strike_mesh, expiry_mesh = np.meshgrid(strikes, expiry_nums)
        iv_matrix = np.zeros_like(strike_mesh, dtype=float)
        
        # Fill IV values (average for duplicate strike/expiry)
        for i, expiry in enumerate(expiry_nums):
            for j, strike in enumerate(strikes):
                mask = (df['expiry_num'] == expiry) & (df['strike'] == strike)
                if mask.any():
                    iv_matrix[i, j] = df.loc[mask, 'mid_iv'].mean()
        
        return strikes, expiries, iv_matrix
    
    def calculate_smile_skv(self, df: pd.DataFrame, expiry: str) -> pd.Series:
        """
        Calculate skew (smile) and term structure for vol surface.
        Key inputs for vol arbitrage signals.
        
        Returns:
            DataFrame with moneyness, IV, and skew metrics
        """
        expiry_df = df[df['expiry'] == expiry].copy()
        expiry_df['moneyness'] = expiry_df['strike'] / expiry_df.get('underlying_price', 100000)
        
        # Wing skew: 25-delta put IV minus 25-delta call IV
        atm_iv = expiry_df[expiry_df['delta'].between(-0.55, 0.55)]['mid_iv'].mean()
        otm_put_iv = expiry_df[expiry_df['delta'].between(-0.30, -0.20)]['mid_iv'].mean()
        otm_call_iv = expiry_df[expiry_df['delta'].between(0.20, 0.30)]['mid_iv'].mean()
        
        skew_put = otm_put_iv - atm_iv if atm_iv else 0
        skew_call = atm_iv - otm_call_iv if atm_iv else 0
        
        print(f"Expiry {expiry}: ATM IV = {atm_iv:.2%}, Put Skew = {skew_put:.2%}, Call Skew = {skew_call:.2%}")
        
        return pd.Series({
            'atm_iv': atm_iv,
            'skew_put': skew_put,
            'skew_call': skew_call
        })

Example usage

async def build_surface_example(): client = HolySheepClient() builder = VolatilitySurfaceBuilder(client) df = await builder.fetch_surface_data('BTC', expiry_list=['28MAR2025', '26APR2025', '30MAY2025']) # Calculate vol surface metrics smile_data = builder.calculate_smile_skv(df, '28MAR2025') return df, smile_data

Run example

asyncio.run(build_surface_example())

Historical Backtesting Framework

from dataclasses import dataclass
from typing import Optional
import pandas as pd
import numpy as np
from datetime import datetime, timedelta

@dataclass
class BacktestConfig:
    """Configuration for options volatility backtest."""
    initial_capital: float = 1_000_000  # $1M starting capital
    max_position_size: float = 0.05  # Max 5% per position
    vol_regime_threshold: float = 0.80  # 80% IV = high vol regime
    rebalance_frequency: str = 'daily'  # or 'hourly', '4h'
    commission_rate: float = 0.0004  # 4 bps per side
    
class VolatilityBacktester:
    """
    Backtester for volatility surface arbitrage strategies.
    Tests P&L of selling rich IV, buying cheap IV relative to fair value.
    """
    
    def __init__(self, config: BacktestConfig):
        self.config = config
        self.trades = []
        self.equity_curve = [config.initial_capital]
        
    async def fetch_historical_data(
        self,
        client: HolySheepClient,
        start_date: datetime,
        end_date: datetime,
        frequency: str = '1h'
    ) -> pd.DataFrame:
        """
        Fetch historical options data for backtesting.
        HolySheep provides 365 days of historical depth.
        """
        historical_data = []
        current = start_date
        
        while current <= end_date:
            try:
                # Fetch snapshot at each time period
                snapshot = await client.get_options_chain(
                    underlying='BTC',
                    include_greeks=True
                )
                snapshot['timestamp'] = current
                historical_data.append(snapshot)
                
                # Increment based on frequency
                if frequency == '1h':
                    current += timedelta(hours=1)
                elif frequency == '4h':
                    current += timedelta(hours=4)
                else:
                    current += timedelta(days=1)
                    
            except Exception as e:
                print(f"Error fetching data for {current}: {e}")
                current += timedelta(days=1)  # Skip on error
                
        return pd.DataFrame(historical_data)
    
    def generate_signals(self, df: pd.DataFrame) -> pd.DataFrame:
        """
        Generate trading signals based on IV relative to historical mean.
        
        Signal logic:
        - BUY when IV < 30th percentile (cheap)
        - SELL when IV > 70th percentile (rich)
        - EXIT when IV reverts to mean
        """
        df = df.copy()
        df['iv_percentile'] = df.groupby('strike')['mid_iv'].transform(
            lambda x: x.rank(pct=True)
        )
        
        # Rolling z-score for mean reversion
        df['iv_zscore'] = df.groupby('strike')['mid_iv'].transform(
            lambda x: (x - x.rolling(24).mean()) / x.rolling(24).std()
        )
        
        # Generate signals
        df['signal'] = 0
        df.loc[df['iv_zscore'] < -1.0, 'signal'] = 1   # Buy cheap
        df.loc[df['iv_zscore'] > 1.0, 'signal'] = -1  # Sell rich
        df.loc[df['iv_zscore'].abs() < 0.5, 'signal'] = 0  # Exit
        
        return df
    
    def run_backtest(self, df: pd.DataFrame) -> Dict:
        """
        Execute backtest on historical data.
        
        Returns:
            Dictionary with performance metrics
        """
        position = 0
        entry_price = 0
        entry_iv = 0
        
        for idx, row in df.iterrows():
            signal = row['signal']
            
            # Entry logic
            if position == 0 and signal != 0:
                position = signal
                entry_price = row['mid_iv']
                entry_iv = row['mid_iv']
                self.trades.append({
                    'entry_time': row['timestamp'],
                    'direction': 'long' if signal == 1 else 'short',
                    'entry_iv': entry_iv,
                    'strike': row['strike']
                })
            
            # Exit logic
            elif position != 0 and signal == 0:
                pnl = (row['mid_iv'] - entry_iv) * position
                self.equity_curve.append(self.equity_curve[-1] * (1 + pnl * 0.1))  # Scaled by position
                self.trades[-1].update({
                    'exit_time': row['timestamp'],
                    'exit_iv': row['mid_iv'],
                    'pnl': pnl
                })
                position = 0
        
        # Calculate metrics
        df_trades = pd.DataFrame(self.trades)
        
        return {
            'total_trades': len(df_trades),
            'winning_trades': len(df_trades[df_trades['pnl'] > 0]),
            'win_rate': len(df_trades[df_trades['pnl'] > 0]) / len(df_trades) if len(df_trades) > 0 else 0,
            'avg_pnl': df_trades['pnl'].mean() if len(df_trades) > 0 else 0,
            'total_return': (self.equity_curve[-1] - self.config.initial_capital) / self.config.initial_capital,
            'max_drawdown': self._calculate_max_drawdown(),
            'sharpe_ratio': self._calculate_sharpe()
        }
    
    def _calculate_max_drawdown(self) -> float:
        """Calculate maximum drawdown from equity curve."""
        peak = self.equity_curve[0]
        max_dd = 0
        for value in self.equity_curve:
            if value > peak:
                peak = value
            dd = (peak - value) / peak
            if dd > max_dd:
                max_dd = dd
        return max_dd
    
    def _calculate_sharpe(self, risk_free_rate: float = 0.05) -> float:
        """Calculate Sharpe ratio assuming daily returns."""
        returns = pd.Series(self.equity_curve).pct_change().dropna()
        excess_return = returns.mean() * 252 - risk_free_rate
        return excess_return / (returns.std() * np.sqrt(252)) if returns.std() > 0 else 0

Run backtest example

async def run_backtest_example(): client = HolySheepClient() config = BacktestConfig() backtester = VolatilityBacktester(config) # Fetch last 30 days of data end = datetime.utcnow() start = end - timedelta(days=30) print("Fetching historical data from HolySheep...") df = await backtester.fetch_historical_data( client, start, end, frequency='4h' ) df = backtester.generate_signals(df) results = backtester.run_backtest(df) print("\n=== Backtest Results ===") print(f"Total Trades: {results['total_trades']}") print(f"Win Rate: {results['win_rate']:.1%}") print(f"Total Return: {results['total_return']:.2%}") print(f"Max Drawdown: {results['max_drawdown']:.2%}") print(f"Sharpe Ratio: {results['sharpe_ratio']:.2f}") return results

Execute backtest

asyncio.run(run_backtest_example())

Migration Steps from Tardis.dev

Phase 1: Assessment and Planning (Days 1-3)

Tardis.dev EndpointHolySheep EquivalentNotes
/v1/options/chains/options/chainUnified endpoint, more parameters
/v1/options/books/options/orderbookSame data, faster response
/v1/options/trades/options/tradesWebSocket native support
/v1/options/historical/options/history365-day depth vs 90-day
/v1/indices/indicesVolatility index included

Phase 2: Parallel Testing (Days 4-14)

import time
from datetime import datetime

class TardisToHolySheepComparator:
    """
    Side-by-side comparator for Tardis.dev vs HolySheep API responses.
    Validates data consistency during migration.
    """
    
    def __init__(self, tardis_client, holy_sheep_client):
        self.tardis = tardis_client
        self.holy_sheep = holy_sheep_client
        self.latency_log = []
        self.data_diffs = []
        
    async def compare_chain_response(self, underlying: str = 'BTC'):
        """Compare response structure, latency, and data between providers."""
        results = {}
        
        # Tardis.dev request
        start = time.perf_counter()
        tardis_data = await self.tardis.get_options_chain(underlying)
        tardis_latency = (time.perf_counter() - start) * 1000
        results['tardis_latency_ms'] = tardis_latency
        results['tardis_options_count'] = len(tardis_data.get('options', []))
        
        # HolySheep request
        start = time.perf_counter()
        holy_sheep_data = await self.holy_sheep.get_options_chain(underlying)
        holy_sheep_latency = (time.perf_counter() - start) * 1000
        results['holy_sheep_latency_ms'] = holy_sheep_latency
        results['holy_sheep_options_count'] = len(holy_sheep_data.get('options', []))
        
        # Calculate speedup
        results['latency_improvement'] = (
            (tardis_latency - holy_sheep_latency) / tardis_latency * 100
        )
        
        # Validate data consistency
        if tardis_data.get('options') and holy_sheep_data.get('options'):
            results['data_match'] = self._validate_data_match(
                tardis_data['options'],
                holy_sheep_data['options']
            )
        
        self.latency_log.append(results)
        return results
    
    def _validate_data_match(self, tardis_opts, holy_opts) -> dict:
        """Validate that both providers return consistent data."""
        strikes_tardis = set(o['strike'] for o in tardis_opts)
        strikes_holy = set(o['strike'] for o in holy_opts)
        
        return {
            'common_strikes': len(strikes_tardis & strikes_holy),
            'tardis_only': len(strikes_tardis - strikes_holy),
            'holy_only': len(strikes_holy - strikes_tardis),
            'strike_coverage_match': len(strikes_tardis & strikes_holy) / max(len(strikes_tardis), len(strikes_holy))
        }
    
    async def run_comparison_study(self, num_samples: int = 100):
        """Run statistical comparison over multiple requests."""
        for i in range(num_samples):
            result = await self.compare_chain_response('BTC')
            print(f"Sample {i+1}/{num_samples}: "
                  f"Tardis {result['tardis_latency_ms']:.1f}ms vs "
                  f"HolySheep {result['holy_sheep_latency_ms']:.1f}ms "
                  f"({result['latency_improvement']:.1%} faster)")
            await asyncio.sleep(1)  # 1 second between samples
            
        avg_tardis = np.mean([r['tardis_latency_ms'] for r in self.latency_log])
        avg_holy = np.mean([r['holy_sheep_latency_ms'] for r in self.latency_log])
        
        print(f"\n=== Comparison Summary ===")
        print(f"Average Tardis.dev latency: {avg_tardis:.1f}ms")
        print(f"Average HolySheep latency: {avg_holy:.1f}ms")
        print(f"Overall improvement: {(avg_tardis-avg_holy)/avg_tardis:.1%}")

Example: Run comparison

asyncio.run(comparator.run_comparison_study(50))

Phase 3: Code Migration (Days 15-21)

Replace Tardis.dev API calls with HolySheep equivalents. Key changes:

Phase 4: Validation and Cutover (Days 22-28)

import hashlib
from typing import List, Dict

class DataIntegrityValidator:
    """
    Validates data integrity during migration.
    Compares computed values (Greeks, IV) between providers.
    """
    
    def __init__(self, holy_sheep_client):
        self.client = holy_sheep_client
        self.validation_results = []
        
    async def validate_greeks_calculation(self, option_data: dict) -> bool:
        """
        Validate that HolySheep's Greeks match Black-Scholes calculations.
        Tolerance: 0.5% for delta, 2% for gamma/theta/vega.
        """
        from scipy.stats import norm
        
        S = option_data.get('underlying_price', 100000)  # BTC spot
        K = option_data['strike']
        T = option_data.get('time_to_expiry', 30/365)  # 30 days
        r = 0.05  # Risk-free rate
        sigma = option_data.get('mid_iv', 0.5)
        option_type = option_data['option_type']
        
        # Black-Scholes formula
        d1 = (np.log(S/K) + (r + sigma**2/2)*T) / (sigma*np.sqrt(T))
        d2 = d1 - sigma*np.sqrt(T)
        
        if option_type == 'call':
            theoretical_price = S*norm.cdf(d1) - K*np.exp(-r*T)*norm.cdf(d2)
            delta = norm.cdf(d1)
        else:
            theoretical_price = K*np.exp(-r*T)*norm.cdf(-d2) - S*norm.cdf(-d1)
            delta = norm.cdf(d1) - 1
        
        gamma = norm.pdf(d1) / (S*sigma*np.sqrt(T))
        vega = S*np.sqrt(T)*norm.pdf(d1) / 100  # Per 1% move
        theta = (-S*sigma*norm.pdf(d1)/(2*np.sqrt(T)) - 
                 r*K*np.exp(-r*T)*norm.cdf(d2 if option_type=='call' else -d2)) / 365
        
        # Compare with API values
        api_delta = option_data.get('greeks', {}).get('delta', 0)
        api_gamma = option_data.get('greeks', {}).get('gamma', 0)
        
        delta_error = abs(delta - api_delta) / abs(delta) if delta != 0 else 0
        gamma_error = abs(gamma - api_gamma) / abs(gamma) if api_gamma != 0 else 0
        
        is_valid = delta_error < 0.005 and gamma_error < 0.02
        
        self.validation_results.append({
            'strike': K,
            'option_type': option_type,
            'theoretical_delta': delta,
            'api_delta': api_delta,
            'delta_error': delta_error,
            'is_valid': is_valid
        })
        
        return is_valid
    
    async def validate_implied_volatility(self, option_price: float, 
                                          strike: float, 
                                          spot: float,