Price Exotic & Multi-Asset Trades

Price a Spread Option With Gradients on Both Legs

Edit the spark spread market and simulation inputs. The Java source below is regenerated from the form and computes Kirk and Margrabe references, a correlated Monte Carlo with both leg deltas, and the Schwartz seasonal futures curve.

Spread market
Option
SimulationOptional

Simulation defaults to 30,000 scenarios in the browser; increase the count to reduce Monte Carlo noise.

Java source
SpreadOptionsRiskStudio.java

This exact source runs in TeaVM. Form changes update its Java literals and reset manual edits.

import com.nablatensor.engine.Nabla;
import com.nablatensor.quant.SchwartzMarket;
import com.nablatensor.quant.SchwartzOneFactor;
import com.nablatensor.quant.Seasonality;
import com.nablatensor.quant.SpreadMarket;
import com.nablatensor.quant.SpreadProducts;
import com.nablatensor.quant.analytic.KirkSpreadOption;
import com.nablatensor.quant.analytic.Margrabe;

public final class SpreadOptionsRiskStudio {
  private SpreadOptionsRiskStudio() {}

  public static void main(String[] args) {
    SpreadMarket market = SpreadMarket.of()
        .s1(60)
        .s2(45)
        .vol1(35 / 100.0)
        .vol2(30 / 100.0)
        .yield1(0.0)
        .yield2(0.0)
        .rate(3 / 100.0)
        .build();
    double rho = 0.55, strike = 6, maturity = 0.5;
    int steps = 64;
    long scenarios = 30000L, seed = 42L;
    double kirk = KirkSpreadOption.price(market.s1(), market.s2(), strike, market.vol1(), market.vol2(),
        rho, market.rate(), market.yield1(), market.yield2(), maturity);
    double margrabe = Margrabe.of()
        .s1(market.s1())
        .s2(market.s2())
        .vol1(market.vol1())
        .vol2(market.vol2())
        .rho(rho)
        .yield1(market.yield1())
        .yield2(market.yield2())
        .maturity(maturity)
        .build()
        .price();
    try (Nabla.TypedPricer<SpreadMarket> pricer = Nabla.model(market, SpreadProducts.spreadOption(strike,
        rho, maturity, steps))
        .fp64()
        .greeks()
        .on("cpu")
        .build()) {
      Nabla.TypedValuation<SpreadMarket> value = pricer.value()
          .with(market)
          .scenarios(scenarios)
          .seed(seed)
          .run();
      SpreadMarket greeks = value.greeks();
      System.out.println("RESULT|" + value.price() + "|" + value.standardError() + "|" + kirk + "|"
          + margrabe + "|" + greeks.s1() + "|" + greeks.s2() + "|" + pricer.nodes());
    }
    SchwartzMarket schwartz = SchwartzMarket.of()
        .spot(50.0)
        .kappa(1.2)
        .level(Math.log(55.0))
        .sigma(0.30)
        .rate(0.03)
        .build();
    Seasonality season = Seasonality.of()
        .aCos(new double[] {
      0.06, 0.0
    })
        .aSin(new double[] {
      0.03, 0.0
    })
        .build();
    for (double t : new double[] {
      0.25, 0.5, 1.0, 2.0, 5.0
    }) {
      double futures = SchwartzOneFactor.futuresPrice(schwartz, t);
      System.out.println("CURVE|" + t + "|" + futures + "|" + futures * Math.exp(season.value(t)));
    }
  }
}
TeaVM compiles and runs the Java source above in this browser.
Implementation guide

Two legs, one correlated payoff

A spread option values the difference between correlated markets, making the correlation assumption a first-class input rather than a technical detail.

Core mechanism

The page compares an approximation with correlated Monte Carlo and differentiates the joint payoff with respect to both legs. The futures curve supplies the term structure behind the commodity values.

Practical workflow

Define both curves and volatilities, select and validate a dependence model, compare approximation error across regimes, and report separate leg risks as well as spread risk.

Key details

*Keywords: spark spread option java, kirk approximation java, margrabe exchange option java, schwartz one factor java, commodity mean reversion java, seasonality curve java*

Feature F10. Commodity prices mean-revert, and the contracts that matter — spark and dark spreads, calendar spreads, exchange options — are on the *difference* of two correlated assets. This adds the Schwartz mean-reverting model and the spread-option toolkit.

The Schwartz-Smith two-factor model (short-term deviation plus a stochastic equilibrium level) and generalising BasketOption beyond three assets are follow-ups.

The spread payoff depends on the difference between two prices, so its value is driven by both leg volatilities and their dependence. Correlation has an economic effect: when legs move together, uncertainty in their difference can be lower than uncertainty in either leg alone.

Approximate formulas are useful speed benchmarks, but the comparison with correlated Monte Carlo is informative precisely where approximation assumptions weaken: unusual moneyness, high volatility, long maturities or changing correlation. Reporting both leg deltas avoids collapsing a two-factor risk into one headline number.

Scope and review point

Commodity curves, convenience yield and seasonality are simplified. The approximation is a benchmark, not a replacement for model validation.