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

> Discover Margrabe's formula for exchange option pricing. This guide explains how to implement the closed-form solution for swapping assets at maturity using OptionStratLib.

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

---

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

```rust
// 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`](https://github.com/joaquinbejar/optionstratlib/blob/main/src/pricing/exchange.rs):

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

```rust
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`](https://github.com/joaquinbejar/optionstratlib/blob/main/src/pricing/exchange.rs) (lines 63-79) demonstrates how correlation impacts pricing:

```rust
// 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`](https://github.com/joaquinbejar/optionstratlib/blob/main/src/pricing/exchange.rs)** – Core implementation of Margrabe's formula with `exchange_black_scholes` and `margrabe_formula` functions.
- **[`src/model/types.rs`](https://github.com/joaquinbejar/optionstratlib/blob/main/src/model/types.rs)** – Defines `OptionType::Exchange { second_asset: f64 }` variant.
- **[`src/pricing/mod.rs`](https://github.com/joaquinbejar/optionstratlib/blob/main/src/pricing/mod.rs)** – Public re-exports for pricing functions (line 193).
- **[`src/model/option.rs`](https://github.com/joaquinbejar/optionstratlib/blob/main/src/model/option.rs)** – `Options` struct and high-level `calculate_price_black_scholes` method.
- **[`src/model/exotic_params.rs`](https://github.com/joaquinbejar/optionstratlib/blob/main/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`](https://github.com/joaquinbejar/optionstratlib/blob/main/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`](https://github.com/joaquinbejar/optionstratlib/blob/main/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`](https://github.com/joaquinbejar/optionstratlib/blob/main/src/model/types.rs) as `OptionType::Exchange`, while additional parameters are stored in the `ExoticParams` struct.