บทนำ

การเทรดความผันผวน (Volatility Trading) เป็นหนึ่งในกลยุทธ์ขั้นสูงที่นักเทรดระดับมืออาชีพใช้ในการสร้างผลตอบแทนจากการเคลื่อนไหวของราคาสินทรัพย์โดยไม่จำเป็นต้องรู้ทิศทางที่แน่นอน ในบทความนี้ผมจะพาทุกท่านเจาะลึกถึงหลักการทำงานของ Greeks (Delta, Gamma, Theta, Vega, Rho) วิธีการคำนวณ และการสร้างระบบ Backtesting ที่เชื่อถือได้สำหรับกลยุทธ์ Volatility Arbitrage จากประสบการณ์การพัฒนาระบบ Quantitative Trading มากว่า 8 ปี ผมพบว่าการเข้าใจ Greeks อย่างลึกซึ้งคือกุญแจสำคัญในการบริหารความเสี่ยงและสร้างผลตอบแทนที่ยั่งยืน โดยเฉพาะในตลาดที่มีความผันผวนสูงอย่างตลาดคริปโตหรือตลาดฟิวเจอร์ส ---

ความเข้าใจพื้นฐานเกี่ยวกับ Volatility

Volatility คืออะไร

Volatility หรือความผันผวน คือการวัดอัตราการเปลี่ยนแปลงของราคาสินทรัพย์ในช่วงเวลาที่กำหนด ในทางคณิตศาสตร์เราใช้ **Standard Deviation** ในการคำนวณ:
σ = √(Σ(Ri - μ)² / N)
โดยที่: - σ (Sigma) = ความผันผวน (Volatility) - Ri = ผลตอบแทนในช่วง i - μ = ผลตอบแทนเฉลี่ย - N = จำนวนข้อมูล

Historical Volatility vs Implied Volatility

**Historical Volatility (HV)** คำนวณจากข้อมูลราคาในอดีต ใช้สำหรับวัดความผันผวนที่เกิดขึ้นจริง **Implied Volatility (IV)** คำนวณย้อนกลับจากราคาตราสารอนุพันธ์ (Derivatives) โดยใช้ Black-Scholes Model ซึ่งสะท้อนความคาดหวังของตลาดต่อความผันผวนในอนาคต ส่วนต่างระหว่าง IV และ HV คือ **Volatility Risk Premium** ซึ่งเป็นหัวใจสำคัญของกลยุทธ์ Volatility Arbitrage ---

Greeks: เครื่องมือวัดความเสี่ยงของออปชัน

Greeks คือตัวแปรที่ใช้วัดความอ่อนไหวของราคาออปชันต่อปัจจัยต่างๆ ในตลาด ซึ่งประกอบด้วย 5 ตัวหลัก:

1. Delta (Δ) - ความอ่อนไหวต่อราคาสินทรัพย์

Delta วัดการเปลี่ยนแปลงของราคาออปชันเมื่อราคาสินทรัพย์อ้างอิง (Underlying Asset) เปลี่ยนแปลง 1 หน่วย
Delta (Call) = N(d1)
Delta (Put) = N(d1) - 1
import numpy as np
from scipy.stats import norm

def calculate_delta(S, K, T, r, sigma, option_type='call'):
    """
    คำนวณ Delta ของออปชัน
    S: ราคาปัจจุบันของสินทรัพย์อ้างอิง
    K: Strike Price
    T: เวลาที่เหลือ (ปี)
    r: อัตราดอกเบี้ยปลอดความเสี่ยง
    sigma: ความผันผวน
    """
    d1 = (np.log(S / K) + (r + 0.5 * sigma**2) * T) / (sigma * np.sqrt(T))
    
    if option_type == 'call':
        delta = norm.cdf(d1)
    else:
        delta = norm.cdf(d1) - 1
    
    return delta

ตัวอย่างการใช้งาน

Delta ของ Call Option

call_delta = calculate_delta(S=100, K=100, T=30/365, r=0.05, sigma=0.2, option_type='call') print(f"Call Delta: {call_delta:.4f}") # ผลลัพธ์: ~0.5248

Delta ของ Put Option

put_delta = calculate_delta(S=100, K=100, T=30/365, r=0.05, sigma=0.2, option_type='put') print(f"Put Delta: {put_delta:.4f}") # ผลลัพธ์: ~-0.4752

2. Gamma (Γ) - อัตราการเปลี่ยนแปลงของ Delta

