Margrabe's Formula for Exchange Option Pricing: Implementation in OptionStratLib

Margrabe's formula calculates the closed-form price of an exchange option, giving the holder the right to swap one asset for another at maturity without a strike price.

Margrabe's formula for exchange option pricing provides an analytical solution for valuing options to exchange one risky asset for another. The Rust library OptionStratLib implements this model in src/pricing/exchange.rs, offering precise calculations for correlation-dependent derivatives.

Understanding Margrabe's Formula for Exchange Options

An exchange option (or Margrabe option) grants the right to exchange asset (S_2) for asset (S_1) at maturity (T). Unlike standard options, there is no strike price—the payoff is (\max(S_1 - S_2, 0)).

The formula requires five key inputs:

  • Spot prices: (S_1) and (S_2) for the two assets
  • Volatilities: (\sigma_1) and (\sigma_2) for each asset
  • Correlation coefficient: (\rho) between the two assets
  • Dividend yields: (q_1) and (q_2) for continuous dividends
  • Time to maturity: (T) in years

Implementation in the OptionStratLib Codebase

Core Pricing Logic in src/pricing/exchange.rs

The public entry point is exchange_black_scholes (lines 34-50), which validates the option type and delegates to the internal margrabe_formula function. The implementation handles both long and short positions through the apply_side helper.

// From src/pricing/exchange.rs
pub fn exchange_black_scholes(option: &Options) -> Result<Decimal, PricingError> {
    // Validation: ensures OptionType::Exchange
    // Extracts exotic parameters: σ₂, q₂, and ρ
    // Calls margrabe_formula with computed parameters
}

Combined Volatility Calculation

The model first computes the combined volatility (\sigma) accounting for correlation between assets (lines 31-34):

[ \sigma = \sqrt{\sigma_1^2 + \sigma_2^2 - 2\rho\sigma_1\sigma_2} ]

This represents the volatility of the spread (S_1/S_2), which is the effective underlying for the exchange option.

Drift and d1/d2 Parameters

The implementation calculates the time-scaled drift (\tilde q = q_2 - q_1) (line 45), representing the net cost of carry for holding the spread position.

The d1 and d2 parameters follow the Black-Scholes structure but applied to the ratio (S_1/S_2) (lines 45-46):

[ d_1 = \frac{\ln(S_1/S_2) + (\tilde q + \frac{\sigma^2}{2})T}{\sigma\sqrt{T}} ]

[ d_2 = d_1 - \sigma\sqrt{T} ]

Final Price Computation

The option price combines present values of both assets with their respective risk-neutral probabilities (line 51):

[ C = S_1 e^{-q_1T} N(d_1) - S_2 e^{-q_2T} N(d_2) ]

Where (N(\cdot)) is the standard normal cumulative distribution function. For short positions, the apply_side function (lines 56-60) negates the price.

Practical Code Examples

Pricing an Exchange Option with Margrabe's Formula

This example demonstrates creating an exchange option and calculating its price using the implementation in src/pricing/exchange.rs:

use optionstratlib::{Options, OptionType, Side, ExpirationDate, OptionStyle};
use optionstratlib::pricing::exchange::exchange_black_scholes;
use positive::{pos_or_panic, Positive};
use rust_decimal_macros::dec;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create exchange option: right to exchange S2 (price 100) for S1 (price 150)
    let option = Options::new(
        OptionType::Exchange { second_asset: 100.0 },
        Side::Long,
        "ASSET1".to_string(),
        Positive::HUNDRED,                 // placeholder strike (unused)
        ExpirationDate::Days(pos_or_panic!(90.0)),
        pos_or_panic!(0.25),               // σ₁: volatility of S1
        Positive::ONE,                     // quantity
        pos_or_panic!(150.0),              // S₁: price of asset 1
        dec!(0.05),                         // risk-free rate
        OptionStyle::Call,                  // style irrelevant for exchange
        pos_or_panic!(0.02),                // q₁: dividend yield of S1
        Some(optionstratlib::model::ExoticParams {
            exchange_second_asset_volatility: Some(pos_or_panic!(0.20)), // σ₂
            exchange_second_asset_dividend: Some(pos_or_panic!(0.01)),   // q₂
            exchange_correlation: Some(dec!(0.5)),                     // ρ
            ..Default::default()
        }),
    );

    let price = exchange_black_scholes(&option)?;
    println!("Exchange option price = ${:.4}", price);
    Ok(())
}

