/** * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.model.finitedifference; import org.apache.commons.lang.Validate; import com.opengamma.analytics.financial.model.option.pricing.analytic.formula.BlackFunctionData; import com.opengamma.analytics.financial.model.option.pricing.analytic.formula.BlackPriceFunction; import com.opengamma.analytics.financial.model.option.pricing.analytic.formula.EuropeanVanillaOption; import com.opengamma.analytics.math.function.Function1D; import com.opengamma.analytics.math.integration.Integrator1D; import com.opengamma.analytics.math.integration.RungeKuttaIntegrator1D; /** * */ public class MarkovChainSmallTimeApprox { private final double _vol1; private final double _vol2; private final double _lambda12; private final double _lambda21; private final double _probState1; private final Integrator1D<Double, Double> _integrator = new RungeKuttaIntegrator1D(); private final BlackPriceFunction _black = new BlackPriceFunction(); public MarkovChainSmallTimeApprox(final double vol1, final double vol2, final double lambda12, final double lambda21, final double probState1) { Validate.isTrue(vol1 >= 0); Validate.isTrue(vol2 >= 0); Validate.isTrue(lambda12 >= 0); Validate.isTrue(lambda21 >= 0); Validate.isTrue(probState1 >= 0 && probState1 <= 1.0); _vol1 = vol1; _vol2 = vol2; _lambda12 = lambda12; _lambda21 = lambda21; _probState1 = probState1; } public double price(final double forward, final double df, final double strike, final double expiry) { final EuropeanVanillaOption option = new EuropeanVanillaOption(strike, expiry, true); final Function1D<BlackFunctionData, Double> priceFunc = _black.getPriceFunction(option); final Function1D<Double, Double> fun1 = new Function1D<Double, Double>() { @SuppressWarnings("synthetic-access") @Override public Double evaluate(final Double tau) { double sigma = _vol1 * _vol1 * tau / expiry + _vol2 * _vol2 * (1 - tau / expiry); sigma = Math.sqrt(sigma); final BlackFunctionData data = new BlackFunctionData(forward, df, sigma); return _lambda12 * priceFunc.evaluate(data) * Math.exp(-_lambda12 * tau); } }; final Function1D<Double, Double> fun2 = new Function1D<Double, Double>() { @SuppressWarnings("synthetic-access") @Override public Double evaluate(final Double tau) { double sigma = _vol1 * _vol1 * (1 - tau / expiry) + _vol2 * _vol2 * tau / expiry; sigma = Math.sqrt(sigma); final BlackFunctionData data = new BlackFunctionData(forward, df, sigma); return _lambda21 * priceFunc.evaluate(data) * Math.exp(-_lambda21 * tau); } }; double p1 = 0; double p2 = 0; if (_probState1 > 0.0) { final BlackFunctionData data = new BlackFunctionData(forward, df, _vol1); p1 = _integrator.integrate(fun1, 0.0, expiry) + priceFunc.evaluate(data) * Math.exp(-_lambda12 * expiry); } if (_probState1 < 1.0) { final BlackFunctionData data = new BlackFunctionData(forward, df, _vol2); p2 = _integrator.integrate(fun2, 0.0, expiry) + priceFunc.evaluate(data) * Math.exp(-_lambda21 * expiry); } return _probState1 * p1 + (1 - _probState1) * p2; } }