Options Strategies With Python – Part 1

Covered Call

import numpy as np
import matplotlib.pyplot as plt

# Function to calculate the payoff of a covered call
def covered_call_payoff(s, strike_price, stock_purchase_price, call_premium):
    # Stock payoff without the call option
    stock_payoff = s - stock_purchase_price
    
    # Call option payoff
    call_payoff = np.minimum(strike_price - s + call_premium, call_premium)
    
    # Covered call payoff
    covered_call_payoff = stock_payoff + call_payoff
    return covered_call_payoff

# Function to calculate maximum loss, maximum profit, and break-even
def calculate_metrics(strike_price, stock_purchase_price, call_premium):
    max_loss = stock_purchase_price - call_premium
    max_profit = strike_price - stock_purchase_price + call_premium
    break_even = stock_purchase_price - call_premium
    return max_loss, max_profit, break_even

# Inputs
stock_price_range = np.arange(30, 70, 1)  # Range of stock prices
strike = 50  # Strike price of the call option
purchase_price = 45  # Purchase price of the underlying stock
premium = 2  # Premium received by selling the call option

# Calculate covered call payoffs for the given range of stock prices
payoff = covered_call_payoff(stock_price_range, strike, purchase_price, premium)

# Calculate metrics
max_loss, max_profit, break_even = calculate_metrics(strike, purchase_price, premium)

# Create the legend strings with formulas for max loss, max profit, and break-even
legend_str = (f'Max Loss: Stock Purchase Price - Call Premium = {max_loss}',
              f'Max Profit: Strike Price - Stock Purchase Price + Call Premium = {max_profit}',
              f'Break-even: Stock Purchase Price - Call Premium = {break_even}')

# Plotting the covered call payoff with annotations in legend on the side
plt.figure(figsize=(8, 6))
plt.plot(stock_price_range, payoff, label='Covered Call Payoff')
plt.xlabel('Stock Price')
plt.ylabel('Payoff')
plt.title('Covered Call Payoff')
plt.axvline(x=strike, linestyle='--', color='r', label='Strike Price')
plt.axhline(y=0, color='black', linestyle='--', alpha=0.5)
plt.legend(title='Metrics', labels=legend_str, loc='center left', bbox_to_anchor=(1, 0.5))
plt.grid(True)
plt.show()

Output


Protective Puts

import numpy as np
import matplotlib.pyplot as plt

# Function to calculate the payoff of a protective put
def protective_put_payoff(s, strike_price, stock_purchase_price, put_premium):
    stock_payoff = s - stock_purchase_price
    put_payoff = np.maximum(strike_price - s - put_premium, -put_premium)
    protective_put_payoff = stock_payoff + put_payoff
    return protective_put_payoff

# Function to calculate maximum loss, maximum profit, and break-even for Protective Put
def calculate_metrics_protective_put(strike_price, stock_purchase_price, put_premium):
    max_loss = stock_purchase_price - strike_price + put_premium
    max_profit = np.inf  # Unlimited upside potential
    break_even = stock_purchase_price + put_premium
    return max_loss, max_profit, break_even

# Inputs for Protective Put
stock_price_range = np.arange(30, 70, 1)
strike = 40
purchase_price = 45
premium = 2

# Calculate Protective Put payoffs for the given range of stock prices
payoff_protective_put = protective_put_payoff(stock_price_range, strike, purchase_price, premium)

# Calculate metrics for Protective Put
max_loss_protective_put, max_profit_protective_put, break_even_protective_put = calculate_metrics_protective_put(strike, purchase_price, premium)

# Create legend strings with formulas for max loss, max profit, and break-even for Protective Put
legend_str_protective_put = (f'Max Loss: Stock Purchase Price - Strike Price+ Put Premium = {max_loss_protective_put}',
                             'Max Profit: Unlimited',
                             f'Break-even: Stock Purchase Price + Put Premium = {break_even_protective_put}')

# Plotting the Protective Put payoff with annotations in legend on the side
plt.figure(figsize=(8, 6))
plt.plot(stock_price_range, payoff_protective_put, label='Protective Put Payoff')
plt.xlabel('Stock Price')
plt.ylabel('Payoff')
plt.title('Protective Put Payoff')
plt.axvline(x=strike, linestyle='--', color='r', label='Strike Price')
plt.axhline(y=0, color='black', linestyle='--', alpha=0.5)
plt.legend(title='Metrics', labels=legend_str_protective_put, loc='center left', bbox_to_anchor=(1, 0.5))
plt.grid(True)
plt.show()

Output


Long Straddle

import matplotlib.pyplot as plt

# Define underlying asset price, strike price, and premiums (adjust as needed)
underlying_price = 100
strike_price = 105
call_premium = 5
put_premium = 4

# Define underlying asset price range
underlying_price_range = range(strike_price - 10, strike_price + 11)

# Calculate profit/loss for each underlying price
profit_loss = []
for price in underlying_price_range:
    call_profit = max(0, price - strike_price) - call_premium
    put_profit = max(0, strike_price - price) - put_premium
    total_profit = call_profit + put_profit
    profit_loss.append(total_profit)

# Plot the payoff diagram
plt.plot(underlying_price_range, profit_loss)

# Customize plot
plt.xlabel("Underlying Price at Expiration")
plt.ylabel("Profit/Loss")
plt.title("Long Straddle Payoff Diagram")

# Adjusted breakeven lines
upper_breakeven = strike_price + call_premium + put_premium
lower_breakeven = strike_price - call_premium - put_premium
plt.axhline(0, color="black", linestyle="-", label="Net Profit/Loss")
plt.axvline(upper_breakeven, color="red", linestyle=":", label=f"Upper Breakeven: {upper_breakeven}")
plt.axvline(lower_breakeven, color="green", linestyle=":", label=f"Lower Breakeven: {lower_breakeven}")

plt.grid(True)
plt.legend()
plt.show()

Output


Short Straddle

import matplotlib.pyplot as plt

# Define underlying asset price, strike price, and premiums (adjust as needed)
underlying_price = 100
strike_price = 105
call_premium = 5
put_premium = 4

# Define underlying asset price range
underlying_price_range = range(strike_price - 10, strike_price + 14)

# Calculate profit/loss for each underlying price, accounting for initial premium
profit_loss = []
initial_profit = call_premium + put_premium  # Total premium received
for price in underlying_price_range:
    call_loss = max(0, strike_price - price) * call_premium
    put_loss = max(0, price - strike_price) * put_premium
    total_loss = -(call_loss + put_loss)  # Short straddle profit = -negative of loss
    net_profit = initial_profit + total_loss  # Adjust for initial premium
    profit_loss.append(net_profit)

# Plot the payoff diagram
plt.plot(underlying_price_range, profit_loss)

# Customize plot
plt.xlabel("Underlying Price at Expiration")
plt.ylabel("Profit/Loss")
plt.title("Short Straddle Payoff Diagram ")

# Adjusted breakeven lines
upper_breakeven = strike_price + call_premium + put_premium
lower_breakeven = strike_price - call_premium - put_premium
plt.axhline(0, color="black", linestyle="-", label="Net Profit/Loss")
plt.axhline(initial_profit, color="blue", linestyle="--", label="Initial Premium")
plt.axvline(upper_breakeven, color="red", linestyle=":", label=f"Upper Breakeven: {upper_breakeven}")
plt.axvline(lower_breakeven, color="green", linestyle=":", label=f"Lower Breakeven: {lower_breakeven}")

plt.grid(True)
plt.legend()
plt.show()

Output


Long Strangle

import numpy as np
import matplotlib.pyplot as plt

# Function to calculate the payoff of a long strangle
def long_strangle_payoff(s, strike_call, call_premium, strike_put, put_premium):
    call_payoff = np.maximum(s - strike_call - call_premium, 0)
    put_payoff = np.maximum(strike_put - s - put_premium, 0)
    total_payoff = call_payoff + put_payoff
    return total_payoff - (call_premium + put_premium)

# Function to calculate metrics for Long Strangle
def calculate_metrics_long_strangle(strike_call, call_premium, strike_put, put_premium):
    max_loss = call_premium + put_premium
    max_profit = np.inf  # Unlimited upside potential
    upper_breakeven = strike_call + call_premium + put_premium
    lower_breakeven = strike_put - put_premium - call_premium
    return max_loss, max_profit, upper_breakeven, lower_breakeven

# Define parameters (adjust as needed)
strike_call = 110
strike_put = 90
call_premium = 3
put_premium = 2

# Define underlying asset price range
price_range = np.arange(strike_put - 40, strike_call + 41, 1)

# Calculate Long Strangle payoffs for the given range of stock prices
payoff_long_strangle = [long_strangle_payoff(price, strike_call, call_premium, strike_put, put_premium) for price in price_range]

# Calculate metrics for Long Strangle
max_loss, max_profit, upper_breakeven, lower_breakeven = calculate_metrics_long_strangle(strike_call, call_premium, strike_put, put_premium)

# Plot the payoff diagram
plt.figure(figsize=(8, 6))
plt.plot(price_range, payoff_long_strangle, label='Long Strangle Payoff', color='blue')

# Adjusted breakeven lines
plt.axhline(y=0, color='black', linestyle='-', label='Net Profit/Loss')
plt.axvline(x=upper_breakeven, color='red', linestyle=':', label=f'Upper Breakeven: {upper_breakeven}')
plt.axvline(x=lower_breakeven, color='green', linestyle=':', label=f'Lower Breakeven: {lower_breakeven}')

# Customize plot
plt.xlabel("Underlying Price at Expiration")
plt.ylabel("Profit/Loss")
plt.title("Long Strangle Payoff Diagram")
plt.grid(True)

# Add legend with formulas
plt.legend(title='Metrics', labels=[
    f'Max Loss: Call Premium + Put Premium = {max_loss}',  
    'Max Profit: Unlimited',
    f'Upper Breakeven: {upper_breakeven} (Strike Call + Call Premium + Put Premium)',
    f'Lower Breakeven: {lower_breakeven} (Strike Put - Put Premium - Call Premium)'
], loc='center left',bbox_to_anchor=(1, 0.5))

plt.show()

Output


Short Strangle

import numpy as np
import matplotlib.pyplot as plt

# Function to calculate the payoff of a short strangle
def short_strangle_payoff(s, lower_strike, upper_strike, call_premium, put_premium):
    call_payoff = -np.maximum(s - upper_strike - call_premium, 0)
    put_payoff = -np.maximum(lower_strike - s - put_premium, 0)
    short_strangle_payoff = call_payoff + put_payoff
    return short_strangle_payoff +  (call_premium + put_premium)

# Function to calculate maximum loss, maximum profit, and break-even for Short Strangle
def calculate_metrics_short_strangle(lower_strike, upper_strike, call_premium, put_premium):
    max_loss = np.inf  # Unlimited
    max_profit = call_premium + put_premium
    break_even_down = lower_strike - (put_premium + call_premium)
    break_even_up = upper_strike + (put_premium + call_premium)
    return max_loss, max_profit, break_even_down, break_even_up

# Function to calculate break-even for Short Strangle
def calculate_break_even_short_strangle(lower_strike, upper_strike, call_premium, put_premium):
    break_even_down = lower_strike - (put_premium + call_premium)
    break_even_up = upper_strike + (put_premium + call_premium)
    return break_even_down, break_even_up

# Inputs for Short Strangle
stock_price_range = np.arange(30, 70, 1)
lower_strike = 45
upper_strike = 55
call_premium = 2
put_premium = 2

# Calculate Short Strangle payoffs for the given range of stock prices
payoff_short_strangle = short_strangle_payoff(stock_price_range, lower_strike, upper_strike, call_premium, put_premium)

# Calculate metrics and break-even for Short Strangle
max_loss_short_strangle, max_profit_short_strangle, break_even_down_short_strangle, break_even_up_short_strangle = calculate_metrics_short_strangle(lower_strike, upper_strike, call_premium, put_premium)
break_even_down_strangle, break_even_up_strangle = calculate_break_even_short_strangle(lower_strike, upper_strike, call_premium, put_premium)

# Create legend strings with formulas for max loss, max profit, and break-even for Short Strangle
legend_str_short_strangle = (f'Max Loss: Unlimited',
                             f'Max Profit: Call Premium + Put Premium = {max_profit_short_strangle}',
                             f'Break-even Down: {break_even_down_strangle} (Lower Strike - Net Premium)',
                             f'Break-even Up: {break_even_up_strangle} (Upper Strike + Net Premium)')

# Plotting the Short Strangle payoff with annotations in legend on the side
plt.figure(figsize=(8, 6))
plt.plot(stock_price_range, payoff_short_strangle, label='Short Strangle Payoff')
plt.xlabel('Stock Price')
plt.ylabel('Payoff')
plt.title('Short Strangle Payoff')
plt.axvline(x=lower_strike, linestyle='--', color='r', label='Lower Strike')
plt.axvline(x=upper_strike, linestyle='--', color='b', label='Upper Strike')
plt.axhline(y=0, color='black', linestyle='--', alpha=0.5)
plt.legend(title='Metrics', labels=legend_str_short_strangle, loc='center left', bbox_to_anchor=(1, 0.5))
plt.grid(True)
plt.show()

Output


Iron Condor

import numpy as np
import matplotlib.pyplot as plt

def call_payoff(sT, strike, premium):
    return np.maximum(sT - strike, 0) - premium

def put_payoff(sT, strike, premium):
    return np.maximum(strike - sT, 0) - premium

def iron_condor_payoff(sT, strike_long_call, premium_long_call, strike_short_call, premium_short_call,
                       strike_short_put, premium_short_put, strike_long_put, premium_long_put):
    payoff_long_call = call_payoff(sT, strike_long_call, premium_long_call)
    payoff_short_call = -1 * call_payoff(sT, strike_short_call, premium_short_call)
    payoff_short_put = -1 * put_payoff(sT, strike_short_put, premium_short_put)
    payoff_long_put = put_payoff(sT, strike_long_put, premium_long_put)
    
    return payoff_long_call + payoff_short_call + payoff_short_put + payoff_long_put

def calculate_metrics_iron_condor(strike_long_call, premium_long_call, strike_short_call, premium_short_call,
                                   strike_short_put, premium_short_put, strike_long_put, premium_long_put):
    max_loss = (strike_long_call - strike_short_call)  + (-premium_short_call - premium_short_put + premium_long_call + premium_long_put)
    max_profit = (-premium_long_call - premium_long_put + premium_short_call + premium_short_put)
    upper_breakeven = strike_short_call + premium_short_call
    lower_breakeven = strike_short_put - premium_short_put
    return max_loss, max_profit, upper_breakeven, lower_breakeven

# Define parameters (adjust as needed)
sT = np.linspace(50, 150, 101)
strike_long_call = 120
premium_long_call = 2
strike_short_call = 110
premium_short_call = 4
strike_short_put = 90
premium_short_put = 4
strike_long_put = 80
premium_long_put = 2

# Calculate Iron Condor payoffs and metrics
payoff_iron_condor = iron_condor_payoff(sT, strike_long_call, premium_long_call, 
                                        strike_short_call, premium_short_call,
                                        strike_short_put, premium_short_put,
                                        strike_long_put, premium_long_put)
max_loss, max_profit, upper_breakeven, lower_breakeven = calculate_metrics_iron_condor(strike_long_call, premium_long_call, 
                                                                                        strike_short_call, premium_short_call,
                                                                                        strike_short_put, premium_short_put,
                                                                                        strike_long_put, premium_long_put)

# Plot the payoff diagram
plt.plot(sT, payoff_iron_condor, label='Iron Condor')
plt.axhline(y=0, color='black', linestyle='-', label='Net Profit/Loss')
plt.axvline(x=upper_breakeven, color='red', linestyle=':', label=f'Upper Breakeven: {upper_breakeven}')
plt.axvline(x=lower_breakeven, color='green', linestyle=':', label=f'Lower Breakeven: {lower_breakeven}')

plt.xlabel('Stock Price at Expiration (sT)')
plt.ylabel('Profit and Loss')
plt.title('Iron Condor Payoff Diagram')
plt.legend(title='Metrics', labels=[
    f'Max Loss: {max_loss}',
    f'Max Profit: {max_profit}',
    f'Upper Breakeven: {upper_breakeven}',
    f'Lower Breakeven: {lower_breakeven}'
], loc='center left',bbox_to_anchor=(1, 0.5))
plt.grid(True)
plt.show()

Output


Long Call Butterfly Spread

import numpy as np
import matplotlib.pyplot as plt

# Set up parameters
underlying_prices = np.linspace(40, 60, 100)
upper_strike = 55
middle_strike = 50
lower_strike = 45
net_premium_paid = 1  # Adjust as needed

# Calculate payoff for each underlying price
payoffs = (np.maximum(underlying_prices - upper_strike, 0) - 
           2 * np.maximum(middle_strike - underlying_prices, 0) +
           np.maximum(lower_strike - underlying_prices, 0) - net_premium_paid)

# Identify the index where maximum loss occurs
max_loss_index = np.argmin(payoffs)

# Plot the key points without the payoff line
plt.figure(figsize=(8, 6))
plt.plot([lower_strike, lower_strike + net_premium_paid, middle_strike, upper_strike - net_premium_paid, upper_strike],
         [-net_premium_paid, 0, payoffs[np.argmax(payoffs)], 0, -net_premium_paid],
         marker='o', linestyle='-', color='blue', markersize=8)

# Annotate key points
plt.text(lower_strike + net_premium_paid, 0.5, 'Lower Breakeven', fontsize=8, ha='right')
plt.text(middle_strike, payoffs[np.argmax(payoffs)] + 0.5, 'Max Profit', fontsize=8, ha='center')
plt.text(upper_strike - net_premium_paid, 0.5, 'Upper Breakeven', fontsize=8, ha='left')
plt.text(lower_strike, -net_premium_paid - 0.5, 'Max Loss', fontsize=8, ha='right')

# Set axis labels and title
plt.title('Long Call Butterfly Spread Key Points')
plt.xlabel('Underlying Price')
plt.ylabel('Payoff')
plt.axhline(0, color='black', linestyle='--', linewidth=1, label='Zero Payoff Line')

# Extend the line after the maximum loss point
plt.plot(underlying_prices[max_loss_index:], np.full_like(underlying_prices[max_loss_index:], -net_premium_paid), linestyle='--', color='gray')

plt.ylim(-5, 5)  # Set y-axis range from -5 to 5
plt.grid(True)
plt.show()

Output