TouchOptionBlackScholesModelBoundary.java
package net.finmath.finitedifference.assetderivativevaluation.boundaries;
import net.finmath.finitedifference.assetderivativevaluation.models.FDMBlackScholesModel;
import net.finmath.finitedifference.assetderivativevaluation.products.FiniteDifferenceEquityProduct;
import net.finmath.finitedifference.assetderivativevaluation.products.TouchOption;
import net.finmath.finitedifference.boundaries.BoundaryCondition;
import net.finmath.finitedifference.boundaries.StandardBoundaryCondition;
import net.finmath.modelling.products.BarrierType;
/**
* Boundary conditions for {@link TouchOption} under {@link
* FDMBlackScholesModel}.
*
* <p>
* Current milestone scope:
* expiry-settled cash one-touch / no-touch only.
* </p>
*/
public class TouchOptionBlackScholesModelBoundary implements FiniteDifferenceBoundary {
/**
* The epsilon.
*/
private static final double EPSILON = 1E-6;
/**
* The model.
*/
private final FDMBlackScholesModel model;
/**
* Performs the operation.
*
* @param model The value.
*/
public TouchOptionBlackScholesModelBoundary(final FDMBlackScholesModel model) {
this.model = model;
}
@Override
public BoundaryCondition[] getBoundaryConditionsAtLowerBoundary(
final FiniteDifferenceEquityProduct product,
double time,
final double... stateVariables) {
final TouchOption option = (TouchOption) product;
final BarrierType barrierType = option.getBarrierType();
if (barrierType == BarrierType.DOWN_OUT) {
return new BoundaryCondition[] {
StandardBoundaryCondition.dirichlet(0.0)
};
}
time = Math.max(time, EPSILON);
return new BoundaryCondition[] {
StandardBoundaryCondition.dirichlet(getDiscountedCashValue(option, time))
};
}
@Override
public BoundaryCondition[] getBoundaryConditionsAtUpperBoundary(
final FiniteDifferenceEquityProduct product,
double time,
final double... stateVariables) {
final TouchOption option = (TouchOption) product;
final BarrierType barrierType = option.getBarrierType();
if (barrierType == BarrierType.UP_OUT) {
return new BoundaryCondition[] {
StandardBoundaryCondition.dirichlet(0.0)
};
}
time = Math.max(time, EPSILON);
return new BoundaryCondition[] {
StandardBoundaryCondition.dirichlet(getDiscountedCashValue(option, time))
};
}
private double getDiscountedCashValue(final TouchOption option, final double time) {
if (time >= option.getMaturity()) {
return option.getPayoffAmount();
}
final double dfTime = model.getRiskFreeCurve().getDiscountFactor(time);
final double dfMat = model.getRiskFreeCurve().getDiscountFactor(option.getMaturity());
return option.getPayoffAmount() * dfMat / dfTime;
}
}