Mở đầu: Khi Độ biến động Nói lên Câu Chuyện Của Thị Trường

Tôi còn nhớ rõ ngày hôm đó - tháng 3 năm 2024, khi Bitcoin bất ngờ tăng 15% chỉ trong 4 giờ. Trong khi các trader amateur đang hân hoan vì lợi nhuận, tôi - lúc đó đang vận hành một quỹ tự quản - nhận ra rằng đây là thời điểm vàng để kiểm tra lại mô hình dự đoán biến động của mình. Tôi đã dành 3 ngày liên tục xây dựng công cụ phân tích volatility smile từ OKX options chain. Kết quả? Tôi đã bắt được đáy của đợt squeeze tiếp theo với độ chính xác khiến nhiều đồng nghiệp phải ngạc nhiên. Bài viết hôm nay sẽ chia sẻ toàn bộ quy trình, từ việc lấy dữ liệu options chain thô từ OKX cho đến việc xây dựng volatility smile - công cụ không thể thiếu của bất kỳ options trader chuyên nghiệp nào.

Volatility Smile Là Gì và Tại Sao Nó Quan Trọng?

Volatility smile (nụ cười biến động) là đồ thị thể hiện mối quan hệ giữa implied volatility (IV) và strike price của các options cùng ngày đáo hạn. Đặc điểm kinh điển của nó là:

Trong thị trường crypto, volatility smile càng quan trọng hơn vì:

Lấy Dữ Liệu OKX Options Chain qua HolySheep AI

Điều đầu tiên bạn cần là dữ liệu options chain thực tế. Thay vì phải tự viết scraper phức tạp, bạn có thể sử dụng HolySheep AI để phân tích và xử lý dữ liệu này với chi phí cực thấp - chỉ từ $0.42/MTok với DeepSeek V3.2, tiết kiệm đến 85% so với các provider khác.

import requests
import json
import pandas as pd
from datetime import datetime

Cấu hình HolySheep AI

HOLYSHEEP_API_KEY = "YOUR_HOLYSHEEP_API_KEY" HOLYSHEEP_BASE_URL = "https://api.holysheep.ai/v1" def query_okx_options_analysis(prompt: str) -> str: """ Gọi HolySheep AI để phân tích dữ liệu options Chi phí: ~$0.42/MTok với DeepSeek V3.2 (tiết kiệm 85%+) Độ trễ: <50ms """ headers = { "Authorization": f"Bearer {HOLYSHEEP_API_KEY}", "Content-Type": "application/json" } payload = { "model": "deepseek-v3.2", "messages": [ { "role": "system", "content": "Bạn là chuyên gia phân tích options và volatility. Hãy phân tích dữ liệu OKX options chain một cách chi tiết." }, { "role": "user", "content": prompt } ], "temperature": 0.3, "max_tokens": 2000 } response = requests.post( f"{HOLYSHEEP_BASE_URL}/chat/completions", headers=headers, json=payload ) if response.status_code == 200: return response.json()["choices"][0]["message"]["content"] else: raise Exception(f"API Error: {response.status_code} - {response.text}")

Ví dụ: Phân tích volatility smile hiện tại

analysis_prompt = """ Phân tích cấu trúc volatility smile cho BTC options trên OKX: - Underlying: BTC - Expiration: 2024-03-29 - Current spot: $68,500 - strikes: [60000, 62000, 64000, 66000, 68000, 70000, 72000, 74000] - IVs: [72%, 68%, 62%, 58%, 60%, 65%, 70%, 75%] Hãy nhận định: 1. Skew direction và mức độ 2. Cơ hội arbitrage 3. Khuyến nghị chiến lược """ result = query_okx_options_analysis(analysis_prompt) print("=== PHÂN TÍCH VOLATILITY SMILE ===") print(result)

Xây dựng Volatility Smile từ Dữ liệu Thực

Bây giờ, hãy xây dựng một hệ thống hoàn chỉnh để lấy dữ liệu từ OKX API và tính toán implied volatility cho mỗi strike price.

import requests
import numpy as np
from scipy.stats import norm
from scipy.optimize import brentq
import pandas as pd
from typing import Dict, List, Tuple
from datetime import datetime, timedelta
import json
import hashlib

class OKXOptionsDataFetcher:
    """Lấy dữ liệu options chain từ OKX Exchange"""
    
    def __init__(self, instrument_id: str = "BTC-USD"):
        self.base_url = "https://www.okx.com"
        self.instrument_id = instrument_id
        self.spot_price = self._get_spot_price()
    
    def _get_spot_price(self) -> float:
        """Lấy giá spot hiện tại của underlying"""
        endpoint = f"{self.base_url}/api/v5/market/ticker"
        params = {"instId": f"{self.instrument_id}-USD"}
        response = requests.get(endpoint, params=params)
        data = response.json()
        return float(data['data'][0]['last'])
    
    def get_options_chain(self, expiry: str) -> List[Dict]:
        """
        Lấy danh sách tất cả options cho một expiry cụ thể
        expiry format: "20240329"
        """
        endpoint = f"{self.base_url}/api/v5/market/opt/strike-price"
        params = {
            "instId": f"{self.instrument_id}-USD",
            "exp": expiry,
            "limit": "100"
        }
        
        response = requests.get(endpoint, params=params)
        data = response.json()
        
        options = []
        for strike_info in data['data']:
            strike = float(strike_info['strike'])
            opt_type = strike_info['optType']  # 'C' hoặc 'C'
            
            # Lấy thông tin chi tiết cho từng option
            inst_id = f"{self.instrument_id}-USD-{expiry}-{opt_type}-{int(strike)}"
            opt_data = self._get_option_details(inst_id)
            
            if opt_data:
                options.append({
                    'strike': strike,
                    'type': 'call' if opt_type == 'C' else 'put',
                    'bid': float(opt_data.get('bidPx', 0)),
                    'ask': float(opt_data.get('askPx', 0)),
                    'iv_bid': float(opt_data.get('bidIv', 0)),
                    'iv_ask': float(opt_data.get('askIv', 0)),
                    'volume': float(opt_data.get('vol24h', 0)),
                    'open_interest': float(opt_data.get('oi', 0))
                })
        
        return options
    
    def _get_option_details(self, inst_id: str) -> Dict:
        """Lấy chi tiết một option cụ thể"""
        endpoint = f"{self.base_url}/api/v5/market/ticker"
        params = {"instId": inst_id}
        
        try:
            response = requests.get(endpoint, params=params, timeout=5)
            return response.json()['data'][0]
        except:
            return {}


class BlackScholes:
    """Tính toán Black-Scholes và Implied Volatility"""
    
    @staticmethod
    def d1(S: float, K: float, T: float, r: float, sigma: float) -> float:
        return (np.log(S/K) + (r + sigma**2/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:
        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:
        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)
    
    @staticmethod
    def implied_volatility(price: float, S: float, K: float, T: float, 
                          r: float, option_type: str = 'call') -> float:
        """
        Tính IV bằng phương pháp Brent
        """
        def objective(sigma):
            if option_type == 'call':
                return BlackScholes.call_price(S, K, T, r, sigma) - price
            else:
                return BlackScholes.put_price(S, K, T, r, sigma) - price
        
        try:
            iv = brentq(objective, 0.001, 5.0)  # Tìm IV trong khoảng 0.1% - 500%
            return iv
        except:
            return np.nan


class VolatilitySmileBuilder:
    """Xây dựng và phân tích volatility smile"""
    
    def __init__(self, options_data: List[Dict], spot_price: float, 
                 time_to_expiry: float, risk_free_rate: float = 0.05):
        self.options_data = options_data
        self.spot_price = spot_price
        self.T = time_to_expiry
        self.r = risk_free_rate
        self.bs = BlackScholes()
    
    def calculate_iv_for_all_strikes(self) -> pd.DataFrame:
        """Tính IV cho tất cả các strikes"""
        
        results = []
        
        for opt in self.options_data:
            # Tính IV từ giá bid-ask trung bình
            mid_price = (opt['bid'] + opt['ask']) / 2
            
            # Nếu có sẵn IV từ exchange, sử dụng luôn
            if opt.get('iv_bid') and opt.get('iv_ask'):
                iv = (opt['iv_bid'] + opt['iv_ask']) / 2 / 100  # Convert từ %
            else:
                # Tính IV từ giá
                iv = self.bs.implied_volatility(
                    mid_price, self.spot_price, opt['strike'],
                    self.T, self.r, opt['type']
                )
            
            # Tính moneyness
            moneyness = opt['strike'] / self.spot_price
            
            results.append({
                'strike': opt['strike'],
                'type': opt['type'],
                'bid': opt['bid'],
                'ask': opt['ask'],
                'mid_price': mid_price,
                'iv': iv * 100 if not np.isnan(iv) else None,
                'moneyness': moneyness,
                'log_moneyness': np.log(moneyness),
                'volume': opt['volume'],
                'open_interest': opt['open_interest']
            })
        
        return pd.DataFrame(results)
    
    def fit_polynomial_smile(self, df: pd.DataFrame, degree: int = 2) -> np.poly1d:
        """Fit polynomial cho volatility smile"""
        # Chỉ sử dụng OTM options (puts cho strikes thấp, calls cho strikes cao)
        otm_puts = df[(df['type'] == 'put') & (df['strike'] < self.spot_price)]
        otm_calls = df[(df['type'] == 'call') & (df['strike'] >= self.spot_price)]
        
        # Kết hợp dữ liệu
        combined = pd.concat([otm_puts, otm_calls])
        
        # Loại bỏ NaN values
        combined = combined.dropna(subset=['iv', 'log_moneyness'])
        
        # Fit polynomial
        return np.polyfit(combined['log_moneyness'], combined['iv'], degree)
    
    def extract_vol_skew(self, df: pd.DataFrame) -> Dict:
        """Trích xuất các thông số skew quan trọng"""
        
        puts = df[df['type'] == 'put'].copy()
        calls = df[df['type'] == 'call'].copy()
        
        # 25-delta put IV
        atm_iv = df[abs(df['moneyness'] - 1) < 0.05]['iv'].mean()
        
        # 25-delta risk reversal (RR)
        rr = None
        if len(puts) >= 2 and len(calls) >= 2:
            low_strike_put = puts[puts['strike'] < self.spot_price].iloc[-1]
            high_strike_call = calls[calls['strike'] > self.spot_price].iloc[0]
            rr = high_strike_call['iv'] - low_strike_put['iv']
        
        # 25-delta butterfly
        bf = None
        if atm_iv:
            wing_iv = (low_strike_put['iv'] + high_strike_call['iv']) / 2
            bf = wing_iv - atm_iv
        
        return {
            'atm_vol': atm_iv,
            'risk_reversal_25d': rr,
            'butterfly_25d': bf,
            'smile_skew': abs(rr) if rr else 0
        }


==================== SỬ DỤNG THỰC TẾ ====================

def main(): print("=== VOLATILITY SMILE BUILDER ===") print(f"Thời gian: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") # Khởi tạo fetcher fetcher = OKXOptionsDataFetcher(instrument_id="BTC") # Lấy expiry tiếp theo (28 ngày) expiry = (datetime.now() + timedelta(days=28)).strftime("%Y%m%d") # Lấy dữ liệu options print(f"Đang lấy options chain cho expiry: {expiry}") options = fetcher.get_options_chain(expiry) # Tính T (năm) T = 28 / 365 # Xây dựng volatility smile builder = VolatilitySmileBuilder( options_data=options, spot_price=fetcher.spot_price, time_to_expiry=T, risk_free_rate=0.05 ) # Tính IV cho tất cả strikes df = builder.calculate_iv_for_all_strikes() print("\n=== VOLATILITY SMILE DATA ===") print(df.to_string()) # Trích xuất skew metrics skew_metrics = builder.extract_vol_skew(df) print("\n=== SKEW METRICS ===") for key, value in skew_metrics.items(): if value is not None: print(f"{key}: {value:.2f}%") # Fit polynomial smile poly_coeffs = builder.fit_polynomial_smile(df, degree=2) print(f"\n=== POLYNOMIAL COEFFICIENTS ===") print(f"y = {poly_coeffs[0]:.4f}x² + {poly_coeffs[1]:.4f}x + {poly_coeffs[2]:.4f}") return df, skew_metrics if __name__ == "__main__": df, metrics = main()

Trực quan hóa Volatility Smile

Để hiểu rõ hơn về cấu trúc biến động, hãy tạo các biểu đồ trực quan với matplotlib.

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from matplotlib.gridspec import GridSpec
import seaborn as sns

class VolatilitySmileVisualizer:
    """Trực quan hóa Volatility Smile"""
    
    def __init__(self, df: pd.DataFrame, spot_price: float):
        self.df = df
        self.spot_price = spot_price
        self._setup_style()
    
    def _setup_style(self):
        """Cấu hình style cho biểu đồ"""
        plt.style.use('seaborn-v0_8-darkgrid')
        self.fig = plt.figure(figsize=(16, 12))
        self.gs = GridSpec(3, 2, figure=self.fig, hspace=0.3, wspace=0.25)
    
    def plot_smile_3d(self):
        """Biểu đồ 3D của volatility surface"""
        ax = self.fig.add_subplot(self.gs[0, :], projection='3d')
        
        # Chuẩn bị dữ liệu
        strikes = self.df['strike'].values
        ivs = self.df['iv'].values
        moneyness = self.df['moneyness'].values
        
        # Scatter plot
        scatter = ax.scatter(strikes, moneyness, ivs, 
                            c=self.df['type'].map({'call': 'blue', 'put': 'red'}),
                            s=100, alpha=0.7)
        
        ax.set_xlabel('Strike Price')
        ax.set_ylabel('Moneyness (K/S)')
        ax.set_zlabel('Implied Volatility (%)')
        ax.set_title('Volatility Smile - 3D View')
        
        return ax
    
    def plot_smile_2d(self):
        """Biểu đồ 2D cổ điển của volatility smile"""
        ax = self.fig.add_subplot(self.gs[1, 0])
        
        # Phân tách calls và puts
        puts = self.df[self.df['type'] == 'put']
        calls = self.df[self.df['type'] == 'call']
        
        # Vẽ đường cong
        ax.plot(puts['strike'], puts['iv'], 'ro-', label='Puts', markersize=8)
        ax.plot(calls['strike'], calls['iv'], 'bo-', label='Calls', markersize=8)
        
        # Đánh dấu ATM
        atm_strike = self.spot_price
        ax.axvline(x=atm_strike, color='green', linestyle='--', alpha=0.5, label='ATM')
        ax.axhline(y=puts[abs(puts['strike'] - atm_strike) < 1000]['iv'].mean(), 
                  color='gray', linestyle=':', alpha=0.5)
        
        ax.set_xlabel('Strike Price (USD)')
        ax.set_ylabel('Implied Volatility (%)')
        ax.set_title('Volatility Smile - 2D View')
        ax.legend()
        ax.grid(True, alpha=0.3)
        
        return ax
    
    def plot_skew_metrics(self, metrics: Dict):
        """Biểu đồ các chỉ số skew"""
        ax = self.fig.add_subplot(self.gs[1, 1])
        
        metrics_names = list(metrics.keys())
        metrics_values = list(metrics.values())
        
        colors = ['#3498db' if v >= 0 else '#e74c3c' for v in metrics_values]
        bars = ax.barh(metrics_names, metrics_values, color=colors, alpha=0.7)
        
        ax.axvline(x=0, color='black', linestyle='-', linewidth=0.5)
        ax.set_xlabel('Volatility (%)')
        ax.set_title('Skew Metrics')
        
        # Thêm giá trị trên thanh
        for bar, val in zip(bars, metrics_values):
            if val is not None:
                ax.text(val + 0.5 if val >= 0 else val - 0.5, 
                       bar.get_y() + bar.get_height()/2,
                       f'{val:.1f}%', va='center', fontsize=10)
        
        return ax
    
    def plot_term_structure(self, time_strikes: List[Dict]):
        """Biểu đồ term structure của ATM volatility"""
        ax = self.fig.add_subplot(self.gs[2, :])
        
        # Giả sử có dữ liệu cho nhiều expiry
        expiries = [d['expiry'] for d in time_strikes]
        atm_vols = [d['atm_vol'] for d in time_strikes]
        
        ax.plot(expiries, atm_vols, 'go-', markersize=10, linewidth=2, label='ATM Vol')
        ax.fill_between(expiries, atm_vols, alpha=0.3)
        
        ax.set_xlabel('Expiry Date')
        ax.set_ylabel('ATM Implied Volatility (%)')
        ax.set_title('ATM Volatility Term Structure')
        ax.grid(True, alpha=0.3)
        
        # Format trục x
        ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
        plt.setp(ax.xaxis.get_majorticklabels(), rotation=45)
        
        return ax
    
    def save_and_show(self, filename: str = 'volatility_smile.png'):
        """Lưu và hiển thị biểu đồ"""
        plt.tight_layout()
        plt.savefig(filename, dpi=150, bbox_inches='tight')
        print(f"Biểu đồ đã lưu: {filename}")
        plt.show()


def create_volatility_report(df: pd.DataFrame, metrics: Dict, 
                             spot_price: float) -> str:
    """
    Tạo báo cáo phân tích volatility smile
    Gửi kết quả đến HolySheep AI để phân tích chuyên sâu
    """
    
    # Chuẩn bị dữ liệu tổng hợp
    report_data = {
        'spot_price': spot_price,
        'total_options': len(df),
        'strike_range': f"{df['strike'].min():.0f} - {df['strike'].max():.0f}",
        'iv_range': f"{df['iv'].min():.1f}% - {df['iv'].max():.1f}%",
        'atm_iv': metrics.get('atm_vol', 0),
        'risk_reversal': metrics.get('risk_reversal_25d', 0),
        'butterfly': metrics.get('butterfly_25d', 0)
    }
    
    report_prompt = f"""
    PHÂN TÍCH VOLATILITY SMILE - BÁO CÁO TỰ ĐỘNG
    
    === THÔNG TIN THỊ TRƯỜNG ===
    - Spot Price: ${report_data['spot_price']:,.0f}
    - Số lượng Options: {report_data['total_options']}
    - Strike Range: {report_data['strike_range']}
    - IV Range: {report_data['iv_range']}
    
    === SKEW METRICS ===
    - ATM IV: {report_data['atm_iv']:.2f}%
    - 25-Delta Risk Reversal: {report_data['risk_reversal']:.2f}%
    - 25-Delta Butterfly: {report_data['butterfly']:.2f}%
    
    === DỮ LIỆU CHI TIẾT (TOP 10) ===
    {df.nlargest(10, 'open_interest')[['strike', 'type', 'iv', 'volume', 'open_interest']].to_string()}
    
    Hãy phân tích:
    1. Đặc điểm của volatility smile hiện tại
    2. So sánh với các đợt volatility squeeze trước đó
    3. Cơ hội trading và risks
    4. Khuyến nghị chiến lược options cụ thể
    """
    
    return report_prompt


==================== CHẠY TRỰC QUAN HÓA ====================

if __name__ == "__main__": # Giả lập dữ liệu cho demo np.random.seed(42) spot = 68500 demo_data = [] for k in np.linspace(55000, 80000, 26): iv_base = 60 - 0.5 * ((k - spot)/spot)**2 * 100 # Parabola shape iv_put = iv_base + 5 * (spot/k - 1) * 100 + np.random.normal(0, 2) iv_call = iv_base - 5 * (k/spot - 1) * 100 + np.random.normal(0, 2) demo_data.append({ 'strike': k, 'type': 'put', 'iv': max(30, iv_put), 'bid': 100, 'ask': 102, 'volume': np.random.randint(100, 1000), 'open_interest': np.random.randint(500, 5000) }) demo_data.append({ 'strike': k, 'type': 'call', 'iv': max(30, iv_call), 'bid': 100, 'ask': 102, 'volume': np.random.randint(100, 1000), 'open_interest': np.random.randint(500, 5000) }) df = pd.DataFrame(demo_data) df['moneyness'] = df['strike'] / spot df['log_moneyness'] = np.log(df['moneyness']) metrics = { 'atm_vol': df[abs(df['moneyness'] - 1) < 0.05]['iv'].mean(), 'risk_reversal_25d': 3.5, 'butterfly_25d': -1.2, 'smile_skew': 3.5 } # Tạo visualizer viz = VolatilitySmileVisualizer(df, spot) viz.plot_smile_2d() viz.plot_skew_metrics(metrics) viz.save_and_show('volatility_smile_demo.png') # Tạo báo cáo gửi đến AI report = create_volatility_report(df, metrics, spot) print("\n=== REPORT PROMPT FOR AI ===") print(report)

Chiến lược Trading dựa trên Volatility Smile

Sau khi có volatility smile, bạn có thể áp dụng nhiều chiến lược options. Dưới đây là một số chiến lược phổ biến được tích hợp với AI để phân tích tự động.

import numpy as np
from dataclasses import dataclass
from typing import Optional, List
from enum import Enum

class StrategyType(Enum):
    RISK_REVERSAL = "risk_reversal"
    COLLAR = "collar"
    IRON_CONDOR = "iron_condor"
    STRADDLE = "straddle"
    BUTTERFLY = "butterfly"
    Calendar = "calendar"

@dataclass
class Option:
    strike: float
    premium: float
    option_type: str  # 'call' or 'put'
    expiry: str

@dataclass
class Strategy:
    name: str
    legs: List[Option]
    max_profit: Optional[float]
    max_loss: Optional[float]
    breakeven: List[float]

class OptionsStrategyAnalyzer:
    """Phân tích và đề xuất chiến lược options dựa trên volatility smile"""
    
    def __init__(self, spot_price: float, iv_surface: dict, 
                 risk_free_rate: float = 0.05):
        self.spot = spot_price
        self.iv = iv_surface
        self.r = risk_free_rate
    
    def analyze_risk_reversal(self, tenor_days: int = 30) -> Strategy:
        """
        Chiến lược Risk Reversal:
        - Bán OTM put (được premium)
        - Mua OTM call (trả premium)
        - Thường used khi expect upside nhưng muốn hedge downside
        """
        
        # Tìm strikes phù hợp
        otm_put_strike = self.spot * 0.95  # 5% OTM
        otm_call_strike = self.spot * 1.05  # 5% OTM
        
        T = tenor_days / 365
        
        # Ước tính premium sử dụng BS
        put_premium = self._estimate_premium(otm_put_strike, T, 'put')
        call_premium = self._estimate_premium(otm_call_strike, T, 'call')
        
        net_credit = put_premium - call_premium
        
        # Max profit: unlimited upside minus net credit
        # Max loss: (otm_put_strike - spot) + net_credit
        max_loss = (self.spot - otm_put_strike) - net_credit
        breakeven = self.spot - max_loss
        
        return Strategy(
            name="Risk Reversal",
            legs=[
                Option(otm_put_strike, put_premium, 'put', f"{tenor_days}d"),
                Option(otm_call_strike, call_premium, 'call', f"{tenor_days}d")
            ],
            max_profit=None,  # Unlimited
            max_loss=max_loss,
            breakeven=[breakeven]
        )
    
    def analyze_iron_condor(self, tenor_days: int = 30) -> Strategy:
        """
        Chiến lược Iron Condor:
        - Bán OTM call spread
        - Bán OTM put spread
        - Profit khi price stay within range
        """
        
        wings = 0.05  # 5% wings
        body = 0.025  # 2.5% body width
        
        put_sell = self.spot * (1 - body)
        put_buy = self.spot * (1 - wings)
        call_sell = self.spot * (1 + body)
        call_buy = self.spot * (1 + wings)
        
        T = tenor_days / 365
        
        premiums = {
            'put_sell': self._estimate_premium(put_sell, T, 'put'),
            'put_buy': self._estimate_premium(put_buy, T, 'put'),
            'call_sell': self._estimate_premium(call_sell, T, 'call'),
            'call_buy': self._estimate_premium(call_buy, T, 'call')
        }
        
        net_credit = (premiums['put_sell'] - premiums['put_buy'] + 
                     premiums['call_sell'] - premiums['call_buy'])
        
        max_profit = net_credit
        max_loss = (wings - body) * self.spot - net_credit
        
        breakeven = [self.spot - body * self.spot - net_credit,
                    self.spot + body * self.spot + net