Gamma วัดอัตราการเปลี่ยนแปลงของ Delta เมื่อราคาสินทรัพย์อ้างอิงเปลี่ยนแปลง 1 หน่วย
def calculate_gamma(S, K, T, r, sigma):
    """
    คำนวณ Gamma ของออปชัน
    Gamma เหมือนกันสำหรับ Call และ Put
    """
    d1 = (np.log(S / K) + (r + 0.5 * sigma**2) * T) / (sigma * np.sqrt(T))
    
    gamma = norm.pdf(d1) / (S * sigma * np.sqrt(T))
    
    return gamma

ตัวอย่างการใช้งาน

gamma = calculate_gamma(S=100, K=100, T=30/365, r=0.05, sigma=0.2) print(f"Gamma: {gamma:.6f}") # ผลลัพธ์: ~0.0242

Gamma จะสูงสุดเมื่อออปชันอยู่ At-The-Money (ATM)

และจะลดลงเมื่อออปชันอยู่ In-The-Money (ITM) หรือ Out-Of-The-Money (OTM)

3. Theta (Θ) - การสึกกร่อนของมูลค่าตามเวลา

Theta วัดการเปลี่ยนแปลงของราคาออปชันเมื่อเวลาผ่านไป 1 วัน
def calculate_theta(S, K, T, r, sigma, option_type='call'):
    """
    คำนวณ Theta ของออปชัน (ต่อวัน)
    """
    d1 = (np.log(S / K) + (r + 0.5 * sigma**2) * T) / (sigma * np.sqrt(T))
    d2 = d1 - sigma * np.sqrt(T)
    
    first_term = -(S * norm.pdf(d1) * sigma) / (2 * np.sqrt(T))
    
    if option_type == 'call':
        theta = (first_term - r * K * np.exp(-r * T) * norm.cdf(d2)) / 365
    else:
        theta = (first_term + r * K * np.exp(-r * T) * norm.cdf(-d2)) / 365
    
    return theta

ตัวอย่างการใช้งาน

call_theta = calculate_theta(S=100, K=100, T=30/365, r=0.05, sigma=0.2, option_type='call') put_theta = calculate_theta(S=100, K=100, T=30/365, r=0.05, sigma=0.2, option_type='put') print(f"Call Theta (ต่อวัน): {call_theta:.4f}") # ผลลัพธ์: ~-0.0167 print(f"Put Theta (ต่อวัน): {put_theta:.4f}") # ผลลัพธ์: ~-0.0093

Theta ของ Put มักจะน้อยกว่า Call เพราะ Put มีค่า Intrinsic Value

จากดอกเบี้ยที่ได้รับเมื่อถือเงินสดแทนหุ้น

4. Vega (Ν) - ความอ่อนไหวต่อความผันผวน

Vega วัดการเปลี่ยนแปลงของราคาออปชันเมื่อ Implied Volatility เปลี่ยนแปลง 1%
def calculate_vega(S, K, T, r, sigma):
    """
    คำนวณ Vega ของออปชัน (% ต่อ 1% IV change)
    Vega เหมือนกันสำหรับ Call และ Put
    """
    d1 = (np.log(S / K) + (r + 0.5 * sigma**2) * T) / (sigma * np.sqrt(T))
    
    vega = S * norm.pdf(d1) * np.sqrt(T) / 100
    
    return vega

ตัวอย่างการใช้งาน

vega = calculate_vega(S=100, K=100, T=30/365, r=0.05, sigma=0.2) print(f"Vega: {vega:.4f}") # ผลลัพธ์: ~0.1212

หมายความว่า ถ้า IV เพิ่มขึ้น 1% ราคาออปชันจะเพิ่มขึ้น ~0.12 บาท

5. Rho (ρ) - ความอ่อนไหวต่ออัตราดอกเบี้ย

Rho วัดการเปลี่ยนแปลงของราคาออปชันเมื่ออัตราดอกเบี้ยปลอดความเสี่ยงเปลี่ยนแปลง 1%
def calculate_rho(S, K, T, r, sigma, option_type='call'):
    """
    คำนวณ Rho ของออปชัน (% ต่อ 1% การเปลี่ยนแปลงของ r)
    """
    d1 = (np.log(S / K) + (r + 0.5 * sigma**2) * T) / (sigma * np.sqrt(T))
    d2 = d1 - sigma * np.sqrt(T)
    
    if option_type == 'call':
        rho = K * T * np.exp(-r * T) * norm.cdf(d2) / 100
    else:
        rho = -K * T * np.exp(-r * T) * norm.cdf(-d2) / 100
    
    return rho

ตัวอย่างการใช้งาน

