Thị trường phái sinh tiền điện tử đang bùng nổ, và Deribit là sàn giao dịch quyền chọn BTC/ETH lớn nhất thế giới với khối lượng hợp đồng hàng ngày vượt 2 tỷ USD. Trong bài viết này, tôi sẽ chia sẻ kinh nghiệm thực chiến 3 năm xây dựng hệ thống backtest volatility — từ những lỗi ConnectionError: timeout đầu tiên đến pipeline xử lý 50GB data/ngày.

Vì sao Deribit Options là nguồn dữ liệu quan trọng cho Quantitative Trading

Quyền chọn Deribit cung cấp volatility surface chứa thông tin về kỳ vọng thị trường mà không nguồn nào sánh được:

Kịch bản lỗi thực tế: ConnectionError khi lấy Deribit WebSocket Data

Khi tôi bắt đầu xây dựng backtest engine năm 2023, đoạn code đầu tiên của tôi là:

# Code gây lỗi - KHÔNG CHẠY
import requests

Lỗi thường gặp: ConnectionError: timeout sau 30 giây

response = requests.get( "https://www.deribit.com/api/v2/public/get_order_book", params={"instrument_name": "BTC-28MAR26-95000-C", "depth": 10}, timeout=30 # Deribit rate limit rất nghiêm ngặt ) print(response.json())

Kết quả: ConnectionError: HTTPSConnectionPool(host='www.deribit.com', port=443): Max retries exceeded

Lý do: Deribit áp dụng strict rate limiting và không có public REST API cho data lịch sử. Giải pháp là dùng Deribit Data API hoặc WebSocket với authentication đúng cách.

Phương pháp 1: Kết nối Deribit WebSocket trực tiếp

# Cài đặt thư viện cần thiết

pip install websockets deribit-api pandas numpy

import json import asyncio from datetime import datetime, timedelta import pandas as pd import numpy as np class DeribitOptionsCollector: def __init__(self, client_id: str, client_secret: str): self.client_id = client_id self.client_secret = client_secret self.access_token = None self.ws_url = "wss://test.deribit.com/ws/api/v2" async def authenticate(self): """Xác thực và lấy access token""" auth_msg = { "jsonrpc": "2.0", "id": 1, "method": "public/auth", "params": { "grant_type": "client_credentials", "client_id": self.client_id, "client_secret": self.client_secret } } # Gửi auth request print(f"[{datetime.now()}] Đang xác thực Deribit API...") return auth_msg async def get_orderbook(self, instrument_name: str): """Lấy orderbook cho một instrument cụ thể""" book_msg = { "jsonrpc": "2.0", "id": 2, "method": "public/get_order_book", "params": { "instrument_name": instrument_name, "depth": 100 # Lấy 100 mức giá } } return book_msg async def get_volatility_smile(self, underlying: str = "BTC", expiry: str = "28MAR26"): """Lấy full volatility smile cho một expiry""" # Lấy danh sách tất cả strike prices instruments = await self._get_instruments(underlying, expiry) smile_data = [] for inst in instruments: book = await self.get_orderbook(inst) # Trích xuất IV từ best bid/ask mid_iv = (book.get('best_bid_vol', 0) + book.get('best_ask_vol', 0)) / 2 smile_data.append({ 'instrument': inst, 'strike': self._extract_strike(inst), 'mid_iv': mid_iv, 'timestamp': datetime.now() }) return pd.DataFrame(smile_data)

Sử dụng

collector = DeribitOptionsCollector( client_id="YOUR_DERIBIT_CLIENT_ID", client_secret="YOUR_DERIBIT_CLIENT_SECRET" )

Phương pháp 2: Download Historical Data với Python

Để backtest, bạn cần historical data. Deribit cung cấp data export nhưng format phức tạp:

import requests
import pandas as pd
from typing import List, Dict
import time

class DeribitHistoricalData:
    """Download và xử lý dữ liệu lịch sử từ Deribit"""
    
    BASE_URL = "https://history.deribit.com/api/v2/public"
    
    def __init__(self):
        self.session = requests.Session()
        self.session.headers.update({
            'Content-Type': 'application/json',
            'User-Agent': 'VolatilityBacktest/1.0'
        })
    
    def get_trades(self, instrument: str, start_timestamp: int, 
                   end_timestamp: int) -> pd.DataFrame:
        """
        Lấy trade history cho một instrument
        
        Args:
            instrument: VD 'BTC-28MAR26-95000-C'
            start_timestamp: Unix timestamp ms (VD 1700000000000)
            end_timestamp: Unix timestamp ms
        
        Returns:
            DataFrame với columns: timestamp, price, direction, iv
        """
        all_trades = []
        current_ts = start_timestamp
        
        while current_ts < end_timestamp:
            try:
                response = self.session.get(
                    f"{self.BASE_URL}/get_last_trades_by_instrument",
                    params={
                        "instrument_name": instrument,
                        "start_seq": current_ts,
                        "count": 1000,
                        "include_old": True
                    },
                    timeout=45
                )
                
                if response.status_code != 200:
                    print(f"Lỗi HTTP {response.status_code}")
                    break
                
                data = response.json()
                trades = data.get('result', {}).get('trades', [])
                
                if not trades:
                    break
                
                all_trades.extend(trades)
                current_ts = trades[-1]['timestamp'] + 1
                
                # Rate limit: max 10 requests/giây
                time.sleep(0.1)
                
            except requests.exceptions.Timeout:
                print(f"Timeout tại timestamp {current_ts}, retry...")
                time.sleep(5)
                continue
            except Exception as e:
                print(f"Lỗi: {e}")
                break
        
        df = pd.DataFrame(all_trades)
        if not df.empty:
            df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
            df['price'] = df['price'].astype(float)
        
        return df
    
    def get_volatility_history(self, currency: str = "BTC", 
                               start_date: str = "2025-01-01",
                               end_date: str = "2025-12-31") -> pd.DataFrame:
        """
        Tổng hợp IV history cho tất cả options của một currency
        
        Quy trình:
        1. Lấy danh sách instruments
        2. Với mỗi instrument, lấy mark_iv history
        3. Pivot thành volatility surface
        """
        # Lấy danh sách tất cả options đã list
        instruments = self._get_all_instruments(currency)
        
        vol_history = []
        for inst in instruments:
            try:
                # Lấy summary (mark price, mark iv, open interest)
                summary = self._get_instrument_summary(inst)
                if summary:
                    vol_history.append({
                        'instrument': inst,
                        'mark_iv': summary.get('mark_iv', 0),
                        'best_bid_iv': summary.get('best_bid_iv', 0),
                        'best_ask_iv': summary.get('best_ask_iv', 0),
                        'open_interest': summary.get('open_interest', 0),
                        'timestamp': datetime.now()
                    })
                
                time.sleep(0.05)  # Tránh rate limit
                
            except Exception as e:
                print(f"Lỗi lấy {inst}: {e}")
                continue
        
        return pd.DataFrame(vol_history)
    
    def _get_all_instruments(self, currency: str) -> List[str]:
        """Lấy danh sách tất cả instrument names"""
        response = self.session.get(
            f"{self.BASE_URL}/get_instruments",
            params={
                "currency": currency,
                "kind": "option",
                "expired": False
            },
            timeout=30
        )
        data = response.json()
        return [i['instrument_name'] for i in data.get('result', [])]
    
    def _get_instrument_summary(self, instrument: str) -> Dict:
        """Lấy summary cho một instrument cụ thể"""
        response = self.session.get(
            f"{self.BASE_URL}/get_summary",
            params={"instrument_name": instrument},
            timeout=30
        )
        data = response.json()
        return data.get('result', {})

Khởi tạo và sử dụng

data_collector = DeribitHistoricalData()

Ví dụ: Lấy 1 tháng data cho BTC options

btc_trades = data_collector.get_trades( instrument="BTC-28MAR26-95000-C", start_timestamp=1746000000000, # 2025-04-30 end_timestamp=1748600000000 # 2025-05-30 ) print(f"Đã lấy {len(btc_trades)} trades") print(btc_trades.head())

Xây dựng Volatility Backtest Engine

Sau khi có data, bước tiếp theo là xây dựng backtest engine để test chiến lược:

import pandas as pd
import numpy as np
from scipy.stats import norm
from scipy.optimize import brentq
from typing import Tuple, Optional
from dataclasses import dataclass
from datetime import datetime

@dataclass
class OptionContract:
    """Đại diện cho một hợp đồng quyền chọn"""
    instrument: str
    strike: float
    expiry: datetime
    option_type: str  # 'C' hoặc 'P'
    mark_iv: float
    mark_price: float
    
@dataclass  
class VolSignal:
    """Tín hiệu giao dịch từ volatility analysis"""
    timestamp: datetime
    instrument: str
    signal_type: str  # 'BUY_IV', 'SELL_IV', 'FLAT'
    current_iv: float
    fair_iv: float
    edge: float  # Chênh lệch IV
    confidence: float

class BlackScholes:
    """Black-Scholes pricing model cho European options"""
    
    @staticmethod
    def price(S: float, K: float, T: float, r: float, sigma: float, 
              option_type: str) -> float:
        """
        Tính giá option theo Black-Scholes
        
        Args:
            S: Giá underlying hiện tại
            K: Strike price
            T: Thời gian đến expiry (năm)
            r: Risk-free rate
            sigma: Implied volatility
            option_type: 'C' (Call) hoặc 'P' (Put)
        """
        if T <= 0 or sigma <= 0:
            return 0.0
        
        d1 = (np.log(S/K) + (r + sigma**2/2) * T) / (sigma * np.sqrt(T))
        d2 = d1 - sigma * np.sqrt(T)
        
        if option_type == 'C':
            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
    
    @staticmethod
    def iv(S: float, K: float, T: float, r: float, 
           market_price: float, option_type: str) -> float:
        """
        Tính implied volatility từ market price
        
        Sử dụng Brent's method để tìm IV
        """
        def objective(sigma):
            return BlackScholes.price(S, K, T, r, sigma, option_type) - market_price
        
        try:
            iv = brentq(objective, 0.001, 5.0, maxiter=100)
            return iv
        except ValueError:
            return np.nan

class VolatilityBacktester:
    """Engine backtest chiến lược volatility"""
    
    def __init__(self, initial_capital: float = 100000, 
                 transaction_cost: float = 0.0005):
        self.capital = initial_capital
        self.initial_capital = initial_capital
        self.transaction_cost = transaction_cost
        self.positions = {}
        self.trade_log = []
        self.equity_curve = []
        
    def run_backtest(self, vol_data: pd.DataFrame, 
                     spot_data: pd.DataFrame,
                     strategy_params: dict) -> dict:
        """
        Chạy backtest với chiến lược volatility
        
        Chiến lược: Mua IV khi mark_iv < historical_avg - 1.5*std
                    Bán IV khi mark_iv > historical_avg + 1.5*std
        """
        lookback = strategy_params.get('lookback', 30)
        z_entry = strategy_params.get('z_entry', 1.5)
        z_exit = strategy_params.get('z_exit', 0.5)
        position_size = strategy_params.get('position_size', 0.1)
        
        results = []
        
        for i, row in vol_data.iterrows():
            timestamp = row['timestamp']
            
            # Tính z-score của IV
            recent_iv = vol_data[vol_data['timestamp'] <= timestamp].tail(lookback)
            if len(recent_iv) < lookback:
                continue
                
            mean_iv = recent_iv['mark_iv'].mean()
            std_iv = recent_iv['mark_iv'].std()
            z_score = (row['mark_iv'] - mean_iv) / std_iv if std_iv > 0 else 0
            
            # Quyết định vào lệnh
            if z_score < -z_entry:
                signal = 'LONG_VOL'  # Mua volatility
                self._enter_position(
                    row['instrument'],
                    signal,
                    row['mark_iv'],
                    position_size,
                    timestamp
                )
            elif z_score > z_entry:
                signal = 'SHORT_VOL'  # Bán volatility
                self._enter_position(
                    row['instrument'],
                    signal,
                    row['mark_iv'],
                    position_size,
                    timestamp
                )
            elif abs(z_score) < z_exit:
                self._exit_all_positions(row['mark_iv'], timestamp)
                signal = 'FLAT'
            
            # Ghi nhận PnL
            pnl = self._calculate_portfolio_pnl(row)
            self.equity_curve.append({
                'timestamp': timestamp,
                'equity': self.capital + pnl,
                'pnl': pnl
            })
            
            results.append({
                'timestamp': timestamp,
                'instrument': row['instrument'],
                'z_score': z_score,
                'signal': signal if 'signal' in locals() else 'HOLD',
                'equity': self.capital + pnl
            })
        
        return self._generate_performance_report(results)
    
    def _enter_position(self, instrument: str, signal: str, 
                       price: float, size: float, timestamp: datetime):
        """Vào vị thế mới"""
        cost = self.capital * size * (1 + self.transaction_cost)
        
        self.positions[instrument] = {
            'signal': signal,
            'entry_price': price,
            'size': size,
            'entry_time': timestamp
        }
        
        self.trade_log.append({
            'timestamp': timestamp,
            'action': 'ENTRY',
            'instrument': instrument,
            'signal': signal,
            'price': price,
            'cost': cost
        })
        
        self.capital -= cost
    
    def _exit_all_positions(self, current_iv: float, timestamp: datetime):
        """Đóng tất cả vị thế"""
        for instrument, pos in list(self.positions.items()):
            pnl = self._calculate_position_pnl(instrument, current_iv)
            self.capital += pnl * (1 - self.transaction_cost)
            
            self.trade_log.append({
                'timestamp': timestamp,
                'action': 'EXIT',
                'instrument': instrument,
                'pnl': pnl
            })
            
            del self.positions[instrument]
    
    def _calculate_position_pnl(self, instrument: str, current_iv: float) -> float:
        """Tính PnL của một vị thế"""
        pos = self.positions[instrument]
        entry_price = pos['entry_price']
        position_value = self.capital * pos['size']
        
        return position_value * (current_iv - entry_price) / entry_price
    
    def _calculate_portfolio_pnl(self, vol_row: pd.DataFrame) -> float:
        """Tính tổng PnL portfolio"""
        total_pnl = 0
        for instrument, pos in self.positions.items():
            if instrument in vol_row['instrument'].values:
                current_iv = vol_row['mark_iv']
                total_pnl += self._calculate_position_pnl(instrument, current_iv)
        return total_pnl
    
    def _generate_performance_report(self, results: list) -> dict:
        """Tạo báo cáo hiệu suất"""
        equity_df = pd.DataFrame(self.equity_curve)
        
        returns = equity_df['equity'].pct_change().dropna()
        
        sharpe = returns.mean() / returns.std() * np.sqrt(365 * 24) if returns.std() > 0 else 0
        max_dd = (equity_df['equity'].cummax() - equity_df['equity']).max()
        
        return {
            'total_return': (self.capital - self.initial_capital) / self.initial_capital,
            'sharpe_ratio': sharpe,
            'max_drawdown': max_dd / self.initial_capital,
            'num_trades': len(self.trade_log),
            'equity_curve': equity_df,
            'trade_log': pd.DataFrame(self.trade_log)
        }

Chạy backtest

backtester = VolatilityBacktester( initial_capital=100000, transaction_cost=0.001 ) results = backtester.run_backtest( vol_data=volatility_df, spot_data=spot_df, strategy_params={ 'lookback': 30, 'z_entry': 1.5, 'z_exit': 0.5, 'position_size': 0.1 } ) print(f"Tổng lợi nhuận: {results['total_return']*100:.2f}%") print(f"Sharpe Ratio: {results['sharpe_ratio']:.2f}") print(f"Max Drawdown: {results['max_drawdown']*100:.2f}%")

Tối ưu hóa với AI: Dùng HolySheep cho Signal Generation

Sau khi có volatility surface, bước quan trọng là phân tích để tạo trading signals. Tại đây, HolySheep AI có thể hỗ trợ xử lý và phân tích dữ liệu với chi phí cực thấp — chỉ từ $0.42/MTok cho DeepSeek V3.2.

# Dùng HolySheep AI để phân tích volatility và tạo signals
import requests
import json

HOLYSHEEP_API_URL = "https://api.holysheep.ai/v1/chat/completions"

def analyze_volatility_signals(volatility_df, market_data):
    """
    Dùng AI để phân tích volatility surface và đề xuất signals
    
    Chi phí ước tính:
    - Input: ~5000 tokens (volatility data JSON)
    - Output: ~500 tokens (analysis)
    - Tổng: 5500 tokens × $0.42/MTok = $0.00231/request
    - So với Claude Sonnet: 5500 × $15/MTok = $0.0825/request (tiết kiệm 97%)
    """
    
    # Format dữ liệu gửi lên AI
    prompt = f"""Phân tích volatility surface cho BTC options:

    Dữ liệu IV hiện tại (top 5 strikes):
    {volatility_df.head().to_json()}

    Thông tin thị trường:
    - BTC Price: ${market_data.get('btc_price', 95000)}
    - Fear & Greed Index: {market_data.get('fear_greed', 65)}
    - Funding Rate: {market_data.get('funding_rate', 0.0001)}

    Đưa ra:
    1. Đánh giá skewness của smile
    2. Cơ hội arbitrage (nếu có)
    3. Khuyến nghị LONG/SHORT volatility với confidence score
    4. Strike prices tiềm năng để vào lệnh
    5. Risk/Reward ratio ước tính

    Format response JSON như sau:
    {{
        "analysis": {{
            "skew_assessment": "string",
            "arbitrage_opportunities": ["string"],
            "recommendation": "LONG_VOL|SHORT_VOL|FLAT",
            "confidence": 0.0-1.0,
            "recommended_strikes": ["string"],
            "risk_reward": 0.0
        }}
    }}"""
    
    response = requests.post(
        HOLYSHEEP_API_URL,
        headers={
            "Authorization": "Bearer YOUR_HOLYSHEEP_API_KEY",
            "Content-Type": "application/json"
        },
        json={
            "model": "deepseek-v3.2",  # Model rẻ nhất, phù hợp cho structured analysis
            "messages": [
                {"role": "system", "content": "Bạn là chuyên gia phân tích volatility derivatives với 10 năm kinh nghiệm tại quant fund."},
                {"role": "user", "content": prompt}
            ],
            "temperature": 0.3,  # Low temperature cho structured output
            "response_format": {"type": "json_object"}
        },
        timeout=30
    )
    
    if response.status_code == 200:
        result = response.json()
        return json.loads(result['choices'][0]['message']['content'])
    else:
        print(f"Lỗi API: {response.status_code} - {response.text}")
        return None

Ví dụ sử dụng

market_data = { 'btc_price': 97500, 'fear_greed': 72, 'funding_rate': 0.00015 } analysis = analyze_volatility_signals(volatility_df, market_data) print(json.dumps(analysis, indent=2))

So sánh chi phí API cho Quantitative Analysis

Dịch vụModelGiá/MTokPhù hợp choĐộ trễ
HolySheep AIDeepSeek V3.2$0.42Signal generation, data processing<50ms
OpenAIGPT-4.1$8.00Complex reasoning~200ms
AnthropicClaude Sonnet 4.5$15.00Detailed analysis~300ms
GoogleGemini 2.5 Flash$2.50Fast prototyping~100ms

Tiết kiệm: Dùng HolySheep cho 10,000 requests/tháng với 5000 tokens/request tiết kiệm 85%+ so với OpenAI.

Lỗi thường gặp và cách khắc phục

1. Lỗi 401 Unauthorized khi kết nối Deribit API

Mã lỗi:

{"jsonrpc": "2.0", "id": 1, "error": {"message": "Invalid credentials", "code": 13009}}

Nguyên nhân: Client ID/Secret sai hoặc hết hạn token

Khắc phục:

import time

def get_valid_token(client_id: str, client_secret: str, refresh_interval: int = 3500):
    """
    Lấy và tự động refresh token
    
    Deribit token hết hạn sau 1 giờ (3600 giây)
    Refresh trước 5 phút để tránh lỗi
    """
    token_url = "https://test.deribit.com/api/v2/public/auth"
    
    def fetch_token():
        response = requests.post(token_url, json={
            "jsonrpc": "2.0",
            "id": 1,
            "method": "public/auth",
            "params": {
                "grant_type": "client_credentials",
                "client_id": client_id,
                "client_secret": client_secret
            }
        })
        
        if response.status_code == 200:
            data = response.json()
            if 'result' in data and 'access_token' in data['result']:
                return {
                    'token': data['result']['access_token'],
                    'expires_at': time.time() + data['result']['expires_in']
                }
        
        raise Exception(f"Auth failed: {response.text}")
    
    # Lấy token đầu tiên
    token_data = fetch_token()
    
    while True:
        if time.time() >= token_data['expires_at'] - 300:  # Refresh 5 phút trước
            token_data = fetch_token()
            print(f"[{datetime.now()}] Token refreshed, expires at {token_data['expires_at']}")
        
        yield token_data['token']
        time.sleep(10)

Sử dụng

for token in get_valid_token("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET"): # Dùng token cho các API calls headers = {"Authorization": f"Bearer {token}"} break

2. Lỗi Rate Limit: "Too many requests"

Mã lỗi:

{"jsonrpc": "2.0", "id": 1, "error": {"message": "Too many requests", "code": 429}}

Khắc phục:

import time
from ratelimit import limits, sleep_and_retry

class RateLimitedClient:
    """
    Deribit rate limits:
    - Public endpoints: 10 requests/second
    - Authenticated endpoints: 20 requests/second
    """
    
    def __init__(self):
        self.last_request_time = {}
        self.min_interval_public = 0.1  # 10 req/s = 100ms interval
        self.min_interval_auth = 0.05   # 20 req/s = 50ms interval
    
    def throttled_request(self, method: str, url: str, 
                         authenticated: bool = False, **kwargs):
        """Gửi request với automatic rate limiting"""
        interval = (self.min_interval_auth if authenticated 
                   else self.min_interval_public)
        
        # Đợi đủ thời gian kể từ request cuối
        last_time = self.last_request_time.get(url, 0)
        elapsed = time.time() - last_time
        
        if elapsed < interval:
            time.sleep(interval - elapsed)
        
        # Retry logic cho 429 errors
        max_retries = 5
        for attempt in range(max_retries):
            response = requests.request(method, url, **kwargs)
            
            if response.status_code == 200:
                self.last_request_time[url] = time.time()
                return response
            
            elif response.status_code == 429:
                # Exponential backoff
                wait_time = 2 ** attempt
                print(f"Rate limited, waiting {wait_time}s...")
                time.sleep(wait_time)
            
            else:
                raise Exception(f"HTTP {response.status_code}: {response.text}")
        
        raise Exception("Max retries exceeded")

Sử dụng

client = RateLimitedClient()

Lấy orderbook với rate limit tự động

response = client.throttled_request( "GET", "https://test.deribit.com/api/v2/public/get_order_book", params={"instrument_name": "BTC-28MAR26-95000-C", "depth": 10} )

3. Lỗi WebSocket Reconnection liên tục

Nguyên nhân: Server disconnect do heartbeat timeout hoặc network instability

Khắc phục:

import asyncio
import websockets
from websockets.exceptions import ConnectionClosed

class RobustWebSocketClient:
    """WebSocket client với automatic reconnection"""
    
    def __init__(self, url: str, heartbeat_interval: int = 30):
        self.url = url
        self.heartbeat_interval = heartbeat_interval
        self.ws = None
        self.reconnect_delay = 1
        self.max_reconnect_delay = 60
    
    async def connect(self):
        """Kết nối với exponential backoff"""
        while True:
            try:
                self.ws = await websockets.connect(
                    self.url,
                    ping_interval=self.heartbeat_interval,
                    ping_timeout=10
                )
                self.reconnect_delay = 1  # Reset delay
                print(f"[{datetime.now()}] Connected to {self.url}")
                return
                
            except Exception as e:
                print(f"[{datetime.now()}] Connection failed: {e}")
                print(f"Retrying in {self.reconnect_delay}s...")
                await asyncio.sleep(self.reconnect_delay)
                self.reconnect_delay = min(
                    self.reconnect_delay * 2, 
                    self.max_reconnect_delay
                )
    
    async def send_and_receive(self, message: dict) -> dict:
        """Gửi message và nhận response"""
        while True:
            try:
                await self.ws.send(json.dumps(message))
                response = await asyncio.wait_for(
                    self.ws.recv(),
                    timeout=30
                )
                return json.loads(response)
                
            except ConnectionClosed as e:
                print(f"Connection lost: {e}")
                await self.connect()
                
            except asyncio.TimeoutError:
                print("Timeout waiting for response, retrying...")
                continue

async def main():
    client = RobustWebSocketClient("wss://test.deribit.com/ws/api/v2")
    await client.connect()
    
    # Subscribe to orderbook updates
    await client.send_and_receive({
        "jsonrpc": "2.0",
        "id": 1,
        "method": "public/subscribe",
        "params": {
            "channels": ["book.BTC-28MAR26-95000-C.100ms"]
        }
    })
    
    # Keep connection alive
    async for message in client.ws:
        data = json.loads(message)
        # Process orderbook update
        print(data)

asyncio.run(main())

4. Xử lý missing data trong volatility surface

Vấn đề: Một số strike prices không có liquidity, tạo holes trong data

Giải pháp:

def fill_volatility_surface(df: pd.DataFrame, method: str = 'spline') -> pd.DataFrame:
    """
    Điền missing values trong volatility surface
    
    Methods:
    - 'forward_fill': Dùng gi