Options Trading System

Integrate all the theory from previous chapters into a working trading system.

๐Ÿ”ฅ Vibe Prompt

"Build an options trading system in Python: real-time stock prices, Black-Scholes pricing, Greeks calculation, strategy signal generation, and risk monitoring alerts. Output buy/sell recommendations and risk metrics."

System Architecture

Market Data โ†’ Pricing Engine โ†’ Strategy Signals โ†’ Risk Control โ†’ Trade Execution
    โ†‘                                                             โ†“
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Feedback Loop (Performance) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Practice Exercise

๐Ÿ’ก Vibe Coding Practice: Ask AI to build a "Complete Options Trading Platform":

  1. Real-time stock price feed (yfinance or API)
  2. Option pricing and Greeks calculation
  3. Strategy signal generator
  4. Risk monitoring dashboard
  5. Trade history and performance analysis
  6. Streamlit or Gradio web interface

Visualizing Option Prices

import matplotlib.pyplot as plt
import numpy as np

stock_prices = np.linspace(50, 150, 100)
prices = [black_scholes(S, 100, 0.5, 0.05, 0.2, 'call') for S in stock_prices]
plt.plot(stock_prices, prices)
plt.axvline(100, color='gray', linestyle='--', alpha=0.5)
plt.title('Call Option Price vs Stock Price')
plt.xlabel('Stock Price')
plt.ylabel('Option Price')
plt.grid(True, alpha=0.3)
plt.show()

Sensitivity Analysis

Impact of Volatility

vols = [0.1, 0.2, 0.3, 0.4, 0.5]
S, K, T, r = 100, 100, 0.5, 0.05
for sigma in vols:
    call = black_scholes(S, K, T, r, sigma, 'call')
    put = black_scholes(S, K, T, r, sigma, 'put')
    print(f'Vol {sigma:.0%}: Call ${call:.2f}, Put ${put:.2f}')

Time Decay

  • As expiration approaches, time value decreases
  • Theta accelerates in the final 30 days
  • ATM options have the highest time value

Practical Applications

Real-World Use Cases

  1. Portfolio Insurance: Buy OTM puts to protect against market crashes
  2. Income Generation: Sell covered calls on stocks you already own
  3. Volatility Trading: Trade options based on volatility expectations
  4. Earnings Play: Trade options around earnings announcements

Greeks in Practice

| Greek | Trader's Focus | |-------|---------------| | Delta | Directional risk, hedge ratio | | Gamma | Convexity, risk of large moves | | Theta | Time decay, option seller's friend | | Vega | Volatility risk, earnings plays | | Rho | Interest rate risk, long-dated options |

Common Issues & Solutions

| Problem | Cause | Solution | |---------|-------|----------| | Unexpected results | Wrong parameters | Check defaults and edge cases | | Slow execution | Inefficient algorithm | Use better data structures | | Out of memory | Too much data | Use batch processing | | Hard to debug | No logging | Add detailed logging |

Further Learning

  • Read official documentation
  • Browse open-source examples on GitHub
  • Join community discussions
  • Practice by modifying code and observing results

Trading System Architecture

A complete trading system has four layers.

Layer 1: Data Acquisition

import yfinance as yf
import pandas as pd
from datetime import datetime, timedelta

def fetch_options_chain(symbol: str, expiry: str = None):
    """Fetch options data for a given symbol."""
    ticker = yf.Ticker(symbol)
    
    # Get all available expiries
    expirations = ticker.options[:5]
    
    chains = {}
    for exp in expirations:
        opt = ticker.option_chain(exp)
        chains[exp] = {
            "calls": opt.calls,
            "puts": opt.puts
        }
    
    return chains

# Example: Fetch Apple options
chains = fetch_options_chain("AAPL")
for exp, chain in chains.items():
    print(f"Expiry: {exp}")
    print(f"  Calls: {len(chain['calls'])} strikes")
    print(f"  Puts: {len(chain['puts'])} strikes")

Layer 2: Signal Generation