call_rho = calculate_rho(S=100, K=100, T=30/365, r=0.05, sigma=0.2, option_type='call') print(f"Call Rho: {call_rho:.4f}") # ผลลัพธ์: ~0.0126
---

กลยุทธ์ Volatility Trading หลัก

กลยุทธ์ที่ 1: Volatility Arbitrage

กลยุทธ์นี้ใช้ประโยชน์จากส่วนต่างระหว่าง Implied Volatility และ Historical Volatility
class VolatilityArbitrageStrategy:
    def __init__(self, symbol, entry_iv_threshold=30, exit_iv_threshold=20):
        self.symbol = symbol
        self.entry_iv_threshold = entry_iv_threshold  # IV ที่จะเข้า Order
        self.exit_iv_threshold = exit_iv_threshold    # IV ที่จะออก Order
        self.position = None
        self.entry_iv = None
        
    def calculate_hv(self, prices, window=20):
        """คำนวณ Historical Volatility"""
        returns = np.diff(np.log(prices))
        hv = np.std(returns[-window:]) * np.sqrt(252) * 100
        return hv
    
    def calculate_iv(self, option_price, S, K, T, r):
        """คำนวณ Implied Volatility โดยใช้ Newton-Raphson"""
        def black_scholes_call(S, K, T, r, sigma):
            d1 = (np.log(S/K) + (r + 0.5*sigma**2)*T) / (sigma*np.sqrt(T))
            d2 = d1 - sigma*np.sqrt(T)
            return S*norm.cdf(d1) - K*np.exp(-r*T)*norm.cdf(d2)
        
        sigma = 0.2  # Initial guess
        for _ in range(100):
            price = black_scholes_call(S, K, T, r, sigma)
            vega = S * norm.pdf((np.log(S/K) + (r + 0.5*sigma**2)*T) / 
                               (sigma*np.sqrt(T))) * np.sqrt(T)
            diff = option_price - price
            if abs(diff) < 1e-6:
                break
            sigma += diff / (vega * 100)
        
        return sigma * 100  # Return as percentage
    
    def generate_signal(self, current_price, option_price, strike, expiry_days):
        """สร้างสัญญาณเข้า/ออก Order"""
        T = expiry_days / 365
        r = 0.05  # Risk-free rate
        
        # คำนวณ IV
        iv = self.calculate_iv(option_price, current_price, strike, T, r)
        
        # สร้างสัญญาณ
        if self.position is None:
            if iv >= self.entry_iv_threshold:
                self.position = 'long_volatility'
                self.entry_iv = iv
                return 'BUY', iv
        else:
            if iv <= self.exit_iv_threshold:
                self.position = None
                return 'SELL', iv
        
        return 'HOLD', iv

ตัวอย่างการใช้งาน

strategy = VolatilityArbitrageStrategy( symbol='SPY', entry_iv_threshold=30, exit_iv_threshold=20 )

ทดสอบสัญญาณ

signal, iv = strategy.generate_signal( current_price=450, option_price=15, strike=450, expiry_days=30 ) print(f"Signal: {signal}, IV: {iv:.2f}%")

กลยุทธ์ที่ 2: Delta Hedged Strategy

กลยุทธ์นี้ใช้ Delta ในการป้องกันความเสี่ยงจากการเคลื่อนไหวของราคา โดยเปิดสถานะสินทรัพย์อ้างอิงในทิศทางตรงข้าม
class DeltaHedgedStrategy:
    def __init__(self, target_delta=0):
        self.target_delta = target_delta
        self.position_pnl = []
        
    def calculate_hedge_ratio(self, option_delta, option_size, underlying_price):
        """คำนวณจำนวนสินทรัพย์อ้างอิงที่ต้องซื้อ/ขายเพื่อ Delta Hedge"""
        total_option_delta = option_delta * option_size
        shares_to_hedge = -total_option_delta / self.target_delta
        return shares_to_hedge
    
    def rebalance(self, current_price, strike, T, r, sigma, 
                  current_shares, option_position):
        """
        Rebalance สถานะเพื่อรักษา Delta Neutral
        """
        # คำนวณ Delta ปัจจุบัน
        current_delta = calculate_delta(current_price, strike, T, r, sigma, 'call')
        
        # คำนวณ Delta ของสถานะทั้งหมด
        total_delta = (current_delta * option_position + 
                      current_shares / current_price)
        
        # คำนวณ Delta ที่ต้องการ
        desired_delta = self.target_delta * (option_position + 1)
        
        # คำนวณการเปลี่ยนแปลง
        delta_diff = desired_delta - total_delta
        shares_to_trade = delta_diff * current_price
        
        return shares_to_trade, total_delta
    
    def backtest_single_period(self, price_path, strike, T, r, sigma, initial_shares=0):
        """
        ทดสอบกลยุทธ์ในช่วงเวลาหนึ่ง
        """
        results = []
        current_shares = initial_shares
        
        for i in range(len(price_path) - 1):
            S = price_path[i]
            S_next = price_path[i + 1]
            T_remaining = T - (i / 252)  # ลดเวลาตามวันที่ผ่านไป
            
            if T_remaining <= 0:
                break
                
            # คำนวณ Delta ปัจจุบัน
            current_delta = calculate_delta(S, strike, T_remaining, r, sigma, 'call')
            
            # Rebalance
            shares_to_trade, total_delta = self.rebalance(
                S, strike, T_remaining, r, sigma, current_shares, 1
            )
            
            # คำนวณ P&L
            underlying_pnl = current_shares * (S_next - S)
            option_price = max(S_next - strike, 0) - max(S - strike, 0)
            
            total_pnl = underlying_pnl + option_price
            self.position_pnl.append(total_pnl)
            
            results.append({
                'price': S,
                'delta': current_delta,
                'shares': current_shares,
                'pnl': total_pnl
            })
            
            # อัปเดตสถานะ
            current_shares += shares_to_trade
        
        return results

