Trong bối cảnh thị trường tiền mã hóa ngày càng phức tạp, việc tiếp cận dữ liệu quyền chọn BTC chất lượng cao là yếu tố then chốt cho các chiến lược giao dịch và quản lý rủi ro. Bài viết này sẽ hướng dẫn chi tiết cách tải dữ liệu lịch sử từ sàn Deribit, bao gồm implied volatility, Greeks, và xây dựng data pipeline cho backtesting.
Mở đầu: Bối cảnh giá AI API 2026
Trước khi đi vào chi tiết kỹ thuật, chúng ta cùng xem xét chi phí vận hành khi xử lý dữ liệu quyền chọn với các mô hình AI hiện đại. Dưới đây là bảng so sánh chi phí cho 10 triệu token/tháng — con số phù hợp với pipeline xử lý dữ liệu quyền chọn quy mô trung bình:
| Mô hình | Giá/MTok | 10M tokens/tháng | Tỷ lệ tiết kiệm |
|---|---|---|---|
| GPT-4.1 | $8.00 | $80 | — |
| Claude Sonnet 4.5 | $15.00 | $150 | — |
| Gemini 2.5 Flash | $2.50 | $25 | 69% vs Claude |
| DeepSeek V3.2 | $0.42 | $4.20 | 85%+ vs GPT-4.1 |
| HolySheep DeepSeek V3.2 | $0.42 | $4.20 | Tỷ giá ¥1=$1, WeChat/Alipay |
Như bạn thấy, đăng ký HolySheep AI không chỉ giúp tiết kiệm chi phí mà còn cung cấp tốc độ phản hồi dưới 50ms — lý tưởng cho các ứng dụng real-time liên quan đến dữ liệu quyền chọn.
Giới thiệu về Deribit và dữ liệu Quyền chọn BTC
Deribit là sàn giao dịch quyền chọn BTC và ETH lớn nhất thế giới tính theo open interest. Dữ liệu từ Deribit bao gồm:
- Implied Volatility (IV): Độ biến động ngụ ý từ giá quyền chọn thị trường
- Delta, Gamma, Theta, Vega (Greeks): Các chỉ số đo lường rủi ro
- OI (Open Interest) và Volume: Dữ liệu thanh khoản
- Funding Rate: Tỷ lệ tài trợ perpetual futures
- IV Rank/Percentile: Vị trí tương đối của IV hiện tại
Kiến trúc Data Pipeline cho Backtesting
Để xây dựng hệ thống backtesting quyền chọn hoàn chỉnh, chúng ta cần kiến trúc data pipeline với các thành phần chính sau:
┌─────────────────────────────────────────────────────────────────┐
│ DATA PIPELINE ARCHITECTURE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Deribit │───▶│ Apache │───▶│ PostgreSQL │ │
│ │ WebSocket │ │ Kafka │ │ + TimescaleDB│ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Historical │ │ Real-time │ │ Backtest │ │
│ │ Batch Load │ │ Stream │ │ Engine │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ HolySheep │ │
│ │ AI Analysis │ │
│ └──────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Tải dữ liệu lịch sử từ Deribit API
1. Thiết lập kết nối Deribit
import requests
import json
import time
from datetime import datetime, timedelta
import pandas as pd
class DeribitDataFetcher:
"""
Fetcher class for Deribit BTC options historical data
Includes: Implied Volatility, Greeks, OHLCV, Funding Rate
"""
BASE_URL = "https://www.deribit.com/api/v2"
def __init__(self, client_id: str, client_secret: str):
self.client_id = client_id
self.client_secret = client_secret
self.access_token = None
self.token_expires = 0
def authenticate(self) -> dict:
"""Get authentication token from Deribit"""
auth_url = f"{self.BASE_URL}/public/auth"
payload = {
"grant_type": "client_credentials",
"client_id": self.client_id,
"client_secret": self.client_secret
}
response = requests.post(auth_url, json=payload)
data = response.json()
if data.get("success"):
self.access_token = data["result"]["access_token"]
self.token_expires = time.time() + 3600
return data["result"]
else:
raise Exception(f"Authentication failed: {data}")
def get_instruments(self, currency: str = "BTC") -> list:
"""Get all options instruments for currency"""
if not self.access_token or time.time() > self.token_expires:
self.authenticate()
url = f"{self.BASE_URL}/public/get_instruments"
params = {
"currency": currency,
"kind": "option",
"expired": False
}
response = requests.get(url, params=params)
return response.json()["result"]
def get_options_book(self, instrument_name: str) -> dict:
"""Get order book with IV and Greeks"""
if not self.access_token:
self.authenticate()
url = f"{self.BASE_URL}/public/get_order_book"
params = {"instrument_name": instrument_name}
response = requests.get(url, params=params)
result = response.json()["result"]
# Calculate implied volatility from mid price
bid_price = float(result.get("bids", [[0]])[0][0])
ask_price = float(result.get("asks", [[0]])[0][0])
mid_price = (bid_price + ask_price) / 2
return {
"instrument_name": instrument_name,
"timestamp": result["timestamp"],
"bid": bid_price,
"ask": ask_price,
"mid_price": mid_price,
"underlying_price": result["underlying_price"],
"mark_iv": result.get("mark_iv", 0),
"bid_iv": result.get("bid_iv", 0),
"ask_iv": result.get("ask_iv", 0)
}
Sử dụng với HolySheep AI để phân tích dữ liệu
def analyze_options_with_holysheep(options_data: list, api_key: str):
"""Use HolySheep AI to analyze options data"""
import openai
client = openai.OpenAI(
api_key=api_key,
base_url="https://api.holysheep.ai/v1" # Chỉ dùng HolySheep API
)
prompt = f"""Analyze the following BTC options data and provide insights:
- IV levels and trends
- Greeks distribution
- Potential opportunities
Data: {json.dumps(options_data[:10], indent=2)}
"""
response = client.chat.completions.create(
model="deepseek-v3.2", # $0.42/MTok - tiết kiệm 85%+
messages=[{"role": "user", "content": prompt}],
temperature=0.3
)
return response.choices[0].message.content
Khởi tạo và sử dụng
fetcher = DeribitDataFetcher(
client_id="YOUR_DERIBIT_CLIENT_ID",
client_secret="YOUR_DERIBIT_CLIENT_SECRET"
)
instruments = fetcher.get_instruments()
print(f"Total BTC options instruments: {len(instruments)}")
2. Tải dữ liệu Historical với Pagination
import requests
from typing import Generator
import time
class DeribitHistoricalData:
"""
Comprehensive historical data fetcher for Deribit options
Supports: OHLCV, Greeks, IV, funding data
"""
BASE_URL = "https://www.deribit.com/api/v2"
def __init__(self):
self.session = requests.Session()
self.session.headers.update({
"Content-Type": "application/json"
})
def fetch_trades_with_pagination(
self,
instrument_name: str,
start_time: int,
end_time: int,
chunk_size: int = 10000
) -> Generator[list, None, None]:
"""
Fetch historical trades with pagination
Returns chunks of up to 10,000 records
"""
offset = 0
start = start_time
while True:
url = f"{self.BASE_URL}/public/get_trades_by_instrument"
params = {
"instrument_name": instrument_name,
"start_seq": start,
"end_seq": end_time,
"count": chunk_size,
"offset": offset
}
response = self.session.get(url, params=params)
data = response.json()
if not data.get("success"):
print(f"Error fetching: {data}")
break
trades = data["result"]["trades"]
if not trades:
break
yield trades
# Pagination logic
if len(trades) < chunk_size:
break
offset += chunk_size
# Rate limiting: 10 requests/second for public endpoints
time.sleep(0.1)
def fetch_ohlcv(
self,
instrument_name: str,
resolution: str = "1h",
start_time: int = None,
end_time: int = None
) -> pd.DataFrame:
"""
Fetch OHLCV candle data for options
Args:
instrument_name: e.g., "BTC-27DEC2024-95000-C"
resolution: "1m", "5m", "1h", "1d"
start_time: Unix timestamp in milliseconds
end_time: Unix timestamp in milliseconds
"""
url = f"{self.BASE_URL}/public/get_tradingview_chart_data"
params = {
"instrument_name": instrument_name,
"resolution": resolution,
"start_timestamp": start_time or int((time.time() - 86400*30) * 1000),
"end_timestamp": end_time or int(time.time() * 1000)
}
response = self.session.get(url, params=params)
result = response.json()["result"]
df = pd.DataFrame({
"timestamp": result["ticks"],
"open": result["open"],
"high": result["high"],
"low": result["low"],
"close": result["close"],
"volume": result["volume"]
})
return df
def fetch_greeks_history(
self,
currency: str = "BTC",
days_back: int = 365
) -> pd.DataFrame:
"""
Fetch historical Greeks data for all options
Creates a comprehensive Greeks time series
"""
end_time = int(time.time() * 1000)
start_time = int((time.time() - days_back * 86400) * 1000)
# Get all options instruments
url = f"{self.BASE_URL}/public/get_instruments"
params = {"currency": currency, "kind": "option", "expired": False}
response = self.session.get(url, params=params)
instruments = response.json()["result"]
all_greeks = []
for instrument in instruments:
name = instrument["instrument_name"]
try:
# Fetch option book data with Greeks
book_url = f"{self.BASE_URL}/public/get_order_book"
book_params = {"instrument_name": name, "depth": 5}
book_response = self.session.get(book_url, params=book_params)
book_data = book_response.json()
if book_data.get("success"):
result = book_data["result"]
greeks = {
"timestamp": result.get("timestamp", int(time.time() * 1000)),
"instrument_name": name,
"strike": result.get("strike", 0),
"option_type": "call" if "C" in name else "put",
"underlying_price": result.get("underlying_price", 0),
"mark_iv": result.get("mark_iv", 0),
"bid_iv": result.get("bid_iv", 0),
"ask_iv": result.get("ask_iv", 0),
"delta": result.get("greeks", {}).get("delta", 0),
"gamma": result.get("greeks", {}).get("gamma", 0),
"theta": result.get("greeks", {}).get("theta", 0),
"vega": result.get("greeks", {}).get("vega", 0),
"rho": result.get("greeks", {}).get("rho", 0),
"bid": result.get("bids", [[0]])[0][0],
"ask": result.get("asks", [[0]])[0][0],
"mark": result.get("mark_price", 0)
}
all_greeks.append(greeks)
time.sleep(0.05) # Rate limiting
except Exception as e:
print(f"Error fetching {name}: {e}")
continue
return pd.DataFrame(all_greeks)
Ví dụ sử dụng
fetcher = DeribitHistoricalData()
Tải 1 năm dữ liệu Greeks cho tất cả quyền chọn BTC
greeks_df = fetcher.fetch_greeks_history(currency="BTC", days_back=365)
Lưu vào CSV cho backtesting
greeks_df.to_csv("btc_options_greeks_2024.csv", index=False)
print(f"Downloaded {len(greeks_df)} records")
print(greeks_df.head())
Tính toán Implied Volatility từ dữ liệu thô
Deribit cung cấp sẵn mark_iv, nhưng trong nhiều trường hợp bạn cần tự tính IV từ giá thị trường bằng mô hình Black-Scholes. Dưới đây là implementation hoàn chỉnh:
import numpy as np
from scipy.stats import norm
from scipy.optimize import brentq
from dataclasses import dataclass
from typing import Tuple, Optional
@dataclass
class OptionQuote:
"""Option quote data structure"""
instrument_name: str
strike: float
expiry: datetime
option_type: str # 'call' or 'put'
spot_price: float
bid_price: float
ask_price: float
time_to_expiry: float # in years
class ImpliedVolatilityCalculator:
"""
Black-Scholes based IV calculator with multiple methods
Supports: Newton-Raphson, Brent, Secant methods
"""
def __init__(self, risk_free_rate: float = 0.05):
self.r = risk_free_rate
def black_scholes_price(
self,
S: float,
K: float,
T: float,
r: float,
sigma: float,
option_type: str
) -> float:
"""
Calculate Black-Scholes option price
Args:
S: Spot price
K: Strike price
T: Time to expiry (years)
r: Risk-free rate
sigma: Volatility
option_type: 'call' or 'put'
"""
if T <= 0:
if option_type == 'call':
return max(S - K, 0)
return max(K - S, 0)
d1 = (np.log(S / K) + (r + sigma**2 / 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_newton(
self,
S: float,
K: float,
T: float,
r: float,
market_price: float,
option_type: str,
sigma_init: float = 0.3,
tol: float = 1e-6,
max_iter: int = 100
) -> Optional[float]:
"""
Calculate IV using Newton-Raphson method
Fast convergence but requires good initial guess
"""
sigma = sigma_init
for _ in range(max_iter):
bs_price = self.black_scholes_price(S, K, T, r, sigma, option_type)
if bs_price <= 0:
sigma *= 1.5
continue
# Vega - derivative of price with respect to sigma
d1 = (np.log(S / K) + (r + sigma**2 / 2) * T) / (sigma * np.sqrt(T))
vega = S * np.sqrt(T) * norm.pdf(d1)
if abs(vega) < 1e-10:
break
# Newton step
diff = bs_price - market_price
sigma_new = sigma - diff / vega
if abs(sigma_new - sigma) < tol:
return sigma_new
sigma = max(sigma_new, 0.01) # Ensure positive volatility
return None
def implied_volatility_brent(
self,
S: float,
K: float,
T: float,
r: float,
market_price: float,
option_type: str
) -> Optional[float]:
"""
Calculate IV using Brent's method
More robust, guaranteed convergence in bounded interval
"""
def objective(sigma):
bs_price = self.black_scholes_price(S, K, T, r, sigma, option_type)
return bs_price - market_price
try:
# Bracket the root
vol_low = 0.001
vol_high = 5.0
# Check if solution exists
p_low = objective(vol_low)
p_high = objective(vol_high)
if p_low * p_high > 0:
# Try to find valid bracket
for multiplier in [2, 3, 5, 10]:
vol_high = multiplier
p_high = objective(vol_high)
if p_low * p_high < 0:
break
return brentq(objective, vol_low, vol_high, xtol=1e-6)
except:
return None
def calculate_iv_surface(
self,
quotes: list,
spot_price: float,
risk_free_rate: float = 0.05
) -> pd.DataFrame:
"""
Calculate IV surface from option quotes
Returns DataFrame with IV for each strike/expiry combination
"""
results = []
for quote in quotes:
# Try Brent method first (more robust)
iv = self.implied_volatility_brent(
S=spot_price,
K=quote.strike,
T=quote.time_to_expiry,
r=risk_free_rate,
market_price=(quote.bid_price + quote.ask_price) / 2,
option_type=quote.option_type
)
if iv is None:
# Fallback to Newton
iv = self.implied_volatility_newton(
S=spot_price,
K=quote.strike,
T=quote.time_to_expiry,
r=risk_free_rate,
market_price=(quote.bid_price + quote.ask_price) / 2,
option_type=quote.option_type
)
results.append({
"instrument_name": quote.instrument_name,
"strike": quote.strike,
"expiry": quote.expiry,
"time_to_expiry": quote.time_to_expiry,
"option_type": quote.option_type,
"bid_price": quote.bid_price,
"ask_price": quote.ask_price,
"mid_price": (quote.bid_price + quote.ask_price) / 2,
"implied_volatility": iv,
"moneyness": spot_price / quote.strike,
"log_moneyness": np.log(spot_price / quote.strike)
})
return pd.DataFrame(results)
Ví dụ sử dụng với HolySheep AI
def generate_volatility_report(iv_data: pd.DataFrame, holysheep_api_key: str):
"""Use HolySheep AI to analyze IV data and generate insights"""
import openai
client = openai.OpenAI(
api_key=holysheep_api_key,
base_url="https://api.holysheep.ai/v1" # HolySheep API
)
# Prepare summary statistics
summary = iv_data.groupby(['time_to_expiry', 'option_type']).agg({
'implied_volatility': ['mean', 'std', 'min', 'max'],
'bid_price': 'mean',
'ask_price': 'mean'
}).round(4)
prompt = f"""Analyze this BTC options IV surface data and provide:
1. IV term structure observations
2. Skew analysis (call vs put IV)
3. Potential trading signals based on IV deviations
Data Summary:
{summary.to_string()}
Full data sample:
{iv_data.head(20).to_json()}
"""
response = client.chat.completions.create(
model="deepseek-v3.2", # $0.42/MTok - tiết kiệm tối đa
messages=[{"role": "user", "content": prompt}],
temperature=0.2
)
return response.choices[0].message.content
Calculate IV surface
calculator = ImpliedVolatilityCalculator(risk_free_rate=0.05)
iv_surface = calculator.calculate_iv_surface(quotes, spot_price=95000)
print(iv_surface.head(10))
Building Backtesting Engine với dữ liệu Deribit
Sau khi đã có dữ liệu Greeks và IV đầy đủ, bước tiếp theo là xây dựng backtesting engine để đánh giá chiến lược quyền chọn:
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
from typing import Dict, List, Callable
from dataclasses import dataclass
@dataclass
class Position:
"""Option position representation"""
instrument_name: str
quantity: int
entry_price: float
strike: float
expiry: datetime
option_type: str # 'call' or 'put'
delta: float
gamma: float
theta: float
vega: float
@dataclass
class BacktestResult:
"""Backtest result container"""
total_pnl: float
sharpe_ratio: float
max_drawdown: float
win_rate: float
total_trades: int
trades: List[Dict]
class OptionsBacktester:
"""
Backtesting engine for Deribit BTC options strategies
Features:
- Greeks-based position sizing
- Transaction cost modeling
- Margin/PnL calculation
"""
def __init__(
self,
initial_capital: float = 100_000,
taker_fee: float = 0.0004,
maker_fee: float = -0.0002
):
self.initial_capital = initial_capital
self.taker_fee = taker_fee
self.maker_fee = maker_fee
self.positions: List[Position] = []
self.trade_history: List[Dict] = []
self.capital = initial_capital
self.equity_curve = []
def calculate_portfolio_greeks(self) -> Dict[str, float]:
"""Calculate aggregate portfolio Greeks"""
total_delta = 0
total_gamma = 0
total_theta = 0
total_vega = 0
for pos in self.positions:
exposure = pos.quantity * pos.delta
total_delta += exposure
total_gamma += pos.quantity * pos.gamma
total_theta += pos.quantity * pos.theta
total_vega += pos.quantity * pos.vega
return {
"delta": total_delta,
"gamma": total_gamma,
"theta": total_theta,
"vega": total_vega,
"position_count": len(self.positions)
}
def calculate_unrealized_pnl(
self,
current_spot: float,
current_iv: float,
risk_free_rate: float = 0.05
) -> float:
"""Calculate unrealized P&L for all positions"""
pnl = 0
for pos in self.positions:
# Use Black-Scholes for current mark-to-market
T = (pos.expiry - datetime.now()).total_seconds() / (365 * 86400)
if T <= 0:
# Expired options
if pos.option_type == 'call':
intrinsic = max(current_spot - pos.strike, 0)
else:
intrinsic = max(pos.strike - current_spot, 0)
pnl += pos.quantity * (intrinsic - pos.entry_price)
else:
# Calculate current theoretical price
d1 = (np.log(current_spot / pos.strike) +
(risk_free_rate + current_iv**2 / 2) * T) / (current_iv * np.sqrt(T))
d2 = d1 - current_iv * np.sqrt(T)
if pos.option_type == 'call':
current_price = (current_spot * norm.cdf(d1) -
pos.strike * np.exp(-risk_free_rate * T) * norm.cdf(d2))
else:
current_price = (pos.strike * np.exp(-risk_free_rate * T) * norm.cdf(-d2) -
current_spot * norm.cdf(-d1))
pnl += pos.quantity * (current_price - pos.entry_price)
return pnl
def execute_strategy(
self,
data: pd.DataFrame,
strategy_func: Callable,
rebalance_frequency: str = '1h'
):
"""
Execute backtest with given strategy
Args:
data: Historical data with OHLCV, Greeks, IV
strategy_func: Function that generates trading signals
rebalance_frequency: How often to check and rebalance
"""
# Group data by rebalance frequency
data['timestamp'] = pd.to_datetime(data['timestamp'], unit='ms')
data = data.set_index('timestamp')
rebalance_times = data.resample(rebalance_frequency).first().index
for timestamp in rebalance_times:
try:
snapshot = data.loc[:timestamp].iloc[-1]
spot = snapshot['close']
iv = snapshot.get('mark_iv', snapshot.get('implied_volatility', 0.5))
# Get strategy signals
signals = strategy_func(snapshot, self.calculate_portfolio_greeks())
# Execute trades based on signals
for signal in signals:
self._execute_trade(signal, snapshot, spot, iv)
# Record equity
unrealized_pnl = self.calculate_unrealized_pnl(spot, iv)
total_equity = self.capital + unrealized_pnl
self.equity_curve.append({
'timestamp': timestamp,
'equity': total_equity,
'spot_price': spot
})
except Exception as e:
print(f"Error at {timestamp}: {e}")
continue
return self.generate_report()
def _execute_trade(self, signal: Dict, snapshot: pd.Series, spot: float, iv: float):
"""Execute a single trade"""
action = signal['action']
instrument = signal['instrument']
if action == 'buy':
cost = snapshot.get('ask', snapshot['close'])
fee = cost * self.taker_fee
self.capital -= (cost + fee) * signal['size']
self.positions.append(Position(
instrument_name=instrument,
quantity=signal['size'],
entry_price=cost,
strike=signal.get('strike', spot),
expiry=pd.to_datetime(signal['expiry']),
option_type=signal.get('type', 'call'),
delta=snapshot.get('delta', 0.5),
gamma=snapshot.get('gamma', 0),
theta=snapshot.get('theta', 0),
vega=snapshot.get('vega', 0)
))
elif action == 'sell':
revenue = snapshot.get('bid', snapshot['close'])
fee = revenue * self.taker_fee
self.capital += (revenue - fee) * signal['size']
# Remove from positions
self.positions = [p for p in self.positions if p.instrument_name != instrument]
self.trade_history.append({
'timestamp': snapshot.name if hasattr(snapshot, 'name') else datetime.now(),
'action': action,
'instrument': instrument,
'price': snapshot.get('close', 0)
})
def generate_report(self) -> BacktestResult:
"""Generate backtest performance report"""
df = pd.DataFrame(self.equity_curve)
df['returns'] = df['equity'].pct_change()
total_return = (df['equity'].iloc[-1] - self.initial_capital) / self.initial_capital
sharpe = df['returns'].mean() / df['returns'].std() * np.sqrt(365 * 24) if df['returns'].std() > 0 else 0
# Max drawdown
cummax = df['equity'].cummax()
drawdown = (df['equity'] - cummax) / cummax
max_dd = drawdown.min()
# Win rate
pnl_values = [t.get('pnl', 0) for t in self.trade_history]
wins = sum(1 for p in pnl_values if p > 0)
win_rate = wins / len(pnl_values) if pnl_values else 0
return BacktestResult(
total_pnl=total_return,
sharpe_ratio=sharpe,
max_drawdown=max_dd,
win_rate=win_rate,
total_trades=len(self.trade_history),
trades=self.trade_history
)
Example strategy using HolySheep AI
def iv_mean_reversion_strategy(snapshot: pd.Series, portfolio_greeks: Dict) -> List[Dict]:
"""IV mean reversion strategy - buy low IV, sell high IV"""
signals = []
iv = snapshot.get('implied_volatility', 0.5)
spot = snapshot['close']
# IV below 20th percentile - buy options
if iv < 0.2:
# Buy OTM calls
strike = spot * 1.05
signals.append({
'action': 'buy',
'instrument': f'BTC-{strike:.0f}-C',
'size': 1,
'strike': strike,
'type': 'call',
'expiry': datetime.now() + timedelta(days=30)
})
# IV above 80th percentile - sell options
elif iv > 0.8:
signals.append({
'action': 'sell',
'instrument': f'BTC-{spot * 0.95:.0f}-P',
'size': 1
})
return signals
Run backtest
backtester = OptionsBacktester(initial_capital=100_000)
results = backtester.execute_strategy(historical_data, iv_mean_reversion_strategy)
print(f