What Is Kirk's Approximation in Spread Option Pricing?

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 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 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.

// 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:

// 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 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:

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 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 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.
  • 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. 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.

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 →