ทดสอบกลยุทธ์

strategy = DeltaHedgedStrategy(target_delta=0) np.random.seed(42) price_path = 100 + np.cumsum(np.random.randn(30) * 0.5) results = strategy.backtest_single_period( price_path=price_path, strike=100, T=30/365, r=0.05, sigma=0.2 )

กลยุทธ์ที่ 3: Gamma Scalping

กลยุทธ์นี้ใช้ประโยชน์จาก Theta Decay โดยการเปิดสถานะที่มี Gamma สูงและ Rebalance สม่ำเสมอ
class GammaScalpingStrategy:
    def __init__(self, target_gamma_exposure=0.5):
        self.target_gamma_exposure = target_gamma_exposure
        self.transaction_costs = 0.001  # 0.1% ต่อครั้ง
        
    def calculate_gamma_exposure(self, delta, gamma, position_size, underlying_price):
        """
        คำนวณ Dollar Gamma Exposure (GEX)
        GEX = Gamma * Position_Size * Underlying_Price^2
        """
        gex = gamma * position_size * underlying_price**2 / 100
        return gex
    
    def optimal_rebalance_frequency(self, gamma, volatility, transaction_cost):
        """
        คำนวณความถี่ที่เหมาะสมในการ Rebalance
        โดยใช้สมการของ Marion และ Mastron:
        Optimal Frequency ∝ √(Γ * σ² / TC)
        """
        optimal_freq = np.sqrt(gamma * volatility**2 / transaction_cost)
        return optimal_freq
    
    def simulate_gamma_scalp(self, S0, mu, sigma, T, K, r, rebalance_days=5):
        """
        จำลองกลยุทธ์ Gamma Scalping
        """
        np.random.seed(42)
        n_steps = int(T * 252)
        dt = T / n_steps
        
        # สร้างราคา
        prices = [S0]
        for _ in range(n_steps):
            z = np.random.randn()
            S_next = prices[-1] * np.exp((mu - 0.5*sigma**2)*dt + sigma*np.sqrt(dt)*z)
            prices.append(S_next)
        
        # ติดตามผล
        portfolio_values = []
        hedge_ratio = 0
        cumulative_theta = 0
        cumulative_gamma_pnl = 0
        
        for i in range(0, n_steps, rebalance_days):
            S = prices[i]
            T_remaining = T - i/252
            
            if T_remaining <= 0:
                break
            
            # คำนวณ Greeks
            d1 = (np.log(S/K) + (r + 0.5*sigma**2)*T_remaining) / (sigma*np.sqrt(T_remaining))
            delta = norm.cdf(d1)
            gamma = norm.pdf(d1) / (S * sigma * np.sqrt(T_remaining))
            theta = -(S * norm.pdf(d1) * sigma) / (2 * np.sqrt(T_remaining)) / 365
            
            # คำนวณ Theta P&L
            theta_pnl = theta * rebalance_days
            cumulative_theta += theta_pnl
            
            # คำนวณ Gamma P&L
            S_next = prices[min(i + rebalance_days, len(prices)-1)]
            gamma_pnl = 0.5 * gamma * S**2 * ((S_next - S)/S)**2 * 100
            cumulative_gamma_pnl += gamma_pnl
            
            # Rebalance Hedge
            hedge_ratio = -delta
            
            portfolio_values.append({
                'day': i,
                'price': S,
                'delta': delta,
                'gamma': gamma,
                'theta_pnl': theta_pnl,
                'gamma_pnl': gamma_pnl
            })
        
        return portfolio_values, cumulative_theta, cumulative_gamma_pnl

