Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 15

Aggregating Greeks for Multi-Leg Credit Spreads

Recommended resources

Hello! Welcome back to our course on building a trading system.

In our previous lesson, we built a crucial component: the OptionsAnalytics utility class, which can calculate the price and Greeks for any single option contract using the py_vollib library. We also made sure to understand the practical conventions the library uses for values like Theta and Vega.

Today, we'll build directly on that foundation to achieve this lesson's learning outcome: Create a function to calculate the aggregated Greeks for a multi-leg credit spread position.

This step is vital. While knowing the risk of each leg is useful, your trading strategies are based on the risk profile of the entire spread. This aggregated view is what you'll use to make decisions about entry, adjustments, and exits. By the end of this lesson, you will have a function that provides the consolidated Delta, Gamma, Theta, and Vega for your credit spread positions.

The Core Principle: Additivity of Greeks

The risk profile of a multi-leg option position, such as a credit spread, is determined by the combined characteristics of its individual legs. The fundamental principle is that the Greeks of a portfolio are the sum of the Greeks of its individual components.

For any given Greek (e.g., Delta), the calculation is:

Where:

  • direction is +1 for a long position and -1 for a short position.
  • quantity is the number of contracts for that leg.
  • Greek_leg is the Greek value for a single option contract, which we already know how to calculate.

Let's read a short excerpt that confirms this principle, even though it uses an Iron Condor as an example. The logic is identical for any multi-leg strategy.

Options: Iron Condor Strategy

This article from QuantBeckman, 'Options: Iron Condor Strategy', provides a clear and concise explanation of how Greeks are aggregated for a multi-leg position.

Read the section titled 'The Greeks'. Focus on the paragraph that begins 'The aggregate Greeks of the four legs...' and the formula provided. This confirms that the position's total Greek is simply the sum of the individual option Greeks, adjusted for being long or short.

This principle of additivity is the foundation for the function we are about to build.


Visualizing the Goal

When we calculate the aggregated Greeks, we are computing a snapshot of the spread's risk profile at a specific underlying price. These aggregated values change as the underlying price moves. The following images for a Bull Put Spread illustrate what we are aiming to quantify.

Put Bull Spread Delta vs Payoff
This graph shows the aggregated Delta (red line) for a put bull spread. Notice that the net delta is positive, meaning the position profits as the underlying price rises. Our function will calculate a single point on this curve for a given underlying price.
Put Bull Spread Gamma vs Payoff (3 Days to Expiration)
This graph shows the aggregated Gamma (red line). For a bull put spread, the gamma is negative between the strikes, which is a key risk factor to monitor. Our function will also compute this value.

Designing the Aggregation Function

To create a flexible function, we first need a way to represent a multi-leg position. For now, a simple list of dictionaries will suffice. Each dictionary will represent one leg of the spread and contain all the information needed for its calculation.

A leg can be defined as:

leg = {
    'direction': 'short',  # 'long' or 'short'
    'quantity': 1,
    'flag': 'p',           # 'c' or 'p'
    'K': 440,              # Strike price
    'sigma': 0.22          # Implied volatility for this leg
}

Our aggregation function will take a list of these leg dictionaries, along with the market parameters that are common to all legs (underlying price, time to expiration, and risk-free rate).

The logic will be:

  1. Initialize a dictionary to hold the total aggregated Greeks (delta, gamma, etc.), starting at zero.
  2. Loop through each leg in the input list.
  3. For each leg, call our existing OptionsAnalytics.calculate_greeks method.
  4. Determine the sign based on the leg's direction (+1 for long, -1 for short).
  5. Multiply the calculated Greeks by the sign and the quantity, and add them to the running totals.
  6. Return the final dictionary of aggregated Greeks.

Implementation in Python

Let's add this new function to our framework/analytics.py file. It will be another static method within the OptionsAnalytics class.

# In framework/analytics.py

from py_vollib.black_scholes import black_scholes
from py_vollib.black_scholes.greeks.analytical import delta, gamma, vega, theta
from typing import List, Dict, Any

class OptionsAnalytics:
    """
    A utility class to encapsulate options pricing and Greek calculations
    using the py_vollib library.
    """
    
    @staticmethod
    def calculate_greeks(flag: str, S: float, K: float, t: float, r: float, sigma: float) -> dict:
        """Calculates the price and primary Greeks for a single option."""
        # ... (code from previous lesson) ...
        if t <= 0 or sigma <= 0:
            return {'price': 0.0, 'delta': 0.0, 'gamma': 0.0, 'vega': 0.0, 'theta': 0.0}
        try:
            price = black_scholes(flag, S, K, t, r, sigma)
            option_delta = delta(flag, S, K, t, r, sigma)
            option_gamma = gamma(flag, S, K, t, r, sigma)
            option_vega = vega(flag, S, K, t, r, sigma)
            option_theta = theta(flag, S, K, t, r, sigma)
        except Exception:
            return {'price': 0.0, 'delta': 0.0, 'gamma': 0.0, 'vega': 0.0, 'theta': 0.0}

        return {
            'price': price, 'delta': option_delta, 'gamma': option_gamma,
            'vega': option_vega, 'theta': option_theta
        }

    @staticmethod
    def calculate_aggregated_greeks(position_legs: List[Dict[str, Any]], S: float, t: float, r: float) -> dict:
        """
        Calculates the aggregated price and Greeks for a multi-leg position.

        Args:
            position_legs (List[Dict]): A list of leg dictionaries. Each dict must contain:
                                       'direction' ('long' or 'short'), 'quantity' (int),
                                       'flag' ('c' or 'p'), 'K' (float), 'sigma' (float).
            S (float): Current underlying asset price.
            t (float): Time to expiration in years (common for all legs).
            r (float): Risk-free interest rate.

        Returns:
            dict: A dictionary containing the aggregated price and Greeks for the position.
        """
        aggregated_greeks = {
            'price': 0.0, 'delta': 0.0, 'gamma': 0.0, 'vega': 0.0, 'theta': 0.0
        }

        for leg in position_legs:
            leg_greeks = OptionsAnalytics.calculate_greeks(
                flag=leg['flag'],
                S=S,
                K=leg['K'],
                t=t,
                r=r,
                sigma=leg['sigma']
            )

            direction_multiplier = 1 if leg['direction'] == 'long' else -1
            quantity = leg['quantity']
            
            for key in aggregated_greeks:
                aggregated_greeks[key] += leg_greeks[key] * direction_multiplier * quantity
        
        return aggregated_greeks

Example: Calculating for a Bull Put Spread

Now, let's use our new function to calculate the risk profile of a typical Bull Put Spread.

A Bull Put Spread consists of:

  • Selling a put option at a higher strike price (K_high).
  • Buying a put option at a lower strike price (K_low).

Let's define a position and calculate its Greeks:

# --- Example Usage for a Bull Put Spread ---

# Market conditions
underlying_price = 100.0
time_to_expiration = 45 / 365.0
risk_free_rate = 0.05

# Bull Put Spread position
# Short a 95 Put, Long a 90 Put
bull_put_spread_position = [
    {
        'direction': 'short', 'quantity': 1, 'flag': 'p',
        'K': 95, 'sigma': 0.28
    },
    {
        'direction': 'long', 'quantity': 1, 'flag': 'p',
        'K': 90, 'sigma': 0.26
    }
]

# Calculate aggregated greeks
spread_greeks = OptionsAnalytics.calculate_aggregated_greeks(
    position_legs=bull_put_spread_position,
    S=underlying_price,
    t=time_to_expiration,
    r=risk_free_rate
)

print("\n--- Aggregated Greeks for Bull Put Spread ---")
for key, value in spread_greeks.items():
    print(f"Net {key.capitalize()}: {value:.4f}")

# Expected Output (approximate):
# Net Price: 1.5791  (This is the net credit received)
# Net Delta: 0.0934
# Net Gamma: -0.0033
# Net Vega: -0.5284
# Net Theta: 0.0249

Interpreting the Results:

  • Net Price: The positive value represents a net credit received for opening the position.
  • Net Delta: The small positive delta (0.0934) confirms the position is bullish. For every $1 increase in the underlying, the spread's value should increase by about $0.09. This matches the intuition from the "Put Bull Spread Delta vs Payoff" graph.
  • Net Gamma: The negative gamma shows we are short convexity. If the price moves against us (down), our delta will become more positive, accelerating our P&L changes.
  • Net Theta: The positive theta is our profit engine. Every day that passes, the position is expected to gain about $0.025 from time decay, all else being equal.
  • Net Vega: The negative vega means the position benefits from a decrease in implied volatility.
Test your understanding!

You want to calculate the aggregated Greeks for a Bear Call Spread. You are short a call with a $250 strike and long a call with a $255 strike.

How would you define the position_legs list to pass to our calculate_aggregated_greeks function? Assume the quantity is 1 for both legs and the implied volatility (sigma) is 0.20 for both.

Show answer

The position_legs list would be structured as follows:

bear_call_spread_position = [
    {
        'direction': 'short', 
        'quantity': 1, 
        'flag': 'c',  # 'c' for call
        'K': 250, 
        'sigma': 0.20
    },
    {
        'direction': 'long', 
        'quantity': 1, 
        'flag': 'c', 
        'K': 255, 
        'sigma': 0.20
    }
]

When you run this through the function, you should expect to see a negative Net Delta, reflecting the bearish nature of the spread.


Conclusion

You have now successfully created a powerful and flexible function to analyze the risk of your target credit spread strategies. This is a significant step in building the "brains" of your trading system.

Key Takeaways:

  • Greeks are Additive: The risk profile of a multi-leg spread is the sum of the signed Greek values of its individual legs.
  • Direction Matters: We use a multiplier (+1 for long, -1 for short) to correctly aggregate the contributions of each leg.
  • Data Structure is Key: Defining a clear input structure (our list of leg dictionaries) allows for a generic function that can handle any spread combination.
  • Integrated Analytics: By adding calculate_aggregated_greeks to our OptionsAnalytics class, we now have a centralized and reusable utility for all our Greek calculations, for both single legs and entire spreads.

Preview of the Next Lesson:
Our analytics functions currently rely on a crucial input: sigma, the implied volatility. But where does this value come from? We can't just hard-code it. In a live system, we must derive sigma from the option's real-time market price.

In the next lesson, we will address this by learning how to "Implement a function to calculate implied volatility for a given option contract from its market price." This will complete our core analytics toolkit, enabling us to calculate real-time Greeks based on live market data.