/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.model.option.pricing.tree;
import org.apache.commons.lang.NotImplementedException;
import com.opengamma.analytics.financial.model.option.pricing.tree.BarrierOptionFunctionProvider.BarrierTypes;
import com.opengamma.util.ArgumentChecker;
/**
* Adaptive mesh method for single barrier options
*/
public class AdaptiveLatticeSpecification extends LatticeSpecification {
private static final double SHIFT = 1.e-12;
private final BarrierOptionFunctionProvider _provider;
/**
* Constructor specifying the barrier
* @param provider BarrierOptionFunctionProvider of OptionFunctionProvider1D
*/
public AdaptiveLatticeSpecification(final OptionFunctionProvider1D provider) {
ArgumentChecker.notNull(provider, "provider");
if (!(provider instanceof BarrierOptionFunctionProvider)) {
throw new IllegalArgumentException();
}
if (provider instanceof DoubleBarrierOptionFunctionProvider) {
throw new NotImplementedException();
}
_provider = (BarrierOptionFunctionProvider) provider;
}
@Override
public double[] getParameters(final double spot, final double strike, final double timeToExpiry, final double volatility, final double interestRate, final int nSteps, final double dt) {
throw new IllegalArgumentException("This lattice specification does not cover binomial tree");
}
@Override
public double[] getParametersTrinomial(final double spot, final double strike, final double timeToExpiry, final double volatility, final double interestRate, final int nSteps, final double dt) {
final double barrier = _provider.getBarrier();
final BarrierTypes type = _provider.getBarrierType();
final double sign = type == BarrierTypes.UpAndOut ? 1. : -1.;
final double modBarrier = barrier + sign * SHIFT;
final double volSq = volatility * volatility;
final double mu = interestRate - 0.5 * volSq;
final double mudt = mu * dt;
final double mudtSq = mudt * mudt;
final double rootDt = Math.sqrt(dt);
final double dx0 = volatility * Math.sqrt(3.) * rootDt;
final int position = (int) Math.round(Math.log(spot / barrier) / dx0);
final double lambdaSqRoot = Math.abs(Math.log(modBarrier / spot) / (position * volatility * rootDt));
final double dx = volatility * lambdaSqRoot * rootDt;
final double upFactor = Math.exp(dx);
final double downFactor = Math.exp(-dx);
final double part = (volSq * dt + mudtSq) / dx / dx;
final double upProbability = 0.5 * (part + mudt / dx);
final double middleProbability = 1. - part;
final double downProbability = 0.5 * (part - mudt / dx);
return new double[] {upFactor, 1., downFactor, upProbability, middleProbability, downProbability };
}
}