ทดสอบกลยุทธ์

strategy = GammaScalpingStrategy() results, total_theta, total_gamma = strategy.simulate_gamma_scalp( S0=100, mu=0.05, sigma=0.2, T=30/365, K=100, r=0.05, rebalance_days=3 ) print(f"Total Theta P&L: {total_theta:.4f}") print(f"Total Gamma P&L: {total_gamma:.4f}") print(f"Net P&L: {total_theta + total_gamma:.4f}")
---

ระบบ Backtesting สำหรับ Volatility Strategies

การสร้าง Backtesting Engine

```python import pandas as pd from datetime import datetime, timedelta import warnings warnings.filterwarnings('ignore') class VolatilityBacktester: def __init__(self, initial_capital=100000, transaction_cost=0.001): self.initial_capital = initial_capital self.transaction_cost = transaction_cost self.results = [] def load_market_data(self, filepath): """โหลดข้อมูลตลาดจาก CSV""" df = pd.read_csv(filepath) df['timestamp'] = pd.to_datetime(df['timestamp']) df.set_index('timestamp', inplace=True) return df def generate_synthetic_data(self, S0, mu, sigma, days, trading_days=252): """สร้างข้อมูลสังเคราะห์สำหรับทดสอบ""" dates = pd.date_range(start='2023-01-01', periods=days, freq='D') n = len(dates) dt = 1 / trading_days drift = (mu - 0.5 * sigma**2) * dt diffusion = sigma * np.sqrt(dt) returns = np.random.normal(drift, diffusion, n) prices = S0 * np.exp(np.cumsum(returns)) # เพิ่ม Volatility Clustering (GARCH-like effect) volatility_regime = np.random.choice([0.5, 1.5], n, p=[0.7, 0.3]) prices = prices * volatility_regime.cumprod() df = pd.DataFrame({ 'open': prices * (1 + np.random.uniform(-0.01, 0.01, n)), 'high': prices * (1 + np.random.uniform(0, 0.02, n)), 'low': prices * (1 - np.random.uniform(0, 0.02, n)), 'close': prices, 'volume': np.random.randint(1000000, 10000000, n) }, index=dates) return df def calculate_portfolio_metrics(self, portfolio_value, risk_free_rate=0.05): """คำนวณ Portfolio Metrics""" returns = np.diff(portfolio_value) / portfolio_value[:-1] # Annualized Return total_days = len(portfolio_value) annual_return = (portfolio_value[-1] / portfolio_value[0]) ** (252/total_days) - 1 # Annualized Volatility annual_volatility = np.std(returns) * np.sqrt(252) # Sharpe Ratio excess_return = annual_return - risk_free_rate sharpe_ratio = excess_return / annual_volatility if annual_volatility > 0 else 0 # Maximum Drawdown cumulative = portfolio_value / portfolio_value[0] running_max = np.maximum.accumulate(cumulative) drawdown = (cumulative - running_max) / running_max max_drawdown = drawdown.min() # Calmar Ratio calmar_ratio = annual_return / abs(max_drawdown) if max_drawdown != 0 else 0 return { 'total_return': (portfolio_value[-1] - portfolio_value[0]) / portfolio_value[0], 'annual_return': annual_return, 'annual_volatility': annual_volatility, 'sharpe_ratio': sharpe_ratio, 'max_drawdown': max_drawdown, 'calmar_ratio': calmar_ratio, 'win_rate': len(returns[returns > 0]) / len(returns) } def run_backtest(self, strategy, market_data, params): """Run Backtest""" capital = self.initial_capital portfolio_value = [capital] position = 0 trades = [] for i in range(len(market_data) - 1): current_price = market_data['close'].iloc[i] next_price = market_data['close'].iloc[i + 1] # สร้างสัญญาณ signal, iv = strategy.generate_signal( current_price=current_price, option_price=params.get('option_premium', current_price * 0.05), strike=params.get('strike', current_price), expiry_days=params.get('expiry_days', 30) ) # ดำเนินการตามสัญญาณ if signal == 'BUY' and position == 0: shares = capital * params.get('position_size', 0.1) / current_price cost = shares * current_price * (1 + self.transaction_cost) position = shares capital -=