Using the High-Level API

For existing Options instances, the library provides a generic pricing method that automatically dispatches to Margrabe's formula:

let price = option.calculate_price_black_scholes()?; // Automatically uses exchange_black_scholes for Exchange type

Verifying Correlation Effects

The test suite in src/pricing/exchange.rs (lines 63-79) demonstrates how correlation impacts pricing:

// Low correlation increases option value (diversification benefit)
let mut low_corr = option.clone();
low_corr.exotic_params.as_mut().unwrap().exchange_correlation = Some(dec!(0.0));
let low_price = exchange_black_scholes(&low_corr)?;

// High correlation decreases option value
let mut high_corr = option;
high_corr.exotic_params.as_mut().unwrap().exchange_correlation = Some(dec!(0.9));
let high_price = exchange_black_scholes(&high_corr)?;

assert!(low_price > high_price);

Key Files and Architecture

  • src/pricing/exchange.rs – Core implementation of Margrabe's formula with exchange_black_scholes and margrabe_formula functions.
  • src/model/types.rs – Defines OptionType::Exchange { second_asset: f64 } variant.
  • src/pricing/mod.rs – Public re-exports for pricing functions (line 193).
  • src/model/option.rs – Options struct and high-level calculate_price_black_scholes method.
  • src/model/exotic_params.rs – Holds exchange-specific parameters including volatility, dividend yield, and correlation for the second asset.

Summary

  • Margrabe's formula provides a closed-form solution for pricing exchange options where one asset is swapped for another without a strike price.
  • The OptionStratLib implementation in src/pricing/exchange.rs computes combined volatility accounting for correlation, then applies the standard Black-Scholes structure to the asset ratio.
  • Key inputs include both assets' prices, volatilities, dividend yields, correlation coefficient, and time to maturity.
  • The library handles long and short positions through automatic sign adjustment and validates all exotic parameters before computation.

Frequently Asked Questions

What is Margrabe's formula used for?

Margrabe's formula is used to price exchange options, which give the holder the right to exchange one risky asset for another at maturity. Unlike standard options, there is no cash strike price—the "strike" is the second asset itself. The formula is commonly applied in mergers and acquisitions, spread trading, and currency swap valuations.

How does correlation affect exchange option pricing?

Correlation has an inverse relationship with exchange option value. When correlation (\rho) between the two assets is low (near 0), the combined volatility (\sigma = \sqrt{\sigma_1^2 + \sigma_2^2 - 2\rho\sigma_1\sigma_2}) increases, raising the option price. High correlation (near 1) reduces the effective volatility of the spread, decreasing the option value because the assets tend to move together, reducing the chance of a favorable exchange.

What parameters are required for Margrabe's formula?

The formula requires two sets of asset parameters: spot prices ((S_1), (S_2)), volatilities ((\sigma_1), (\sigma_2)), and continuous dividend yields ((q_1), (q_2)). Additionally, you need the correlation coefficient (\rho) between the assets and the time to maturity (T). In OptionStratLib, these are passed via the ExoticParams struct with fields exchange_second_asset_volatility, exchange_second_asset_dividend, and exchange_correlation.

Where is Margrabe's formula implemented in OptionStratLib?

Margrabe's formula is implemented in src/pricing/exchange.rs within the margrabe_formula function, which is called by the public API function exchange_black_scholes. The implementation handles the combined volatility calculation, d1/d2 computations, and final price derivation using the standard normal CDF. The option type definition resides in src/model/types.rs as OptionType::Exchange, while additional parameters are stored in the ExoticParams struct.

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 →