# Difference Between Long and Short Butterfly Spread Payoff Calculations

> Understand the key difference in long and short butterfly spread payoff calculations. Explore how inverted positions create distinct profit profiles.

- Repository: [Joaquin Bejar Garcia/optionstratlib](https://github.com/joaquinbejar/optionstratlib)
- Tags: deep-dive
- Published: 2026-03-04

---

**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](https://github.com/joaquinbejar/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`](https://github.com/joaquinbejar/optionstratlib/blob/main/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:

```rust
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`](https://github.com/joaquinbejar/optionstratlib/blob/main/src/strategies/short_butterfly_spread.rs) inverts this structure:

```rust
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:

```rust
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):

```rust
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

```rust
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

```rust
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

```rust
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`](https://github.com/joaquinbejar/optionstratlib/blob/main/src/strategies/long_butterfly_spread.rs) and `ShortButterflySpread::update_break_even_points` in [`src/strategies/short_butterfly_spread.rs`](https://github.com/joaquinbejar/optionstratlib/blob/main/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.