def generate_momentum_signals(data: pd.DataFrame, symbol: str, chain: dict):
    """Generate trading signals based on technical indicators."""
    signals = []
    
    # Calculate 20-day moving average
    data['SMA_20'] = data['Close'].rolling(20).mean()
    data['SMA_50'] = data['Close'].rolling(50).mean()
    
    latest = data.iloc[-1]
    
    # Golden cross (bullish)
    if latest['SMA_20'] > latest['SMA_50']:
        # Find ATM call
        atm_strike = round(latest['Close'] / 5) * 5
        for _, option in chain['calls'].iterrows():
            if abs(option['strike'] - atm_strike) < 2.5:
                signals.append({
                    'type': 'BUY_CALL',
                    'symbol': symbol,
                    'strike': option['strike'],
                    'expiry': expiry,
                    'mid_price': (option['bid'] + option['ask']) / 2,
                    'reason': 'Golden cross, bullish momentum'
                })
                break
    
    return signals

Layer 3: Risk Management

class RiskManager:
    def __init__(self, max_daily_loss: float = 500, max_position_size: float = 2000):
        self.max_daily_loss = max_daily_loss
        self.max_position_size = max_position_size
        self.daily_pnl = 0
        self.positions = []
    
    def can_open_position(self, cost: float, delta: float) -> bool:
        """Check if a new position meets risk criteria."""
        checks = [
            (cost <= self.max_position_size, "Exceeds max position size"),
            (abs(delta) <= 20, "Delta too high"),
            (len(self.positions) < 5, "Max 5 concurrent positions"),
            (self.daily_pnl > -self.max_daily_loss, "Max daily loss exceeded")
        ]
        
        for passed, reason in checks:
            if not passed:
                print(f"Blocked: {reason}")
                return False
        return True
    
    def update_pnl(self, pnl: float):
        self.daily_pnl += pnl
        if self.daily_pnl < -self.max_daily_loss:
            print("โš ๏ธ STOP LOSS TRIGGERED! Close all positions.")
            self.close_all()

Layer 4: Execution

import time
from typing import Optional

class PaperExecutor:
    def __init__(self, initial_capital: float = 10000):
        self.capital = initial_capital
        self.positions = []
        self.trades = []
    
    def execute_signal(self, signal: dict):
        """Execute a trading signal (paper trading)."""
        cost = signal['mid_price'] * 100  # 1 contract = 100 shares
        
        if cost > self.capital:
            print(f"Insufficient capital: need ${cost:.2f}, have ${self.capital:.2f}")
            return None
        
        trade = {
            'timestamp': datetime.now(),
            'symbol': signal['symbol'],
            'type': signal['type'],
            'strike': signal['strike'],
            'entry_price': signal['mid_price'],
            'cost': cost,
            'status': 'open'
        }
        
        self.capital -= cost
        self.positions.append(trade)
        self.trades.append(trade)
        
        print(f"Executed: {trade['type']} {trade['symbol']} @ ${trade['entry_price']}")
        return trade

Backtesting Framework

def backtest_strategy(symbol: str, days: int = 60):
    """Run a simple backtest of the momentum strategy."""
    ticker = yf.Ticker(symbol)
    hist = ticker.history(period=f"{days}d")
    
    executor = PaperExecutor(initial_capital=10000)
    wins = 0
    losses = 0
    
    for i in range(20, len(hist)):
        data = hist.iloc[:i]
        signal = generate_signals(data)
        
        if signal and executor.capital > signal['cost']:
            trade = executor.execute_signal(signal)
            if trade:
                # Simulate closing after 5 days
                exit_price = hist.iloc[i]['Close'] if i < len(hist)-1 else signal['entry_price']
                pnl = (exit_price - signal['entry_price']) * 100
                if pnl > 0:
                    wins += 1
                else:
                    losses += 1
    
    print(f"Win Rate: {wins/(wins+losses)*100:.1f}%")
    print(f"Total PnL: ${executor.capital - 10000:.2f}")

Summary

A trading system needs four layers: data, signals, risk management, and execution. Backtest thoroughly before trading with real money.

Key takeaways:

  • Four layers: data acquisition โ†’ signal generation โ†’ risk โ†’ execution |
  • Paper trading validates strategies without financial risk |
  • Risk manager enforces max position size, max loss, and delta limits |
  • Backtesting measures win rate and total PnL over historical data |
  • yfinance provides free options chain and price data |
  • Always test on multiple symbols and time periods |
  • Track every trade for post-analysis and improvement |

What's Next: Risk Management

The next chapter covers advanced risk management techniques.

Unlock Full Tutorial

This chapter is paid content. Join the project to unlock over 5000 words of deep analysis, including 10+ god-tier Prompts and real Source Code examples!