Đường dẫn: holysheep.ai/blog/deribit-tardis-volatility-backtest

Bắt đầu bằng một lỗi thực tế

Khi tôi lần đầu thử fetch dữ liệu Deribit options history để backtest chiến lược straddle, terminal bắn ra lỗi này:

ConnectionError: HTTPSConnectionPool(host='://www.deribit.com', port=443): 
Max retries exceeded with url: /api/v2/public/get_book_summary_by_currency
(Caused by NewConnectionError: '<urllib3.connection.HTTPSConnection object at 0x7f8a3c2d1a90>:
Failed to establish a new connection: [Errno 110] Connection timed out'))

Response: {"usIn":1746302400000, "usOut":1746302400100, "success":false,
"error":{"code":-32000,"message":"API rate limit exceeded for this IP"}}

Sau 3 ngày debug, tôi phát hiện: Deribit không lưu trữ options orderbook history quá 24 giờ. Để backtest volatility strategy cần ít nhất 6 tháng dữ liệu, bạn bắt buộc phải dùng data vendor như Tardis Machine. Bài viết này sẽ hướng dẫn bạn workflow hoàn chỉnh từ fetch data → clean → tính implied volatility → backtest với Python.

Tardis Machine là gì và tại sao cần thiết

Tardis Machine là dịch vụ cung cấp historical market data cho crypto derivatives. Khác với Deribit API chỉ cho real-time và 24h history, Tardis lưu trữ:

Kiến trúc hệ thống

┌─────────────────────────────────────────────────────────────────────┐
│                    VOLATILITY BACKTEST ARCHITECTURE                  │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  [Deribit] ──────► [Tardis API] ──────► [Python Pipeline]           │
│       │                 │                    │                      │
│       │                 │                    ▼                      │
│  Real-time        Historical           ┌─────────────┐              │
│  (24h only)       (6+ months)          │ Data Lake   │              │
│                                         │ CSV/Parquet │              │
│                                         └─────────────┘              │
│                                                 │                      │
│                                                 ▼                      │
│                                         ┌─────────────────┐          │
│                                         │ Implied Vol Calc │          │
│                                         │ + GARCH Model    │          │
│                                         └─────────────────┘          │
│                                                 │                      │
│                                                 ▼                      │
│                                         ┌─────────────────┐          │
│                                         │ Backtest Engine │          │
│                                         │ (PyPortfolioOpt)│          │
│                                         └─────────────────┘          │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

Cài đặt môi trường

pip install tardis-machine pandas numpy scipy pyarrow \
    pyfolio-reloaded arch sqlalchemy python-dotenv aiohttp

Code thực chiến: Fetch Deribit Options History qua Tardis

# config.py
import os
from dataclasses import dataclass

@dataclass
class Config:
    # Tardis API credentials
    TARDIS_API_KEY: str = "your_tardis_api_key_here"
    TARDIS_API_SECRET: str = "your_tardis_secret_here"
    
    # HolySheep AI cho Volatility Analysis
    HOLYSHEEP_API_KEY: str = "YOUR_HOLYSHEEP_API_KEY"  # Đăng ký tại https://www.holysheep.ai/register
    HOLYSHEEP_BASE_URL: str = "https://api.holysheep.ai/v1"
    
    # Data parameters
    START_DATE: str = "2025-11-01"
    END_DATE: str = "2026-04-30"
    INSTRUMENT_TYPE: str = "option"
    CURRENCY: str = "BTC"
    SETTLEMENT_CURRENCY: str = "BTC"
    
    # Backtest parameters
    INITIAL_CAPITAL: float = 100_000.0  # USDT
    RISK_FREE_RATE: float = 0.05  # 5% annual
    CONFIDENCE_LEVEL: float = 0.95

config = Config()
# tardis_client.py
import aiohttp
import asyncio
import pandas as pd
from datetime import datetime, timedelta
from typing import List, Dict, Optional
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class TardisClient:
    """
    Async client cho Tardis Machine API
    Documentation: https://docs.tardis.dev/
    """
    
    BASE_URL = "https://api.tardis.dev/v1"
    
    def __init__(self, api_key: str, api_secret: str):
        self.api_key = api_key
        self.api_secret = api_secret
        self._session: Optional[aiohttp.ClientSession] = None
    
    async def __aenter__(self):
        self._session = aiohttp.ClientSession(
            auth=aiohttp.BasicAuth(self.api_key, self.api_secret)
        )
        return self
    
    async def __aexit__(self, *args):
        if self._session:
            await self._session.close()
    
    async def fetch_options_books(
        self,
        exchange: str = "deribit",
        currency: str = "BTC",
        start_date: str = "2025-11-01",
        end_date: str = "2026-04-30",
        compression: str = "none"  # none, gzip, zstd
    ) -> pd.DataFrame:
        """
        Fetch historical orderbook data cho Deribit options
        
        Lỗi thường gặp:
        - 401 Unauthorized: Check API key
        - 429 Too Many Requests: Rate limit - thêm delay 1s giữa requests
        - 500 Internal Server Error: Retry với exponential backoff
        """
        
        # Lấy danh sách available symbols trước
        symbols_url = f"{self.BASE_URL}/exchanges/{exchange}/symbols"
        
        async with self._session.get(symbols_url) as resp:
            if resp.status == 401:
                raise Exception("Tardis API: 401 Unauthorized - Kiểm tra API key")
            symbols_data = await resp.json()
        
        # Filter options symbols
        option_symbols = [
            s for s in symbols_data 
            if s.get('instrumentType') == 'option' and currency in s.get('underlying', '')
        ]
        
        logger.info(f"Tìm thấy {len(option_symbols)} options symbols cho {currency}")
        
        all_books = []
        
        # Fetch data theo ngày (Tardis giới hạn 30 ngày/request)
        start = datetime.strptime(start_date, "%Y-%m-%d")
        end = datetime.strptime(end_date, "%Y-%m-%d")
        
        for symbol in option_symbols[:10]:  # Demo: chỉ lấy 10 symbols
            symbol_name = symbol['symbol']
            current = start
            
            while current < end:
                period_end = min(current + timedelta(days=29), end)
                
                url = f"{self.BASE_URL}/exchanges/{exchange}/book_snapshot"
                params = {
                    'symbol': symbol_name,
                    'from': current.isoformat(),
                    'to': period_end.isoformat(),
                    'compression': compression,
                    'format': 'json'
                }
                
                try:
                    async with self._session.get(url, params=params) as resp:
                        if resp.status == 429:
                            logger.warning(f"Rate limit hit, sleeping 60s...")
                            await asyncio.sleep(60)
                            continue
                        
                        if resp.status == 500:
                            # Retry với exponential backoff
                            for attempt in range(3):
                                await asyncio.sleep(2 ** attempt)
                                async with self._session.get(url, params=params) as retry_resp:
                                    if retry_resp.status == 200:
                                        data = await retry_resp.json()
                                        break
                            else:
                                raise Exception(f"Tardis 500 error sau 3 retries: {symbol_name}")
                        
                        data = await resp.json()
                        
                        for tick in data:
                            all_books.append({
                                'timestamp': pd.to_datetime(tick['timestamp']),
                                'symbol': symbol_name,
                                'bids': tick.get('bids', []),
                                'asks': tick.get('asks', []),
                                'best_bid': float(tick['bids'][0][0]) if tick.get('bids') else None,
                                'best_ask': float(tick['asks'][0][0]) if tick.get('asks') else None,
                                'spread': None,
                                'mid_price': None
                            })
                        
                        logger.info(f"Fetched {symbol_name}: {current.date()} - {period_end.date()}")
                        
                except Exception as e:
                    logger.error(f"Error fetching {symbol_name}: {e}")
                
                current = period_end + timedelta(days=1)
                await asyncio.sleep(0.5)  # Rate limit protection
        
        df = pd.DataFrame(all_books)
        
        if not df.empty:
            df['spread'] = df['best_ask'] - df['best_bid']
            df['mid_price'] = (df['best_ask'] + df['best_bid']) / 2
        
        return df

Sử dụng

async def main(): from config import config async with TardisClient(config.TARDIS_API_KEY, config.TARDIS_API_SECRET) as client: df_books = await client.fetch_options_books( exchange="deribit", currency="BTC", start_date=config.START_DATE, end_date=config.END_DATE ) # Save to parquet cho efficient storage df_books.to_parquet('deribit_options_books.parquet', index=False) logger.info(f"Saved {len(df_books)} rows to deribit_options_books.parquet") if __name__ == "__main__": asyncio.run(main())

Tính Implied Volatility từ Orderbook

# volatility_calculator.py
import pandas as pd
import numpy as np
from scipy.stats import norm
from scipy.optimize import brentq
from typing import Tuple, Optional
import logging

logger = logging.getLogger(__name__)

class BlackScholes:
    """Black-Scholes option pricing với IV calculation"""
    
    @staticmethod
    def d1(S: float, K: float, T: float, r: float, sigma: float) -> float:
        if T <= 0 or sigma <= 0:
            return np.nan
        return (np.log(S / K) + (r + 0.5 * sigma ** 2) * T) / (sigma * np.sqrt(T))
    
    @staticmethod
    def d2(S: float, K: float, T: float, r: float, sigma: float) -> float:
        return BlackScholes.d1(S, K, T, r, sigma) - sigma * np.sqrt(T)
    
    @staticmethod
    def call_price(S: float, K: float, T: float, r: float, sigma: float) -> float:
        if T <= 0:
            return max(S - K, 0)
        d1 = BlackScholes.d1(S, K, T, r, sigma)
        d2 = BlackScholes.d2(S, K, T, r, sigma)
        return S * norm.cdf(d1) - K * np.exp(-r * T) * norm.cdf(d2)
    
    @staticmethod
    def put_price(S: float, K: float, T: float, r: float, sigma: float) -> float:
        if T <= 0:
            return max(K - S, 0)
        d1 = BlackScholes.d1(S, K, T, r, sigma)
        d2 = BlackScholes.d2(S, K, T, r, sigma)
        return K * np.exp(-r * T) * norm.cdf(-d2) - S * norm.cdf(-d1)

def implied_volatility(
    market_price: float,
    S: float,
    K: float,
    T: float,
    r: float,
    option_type: str = 'call',
    tol: float = 1e-6,
    max_iter: int = 100
) -> Optional[float]:
    """
    Tính Implied Volatility bằng Newton-Raphson
    
    Args:
        market_price: Giá thị trường hiện tại của option
        S: Spot price (giá underlying)
        K: Strike price
        T: Time to expiration (năm)
        r: Risk-free rate
        option_type: 'call' hoặc 'put'
    
    Returns:
        Implied volatility hoặc None nếu không hội tụ
    """
    
    if T <= 0:
        return None
    
    # Kiểm tra intrinsic value
    intrinsic = max(S - K, 0) if option_type == 'call' else max(K - S, 0)
    if market_price <= intrinsic:
        return None
    
    # Brent's method cho robust root finding
    def objective(sigma):
        if option_type == 'call':
            return BlackScholes.call_price(S, K, T, r, sigma) - market_price
        else:
            return BlackScholes.put_price(S, K, T, r, sigma) - market_price
    
    try:
        # Search range: 1% to 500% volatility
        iv = brentq(objective, 0.01, 5.0, xtol=tol, maxiter=max_iter)
        return iv
    except ValueError:
        # Không tìm được nghiệm trong range
        return None

class VolatilitySurfaceBuilder:
    """Build volatility surface từ Deribit options data"""
    
    def __init__(self, risk_free_rate: float = 0.05):
        self.risk_free_rate = risk_free_rate
        self.bs = BlackScholes()
    
    def parse_deribit_symbol(self, symbol: str) -> Tuple[str, float, str]:
        """
        Parse Deribit option symbol
        Ví dụ: BTC-28MAR2025-95000-C => (BTC, 95000, call)
        """
        parts = symbol.replace('-', '').upper()
        
        if '-C' in symbol:
            option_type = 'call'
            strike_str = parts.split('C')[0][-8:]  # Lấy 8 ký tự cuối trước C
        else:
            option_type = 'put'
            strike_str = parts.split('P')[0][-8:]
        
        strike = float(strike_str)
        underlying = symbol.split('-')[0]
        
        return underlying, strike, option_type
    
    def calculate_volatility_surface(
        self,
        df: pd.DataFrame,
        spot_price: float,
        current_timestamp: pd.Timestamp
    ) -> pd.DataFrame:
        """
        Tính volatility surface từ orderbook data
        
        Data structure mong đợi từ Tardis:
        - symbol: BTC-28MAR2025-95000-C
        - best_bid, best_ask: prices
        - timestamp
        """
        
        results = []
        
        for _, row in df.iterrows():
            try:
                symbol = row['symbol']
                _, strike, option_type = self.parse_deribit_symbol(symbol)
                
                # Mid price
                mid_price = (row['best_bid'] + row['best_ask']) / 2
                
                # Time to expiration
                # Parse expiration date từ symbol
                exp_date_str = symbol.split('-')[1]
                exp_date = pd.to_datetime(exp_date_str, format='%d%b%Y')
                T = (exp_date - current_timestamp).days / 365.0
                
                if T <= 0:
                    continue
                
                # Calculate IV
                iv = implied_volatility(
                    market_price=mid_price,
                    S=spot_price,
                    K=strike,
                    T=T,
                    r=self.risk_free_rate,
                    option_type=option_type
                )
                
                if iv is not None and 0.01 < iv < 5.0:  # Filter outliers
                    results.append({
                        'timestamp': row['timestamp'],
                        'symbol': symbol,
                        'strike': strike,
                        'moneyness': spot_price / strike,
                        'time_to_expiry': T,
                        'mid_price': mid_price,
                        'implied_vol': iv,
                        'option_type': option_type,
                        'bid_ask_spread': row['best_ask'] - row['best_bid']
                    })
                    
            except Exception as e:
                logger.debug(f"Error parsing {row['symbol']}: {e}")
                continue
        
        return pd.DataFrame(results)

Sử dụng với HolySheep AI cho phân tích nâng cao

def analyze_with_holysheep(vol_surface_df: pd.DataFrame) -> dict: """ Dùng HolySheep AI để phân tích volatility surface patterns Tiết kiệm 85%+ so với OpenAI API """ import openai client = openai.OpenAI( base_url="https://api.holysheep.ai/v1", api_key="YOUR_HOLYSHEEP_API_KEY" ) # Tính statistics stats_summary = { 'mean_iv': vol_surface_df['implied_vol'].mean(), 'median_iv': vol_surface_df['implied_vol'].median(), 'iv_skew': vol_surface_df.groupby('moneyness')['implied_vol'].mean(), 'term_structure': vol_surface_df.groupby('time_to_expiry')['implied_vol'].mean() } # Gửi summary cho AI phân tích prompt = f""" Phân tích volatility surface data: - Mean IV: {stats_summary['mean_iv']:.2%} - Median IV: {stats_summary['median_iv']:.2%} - Skew analysis: {stats_summary['iv_skew'].to_dict()} Đưa ra recommendations cho: 1. ATM options trading strategy 2. Skew trading opportunities 3. Risk management suggestions """ response = client.chat.completions.create( model="gpt-4.1", messages=[ {"role": "system", "content": "Bạn là chuyên gia volatility trading."}, {"role": "user", "content": prompt} ], temperature=0.3, max_tokens=1000 ) return { 'stats': stats_summary, 'ai_recommendation': response.choices[0].message.content }

Backtest Engine: Đánh giá Chiến lược Straddle

# backtest_engine.py
import pandas as pd
import numpy as np
from typing import List, Dict, Tuple
from dataclasses import dataclass
import pyfolio as pf
import warnings
warnings.filterwarnings('ignore')

@dataclass
class Trade:
    entry_time: pd.Timestamp
    exit_time: pd.Timestamp
    entry_price: float
    exit_price: float
    size: float
    pnl: float
    return_pct: float
    strike: float
    expiry: pd.Timestamp

class StraddleBacktester:
    """
    Backtest chiến lược Long Straddle trên Deribit options
    
    Chiến lược:
    - Mua ATM call + ATM put cùng expiration
    - Exit khi đạt target return hoặc trước expiry 1 ngày
    """
    
    def __init__(
        self,
        initial_capital: float = 100_000.0,
        risk_free_rate: float = 0.05,
        position_size_pct: float = 0.10,  # 10% cap cho mỗi trade
        target_return: float = 0.50,  # Exit khi đạt 50% return
        stop_loss: float = -0.80  # Stop loss -80%
    ):
        self.initial_capital = initial_capital
        self.risk_free_rate = risk_free_rate
        self.position_size_pct = position_size_pct
        self.target_return = target_return
        self.stop_loss = stop_loss
        self.trades: List[Trade] = []
        self.equity_curve: List[Dict] = []
        self.current_capital = initial_capital
    
    def calculate_position_size(
        self,
        option_price: float,
        volatility: float
    ) -> float:
        """
        Kelly Criterion với adjustment cho volatility
        """
        # Đơn giản hóa: dùng fixed percentage của capital
        position_value = self.current_capital * self.position_size_pct
        
        # Edge adjustment dựa trên IV rank
        if volatility > 0.8:
            position_value *= 0.7  # Giảm size khi IV cao
        elif volatility < 0.3:
            position_value *= 1.2  # Tăng size khi IV thấp
        
        num_contracts = position_value / (option_price * 100)  # Deribit lot size = 1
        return max(1, int(num_contracts))
    
    def run_backtest(
        self,
        vol_surface: pd.DataFrame,
        spot_prices: pd.Series,
        daily_rets: pd.Series
    ) -> Dict:
        """
        Run backtest trên volatility surface data
        
        Args:
            vol_surface: DataFrame với columns [timestamp, strike, implied_vol, mid_price]
            spot_prices: Series timestamp-indexed spot prices
            daily_rets: Daily returns của spot
        """
        
        # Filter cho mỗi expiration date
        expiry_groups = vol_surface.groupby('time_to_expiry')
        
        for expiry, group in expiry_groups:
            if len(group) < 10:
                continue
            
            # Tính ATM strike cho mỗi timestamp
            timestamps = sorted(group['timestamp'].unique())
            
            for i, ts in enumerate(timestamps[:50]):  # Demo: 50 timestamps
                ts_data = group[group['timestamp'] == ts]
                
                # Tìm ATM options
                atm_options = ts_data[
                    (ts_data['moneyness'] >= 0.95) & 
                    (ts_data['moneyness'] <= 1.05)
                ]
                
                if atm_options.empty:
                    continue
                
                # Get current spot
                closest_spot = spot_prices.asof(ts)
                if pd.isna(closest_spot):
                    continue
                
                # Entry: Long straddle (ATM call + ATM put)
                call = atm_options[atm_options['option_type'] == 'call'].iloc[0]
                put = atm_options[atm_options['option_type'] == 'put'].iloc[0]
                
                entry_cost = (call['mid_price'] + put['mid_price']) * 100
                size = self.calculate_position_size(entry_cost, call['implied_vol'])
                
                if size < 1:
                    continue
                
                entry_time = ts
                entry_price = entry_cost
                
                # Exit logic
                exit_idx = i + 1
                exit_time = None
                exit_price = None
                exit_reason = None
                
                for j in range(i + 1, min(i + 20, len(timestamps))):
                    # Check P&L at each point
                    ts_exit = timestamps[j]
                    ts_exit_data = group[group['timestamp'] == ts_exit]
                    
                    if ts_exit_data.empty:
                        continue
                    
                    # Recalculate ATM prices
                    atm_exit = ts_exit_data[
                        (ts_exit_data['moneyness'] >= 0.95) & 
                        (ts_exit_data['moneyness'] <= 1.05)
                    ]
                    
                    if atm_exit.empty:
                        continue
                    
                    call_exit = atm_exit[atm_exit['option_type'] == 'call']
                    put_exit = atm_exit[atm_exit['option_type'] == 'put']
                    
                    if call_exit.empty or put_exit.empty:
                        continue
                    
                    current_value = (call_exit['mid_price'].iloc[0] + 
                                   put_exit['mid_price'].iloc[0]) * 100 * size
                    
                    pnl = current_value - entry_cost * size
                    pnl_pct = pnl / (entry_cost * size)
                    
                    if pnl_pct >= self.target_return:
                        exit_time = ts_exit
                        exit_price = current_value / size
                        exit_reason = 'target_hit'
                        break
                    elif pnl_pct <= self.stop_loss:
                        exit_time = ts_exit
                        exit_price = current_value / size
                        exit_reason = 'stop_loss'
                        break
                
                # Nếu không exit trong 20 periods, close at expiry
                if exit_time is None and i + 20 >= len(timestamps):
                    last_ts = timestamps[-1]
                    last_data = group[group['timestamp'] == last_ts]
                    last_atm = last_data[
                        (last_data['moneyness'] >= 0.95) & 
                        (last_data['moneyness'] <= 1.05)
                    ]
                    
                    if not last_atm.empty:
                        exit_time = last_ts
                        exit_price = (last_atm['mid_price'].iloc[0] + 
                                    last_atm['mid_price'].iloc[0]) * 100
                        exit_reason = 'expiry'
                
                if exit_time is not None:
                    pnl = (exit_price - entry_price) * size
                    
                    trade = Trade(
                        entry_time=entry_time,
                        exit_time=exit_time,
                        entry_price=entry_price,
                        exit_price=exit_price,
                        size=size,
                        pnl=pnl,
                        return_pct=pnl / (entry_price * size),
                        strike=call['strike'],
                        expiry=pd.Timestamp(call['timestamp']) + pd.Timedelta(days=int(expiry * 365))
                    )
                    
                    self.trades.append(trade)
                    
                    # Update capital
                    self.current_capital += pnl
                    
                    self.equity_curve.append({
                        'timestamp': exit_time,
                        'capital': self.current_capital,
                        'trade_count': len(self.trades)
                    })
        
        return self.generate_report()
    
    def generate_report(self) -> Dict:
        """Generate backtest performance report"""
        
        if not self.trades:
            return {'error': 'No trades generated'}
        
        trades_df = pd.DataFrame([
            {
                'entry_time': t.entry_time,
                'exit_time': t.exit_time,
                'pnl': t.pnl,
                'return_pct': t.return_pct,
                'holding_days': (t.exit_time - t.entry_time).days
            }
            for t in self.trades
        ])
        
        # Performance metrics
        total_pnl = trades_df['pnl'].sum()
        total_return = total_pnl / self.initial_capital
        
        # Win rate
        wins = len(trades_df[trades_df['pnl'] > 0])
        losses = len(trades_df[trades_df['pnl'] <= 0])
        win_rate = wins / len(trades_df) if trades_df else 0
        
        # Average win/loss
        avg_win = trades_df[trades_df['pnl'] > 0]['pnl'].mean() if wins > 0 else 0
        avg_loss = trades_df[trades_df['pnl'] <= 0]['pnl'].mean() if losses > 0 else 0
        
        # Sharpe ratio
        if len(trades_df) > 1:
            returns = trades_df['pnl'] / self.initial_capital
            sharpe = (returns.mean() - self.risk_free_rate / 252) / returns.std() * np.sqrt(252)
        else:
            sharpe = 0
        
        # Max drawdown
        equity = pd.DataFrame(self.equity_curve)
        equity['peak'] = equity['capital'].cummax()
        equity['drawdown'] = (equity['capital'] - equity['peak']) / equity['peak']
        max_drawdown = equity['drawdown'].min()
        
        return {
            'total_trades': len(trades_df),
            'wins': wins,
            'losses': losses,
            'win_rate': f"{win_rate:.2%}",
            'total_pnl': f"${total_pnl:,.2f}",
            'total_return': f"{total_return:.2%}",
            'avg_win': f"${avg_win:,.2f}",
            'avg_loss': f"${avg_loss:,.2f}",
            'sharpe_ratio': f"{sharpe:.2f}",
            'max_drawdown': f"{max_drawdown:.2%}",
            'final_capital': f"${self.current_capital:,.2f}",
            'trades_df': trades_df
        }

Run full pipeline

def run_full_pipeline(): from config import Config # Load data df_books = pd.read_parquet('deribit_options_books.parquet') # Calculate volatility surface builder = VolatilitySurfaceBuilder(risk_free_rate=Config.RISK_FREE_RATE) # Mock spot prices (trong thực tế lấy từ Tardis hoặc exchange) spot_prices = pd.Series( np.random.uniform(90000, 110000, len(df_books['timestamp'].unique())), index=df_books['timestamp'].unique() ).sort_index() # Generate synthetic IV data cho demo vol_surface = df_books.copy() vol_surface['implied_vol'] = np.random.uniform(0.5, 1.5, len(vol_surface)) vol_surface['moneyness'] = vol_surface['strike'] / vol_surface['mid_price'] vol_surface['option_type'] = vol_surface['symbol'].apply( lambda x: 'call' if '-C' in x else 'put' ) # Run backtest backtester = StraddleBacktester( initial_capital=Config.INITIAL_CAPITAL, risk_free_rate=Config.RISK_FREE_RATE, position_size_pct=0.10, target_return=0.50, stop_loss=-0.80 ) results = backtester.run_backtest(vol_surface, spot_prices, None) print("=" * 60) print("STRADDLE BACKTEST RESULTS") print("=" * 60) for key, value in results.items(): if key != 'trades_df': print(f"{key}: {value}") return results if __name__ == "__main__": results = run_full_pipeline()

So sánh: Tardis vs Alternatives cho Deribit Data

Tiêu chí Tardis Machine Kaiko CoinMetrics HolySheep AI (Analysis)
Data Depth 2018-present 2014-present 2010-present Không lưu trữ data
Options Orderbook ✅ Full depth ⚠️ Top 10 only ❌ Không có ✅ AI analysis
Latency <50ms 100-200ms 500ms+ <50ms API
Giá m/tháng $199-999 $500-2000 $1000-5000 $0 (chỉ analysis)
Free tier 3 ngày history 100 API calls Không $5 credits
API Style REST + WebSocket REST REST + CSV OpenAI-compatible
Tốt cho Backtest, research Real-time feeds On-chain analysis Volatility analysis

Phù hợp / Không phù hợp với ai

✅ NÊN dùng Tardis + Backtest này nếu bạn là:

❌ KHÔNG nên dùng nếu bạn là: