# What Is Kirk's Approximation in Spread Option Pricing?

> Discover Kirk's approximation for spread option pricing. Learn how this analytical method prices options with non-zero strikes using adjusted strikes and effective volatility.

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

---

**Kirk's approximation is a closed-form analytical method that prices spread options with non-zero strikes by treating the position as a call option on the first underlying asset with an adjusted strike price and effective volatility derived from both assets' volatilities and their correlation.**

Spread options derive their value from the difference between two underlying asset prices, requiring specialized pricing models when the strike price differs from zero. In the **optionstratlib** repository, Kirk's approximation provides a computationally efficient alternative to numerical integration for pricing these instruments. This article examines the implementation in [`src/pricing/spread.rs`](https://github.com/joaquinbejar/optionstratlib/blob/main/src/pricing/spread.rs) and explains how the method handles spread options where the strike \(K \neq 0\).

## Kirk's Approximation vs. Margrabe's Formula: Selecting the Correct Model

The `spread_black_scholes` function in [`src/pricing/spread.rs`](https://github.com/joaquinbejar/optionstratlib/blob/main/src/pricing/spread.rs) acts as a dispatcher that selects between two analytical methods based on the strike price. When the strike is essentially zero (`k.abs() < 0.0001`), the implementation falls back to **Margrabe's formula**, which provides the exact solution for exchange options (where \(K = 0\)). For all other cases involving a non-zero strike, the function invokes `kirk_approximation`.

```rust
// src/pricing/spread.rs#L86-L101
let price = if k.abs() < dec!(0.0001) {
    margrabe_formula(...)
} else {
    kirk_approximation(...)
}?;

```

This branching logic ensures that traders use the mathematically appropriate model: Margrabe's formula for pure exchange options and Kirk's approximation for spread options with positive or negative strikes.

## Mathematical Foundation of Kirk's Approximation

Kirk's method treats the spread option as a plain vanilla call on the first asset \(S_1\) with modified parameters that account for the second asset \(S_2\) and the strike \(K\). The implementation follows three critical steps:

### Adjusted Strike Calculation

The algorithm computes an **adjusted strike** equal to the price of the second asset plus the original strike \((S_2 + K)\). This adjusted strike must remain positive for the formula to remain valid. The first asset price \(S_1\) is then evaluated against this composite strike level.

### Effective Volatility and Correlation

The **effective volatility** \(\sigma\) combines the volatilities of both underlying assets (\(\sigma_1\) and \(\sigma_2\)) with their correlation coefficient \(\rho\). The calculation uses the ratio \(s2\_ratio = S_2 / (S_2 + K)\) to weight the contribution of the second asset's volatility:

```rust
// src/pricing/spread.rs#L62-L66
let sigma_sq = sigma1 * sigma1
    + s2_ratio * s2_ratio * sigma2 * sigma2
    - dec!(2.0) * rho * sigma1 * sigma2 * s2_ratio;
let sigma = sigma_sq.sqrt()?;

```

This combined volatility captures the risk characteristics of both assets while accounting for their co-movement through the correlation term.

### Black-Scholes Integration

With the adjusted strike and effective volatility established, the function computes standard Black-Scholes \(d_1\) and \(d_2\) parameters. The final price equals the discounted expectation of the call payoff using these modified inputs, preserving the risk-neutral pricing framework while adapting it for the two-asset structure.

## Implementation Details in src/pricing/spread.rs

The `kirk_approximation` function in [`src/pricing/spread.rs`](https://github.com/joaquinbejar/optionstratlib/blob/main/src/pricing/spread.rs) handles several edge cases to ensure numerical stability. When time-to-maturity \(t \leq 0\), the function computes the payoff directly to avoid division errors in the volatility terms. The implementation validates that the adjusted strike remains positive before proceeding with the square root calculation for the effective volatility.

The function signature accepts the first asset price \(s1\), second asset price \(s2\), strike \(k\), respective volatilities \(sigma1\) and \(sigma2\), correlation \(rho\), time to maturity \(t\), and risk-free rate \(rate\). These parameters map directly to the mathematical variables in Kirk's original derivation.

## Code Example: Pricing a Spread Option in Rust

The following example demonstrates how to configure a spread option with a non-zero strike and price it using the library's implementation of Kirk's approximation:

```rust
use optionstratlib::{
    Options, OptionStyle, OptionType, Side, ExpirationDate, Positive,
};
use rust_decimal_macros::dec;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Define a spread option: long call on S1, short S2, strike = 5
    let opt = Options::new(
        OptionType::Spread { second_asset: 100.0 }, // S2 price
        Side::Long,
        "AAPL".to_string(),
        Positive::new(5.0)?,          // non-zero strike K
        ExpirationDate::Days(Positive::new(90.0)?),
        Positive::new(0.20)?,        // implied vol of S1 (sigma1)
        Positive::ONE,                // notional
        Positive::new(105.0)?,        // S1 price
        dec!(0.05),                   // risk-free rate
        OptionStyle::Call,
        Positive::ZERO,               // dividend of S1
        Some(ExoticParams {
            spread_second_asset_volatility: Some(Positive::new(0.25)?),
            spread_correlation: Some(dec!(0.5)),
            ..Default::default()
        }),
    );

    // Price invokes kirk_approximation because K ≠ 0
    let price = optionstratlib::pricing::spread::spread_black_scholes(&opt)?;
    println!("Spread option price = {}", price);
    Ok(())
}

```

Because the strike is non-zero, `spread_black_scholes` automatically routes the calculation to `kirk_approximation`, delivering an analytical price without numerical integration.

## Accuracy and Performance Characteristics

Kirk's approximation executes in constant time \(O(1)\) because it relies solely on arithmetic operations and standard mathematical functions. This performance advantage makes it suitable for high-throughput scenarios such as Monte Carlo simulations or real-time risk calculations where numerical methods like finite difference or binomial trees would introduce unacceptable latency.

The approximation remains highly accurate for practical trading scenarios where the strike is moderate and the correlation between assets is not extreme. The test suite in [`src/pricing/spread.rs`](https://github.com/joaquinbejar/optionstratlib/blob/main/src/pricing/spread.rs) includes `test_kirk_approximation_nonzero_strike` to validate that the function returns positive prices for valid non-zero strikes, while additional property-based tests in [`tests/property/put_call_parity_test.rs`](https://github.com/joaquinbejar/optionstratlib/blob/main/tests/property/put_call_parity_test.rs) verify that the pricing methodology respects put-call parity relationships.

## Summary

- **Kirk's approximation** provides a closed-form solution for pricing spread options with non-zero strikes in [`src/pricing/spread.rs`](https://github.com/joaquinbejar/optionstratlib/blob/main/src/pricing/spread.rs).
- The method treats the spread as a call on \(S_1\) with an **adjusted strike** of \((S_2 + K)\) and **effective volatility** derived from both assets' volatilities and their correlation.
- The implementation automatically falls back to **Margrabe's formula** when the strike approaches zero.
- The algorithm handles edge cases including expired options and validates input parameters to ensure numerical stability.
- This approach offers significant performance advantages over numerical integration while maintaining accuracy for typical market conditions.

## Frequently Asked Questions

### What is the difference between Kirk's approximation and Margrabe's formula?

**Margrabe's formula** provides the exact analytical solution for exchange options where the strike \(K = 0\), pricing the right to exchange one asset for another. **Kirk's approximation** extends this framework to handle non-zero strikes by adjusting the effective strike price and volatility, making it suitable for commodity spreads, crack spreads, and other derivatives where the payoff depends on the price differential minus a fixed strike.

### When is Kirk's approximation most accurate?

Kirk's approximation delivers the most accurate results when the strike price is moderate relative to the underlying asset prices and when the correlation between the two assets is not close to extreme values (perfect positive or negative correlation). The method assumes log-normal distributions for both assets and works best when the time to maturity is not excessively long, as the volatility term structure remains stable over shorter horizons.

### How does correlation affect the pricing in Kirk's approximation?

The correlation coefficient \(\rho\) directly influences the **effective volatility** calculation in [`src/pricing/spread.rs`](https://github.com/joaquinbejar/optionstratlib/blob/main/src/pricing/spread.rs). Higher positive correlation reduces the effective volatility because the assets tend to move together, decreasing the spread's variability. Conversely, negative correlation increases the effective volatility, raising the option price due to the greater dispersion between the two assets. The formula explicitly subtracts \(2 \rho \sigma_1 \sigma_2\) from the variance calculation, making the price sensitive to this parameter.

### Can Kirk's approximation handle put spread options?

Yes, the implementation supports put spread options through the standard Black-Scholes put-call parity transformation. When `OptionStyle::Put` is specified in the `Options` struct, the pricing engine adjusts the final calculation to reflect the put payoff structure while maintaining the same adjusted strike and effective volatility methodology. The put-call parity tests in the repository validate that the spread pricing remains consistent across both option styles.