Difference Between Long and Short Butterfly Spread Payoff Calculations

The fundamental difference between long and short butterfly spread payoff calculations is the complete inversion of buy/sell positions for each leg, flipping the sign of each leg's P&L contribution and transforming the profit profile from a "tent" shape (long) to a "valley" shape (short).

Understanding the mathematical distinction between long and short butterfly spread payoff calculations is essential for options traders implementing these limited-risk, three-leg strategies. According to the optionstratlib source code, the difference manifests in the sign reversal of each leg's contribution to the total profit at expiration, directly impacting break-even calculations and risk profiles.

Leg Composition and Position Signs

Both strategies use two wing options (low and high strike) and a body option at the middle strike, but with opposite buy/sell directions. The Long Butterfly Spread consists of:

  • A long call at the low strike
  • Short two calls at the middle strike
  • A long call at the high strike

Conversely, the Short Butterfly Spread reverses every position:

  • A short call at the low strike
  • Long two calls at the middle strike
  • A short call at the high strike

This reversal changes the profit formula from:

  • Long: Profit = (+)PNL_low + (-)2·PNL_mid + (+)PNL_high
  • Short: Profit = (-)PNL_low + (+)2·PNL_mid + (-)PNL_high

Profit Calculation Implementation

In src/strategies/long_butterfly_spread.rs, the calculate_profit_at method implements the long payoff by summing the P&L of each position, where the short middle leg naturally contributes negatively:

impl Profit for LongButterflySpread {
    fn calculate_profit_at(&self, price: &Positive) -> Result<Decimal, PricingError> {
        let price = Some(price);
        Ok(self.long_call_low.pnl_at_expiration(&price)?
            + self.short_call.pnl_at_expiration(&price)?
            + self.long_call_high.pnl_at_expiration(&price)?)
    }
}

The short butterfly implementation in src/strategies/short_butterfly_spread.rs inverts this structure:

impl Profit for ShortButterflySpread {
    fn calculate_profit_at(&self, price: &Positive) -> Result<Decimal, PricingError> {
        let price = Some(price);
        Ok(self.short_call_low.pnl_at_expiration(&price)?
            + self.long_call.pnl_at_expiration(&price)?
            + self.short_call_high.pnl_at_expiration(&price)?)
    }
}

Note that pnl_at_expiration returns negative values for short positions and positive values for long positions, effectively flipping the sign of each leg's contribution between the two strategies.

Break-Even Point Logic

The break-even calculations differ in their sign comparisons within update_break_even_points. For Long Butterfly Spread, the code searches for negative net values (losses that must be offset) at the wings:

if left_net_value <= Decimal::ZERO {
    self.break_even_points
        .push((self.long_call_low.option.strike_price - left_net_value).round_to(2));
}
if right_net_value <= Decimal::ZERO {
    self.break_even_points
        .push((self.long_call_high.option.strike_price + right_net_value).round_to(2));
}

For Short Butterfly Spread, the logic checks for positive net values (gains that must be offset):

if left_net_value >= Decimal::ZERO {
    self.break_even_points
        .push((self.short_call_low.option.strike_price + left_net_value).round_to(2));
}
if right_net_value >= Decimal::ZERO {
    self.break_even_points
        .push((self.short_call_high.option.strike_price - right_net_value).round_to(2));
}

Profit and Loss Profiles

The payoff shapes are inverted mirrors:

Long Butterfly:

  • Maximum profit: Achieved when the underlying expires near the middle strike, creating a "tent" shaped payoff curve.
  • Maximum loss: Limited to the net premium paid (the total cost of the three positions).

Short Butterfly:

  • Maximum profit: Achieved when the underlying expires far from the middle strike (at either wing), creating a "valley" shaped payoff curve.
  • Maximum loss: Limited to the net premium received (the total credit collected).

Practical Code Examples

Creating a Long Butterfly Spread

use optionstratlib::strategies::long_butterfly_spread::LongButterflySpread;
use positive::Positive;
use rust_decimal_macros::dec;
use optionstratlib::model::ExpirationDate;

let butterfly = LongButterflySpread::new(
    "XYZ".to_string(),
    Positive::HUNDRED,                     // underlying price
    pos_or_panic!(90.0),                   // low strike (long)
    Positive::HUNDRED,                     // middle strike (short x2)
    pos_or_panic!(110.0),                  // high strike (long)
    ExpirationDate::Days(pos_or_panic!(30.0)),
    pos_or_panic!(0.2),                    // implied vol
    dec!(0.05),                            // risk-free rate
    Positive::ZERO,                        // dividend yield
    Positive::ONE,                         // qty per wing
    pos_or_panic!(3.0),                    // premium low
    Positive::TWO,                         // premium middle (per contract)
    pos_or_panic!(1.0),                    // premium high
    /* fees … */ Positive::ONE, Positive::ONE,
    Positive::ONE, Positive::ONE,
    Positive::ONE, Positive::ONE,
);

// Profit at underlying = 100 (the body strike)
let profit = butterfly.calculate_profit_at(&Positive::HUNDRED).unwrap();
println!("Profit at 100 = {}", profit); // Positive value near max profit

Creating a Short Butterfly Spread

use optionstratlib::strategies::short_butterfly_spread::ShortButterflySpread;
use positive::Positive;
use rust_decimal_macros::dec;
use optionstratlib::model::ExpirationDate;

let butterfly = ShortButterflySpread::new(
    "XYZ".to_string(),
    Positive::HUNDRED,
    pos_or_panic!(90.0),        // low strike (short)
    Positive::HUNDRED,          // middle strike (long x2)
    pos_or_panic!(110.0),       // high strike (short)
    ExpirationDate::Days(pos_or_panic!(30.0)),
    pos_or_panic!(0.2),
    dec!(0.05),
    Positive::ZERO,
    Positive::ONE,
    pos_or_panic!(10.0),        // premium low (collected)
    Positive::ONE,              // premium middle (paid per contract)
    pos_or_panic!(0.5),         // premium high (collected)
    /* fees … */ Positive::ONE, Positive::ONE,
    Positive::ONE, Positive::ONE,
    Positive::ONE, Positive::ONE,
);

// Profit at underlying = 130 (far from body)
let profit = butterfly.calculate_profit_at(&pos_or_panic!(130.0)).unwrap();
println!("Profit at 130 = {}", profit); // Positive value, max profit at wings

Comparing Break-Even Points

let long_be = butterfly_long.get_break_even_points().unwrap();
let short_be = butterfly_short.get_break_even_points().unwrap();

println!("Long butterfly BE:  {:?} - {:?}", long_be[0], long_be[1]);
println!("Short butterfly BE: {:?} - {:?}", short_be[0], short_be[1]);

Implementation references: LongButterflySpread::update_break_even_points in src/strategies/long_butterfly_spread.rs and ShortButterflySpread::update_break_even_points in src/strategies/short_butterfly_spread.rs.

Summary

  • Long and short butterfly spread payoff calculations differ primarily in the sign reversal of each leg's P&L contribution, with long strategies buying the wings and shorting the body while short strategies do the inverse.
  • The profit formula for long butterflies adds the low and high strike P&L while subtracting twice the middle strike P&L, whereas short butterflies subtract the wings and add twice the body.
  • Break-even logic inverts the search condition: long butterflies look for negative net values (losses to offset), while short butterflies look for positive net values (gains to offset).
  • Risk profiles are opposites: long butterflies profit when the underlying stays near the middle strike (limited loss equals premium paid), while short butterflies profit when the underlying moves toward either wing (limited loss equals premium received).

Frequently Asked Questions

How does the payoff shape differ between long and short butterfly spreads?

The long butterfly spread produces a tent-shaped payoff curve with maximum profit at the middle strike and decreasing profits toward the wings. The short butterfly spread creates a valley-shaped curve with maximum profit achieved when the underlying price expires at or beyond either wing strike, and maximum loss occurring if the price settles exactly at the middle strike.

What determines the break-even points in butterfly spread calculations?

Break-even points are determined by the wing strikes and the net premium values. For long butterflies, the code adds the negative net value magnitude to the low strike and subtracts it from the high strike within update_break_even_points. For short butterflies, the positive net values are added to the low strike and subtracted from the high strike, reflecting the inverted profit structure.

Can butterfly spreads be constructed with puts instead of calls?

Yes, both long and short butterfly spreads can be constructed using put options instead of calls. The payoff calculation logic remains identical in the optionstratlib implementation—the Profit trait and calculate_profit_at method handle the P&L aggregation the same way, with the only difference being the intrinsic value calculation within pnl_at_expiration for puts versus calls.

What is the maximum risk for each butterfly spread type?

For long butterfly spreads, the maximum risk is limited to the net premium paid to establish the position (debit spread). For short butterfly spreads, the maximum risk is limited to the net premium received (the total credit collected), representing the obligation to fulfill the short positions if the underlying price moves against the strategy.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →