WorstOfExpressCertificate.java
/*
* (c) Copyright Christian P. Fries, Germany. Contact: email@christian-fries.de.
*
* Created on 04.04.2015
*/
package net.finmath.montecarlo.hybridassetinterestrate.products;
import net.finmath.exception.CalculationException;
import net.finmath.modelling.Model;
import net.finmath.modelling.Product;
import net.finmath.montecarlo.hybridassetinterestrate.HybridAssetLIBORModelMonteCarloSimulation;
import net.finmath.stochastic.RandomVariable;
import net.finmath.stochastic.Scalar;
/**
* @author Christian Fries
* @version 1.0
*/
public class WorstOfExpressCertificate implements Product {
private final double maturity;
private final double[] strikeLevels;
private final double[] exerciseDates;
private final double[] triggerPerformanceLevel;
private final double[] redemption;
private final double redemptionFinal;
public WorstOfExpressCertificate(final double maturity, final double[] baseLevels,
final double[] exerciseDates, final double[] triggerLevels,
final double[] redemption, final double redemptionFinal) {
super();
this.maturity = maturity;
strikeLevels = baseLevels;
this.exerciseDates = exerciseDates;
triggerPerformanceLevel = triggerLevels;
this.redemption = redemption;
this.redemptionFinal = redemptionFinal;
}
/* (non-Javadoc)
* @see net.finmath.modelling.Product#getValue(double, net.finmath.modelling.Model)
*/
@Override
public Object getValue(final double evaluationTime, final Model model) {
return null;
}
public double getValue(final double evaluationTime, final HybridAssetLIBORModelMonteCarloSimulation model) throws CalculationException {
final RandomVariable zero = model.getRandomVariableForConstant(0.0);
RandomVariable values = model.getRandomVariableForConstant(0.0);
RandomVariable exerciseIndicator = model.getRandomVariableForConstant(1.0);
for(int triggerIndex=0; triggerIndex<exerciseDates.length; triggerIndex++) {
// get worst performance
final RandomVariable worstPerformance = getWorstPerformance(model, exerciseDates[triggerIndex], strikeLevels);
// exercise if worstPerformance >= triggerPerformanceLevel[triggerIndex]
final RandomVariable trigger = worstPerformance.sub(triggerPerformanceLevel[triggerIndex]);
RandomVariable payment = exerciseIndicator.mult(redemption[triggerIndex]);
payment = payment.div(model.getNumeraire(exerciseDates[triggerIndex]));
// if trigger >= 0 we have a payment and set the exerciseIndicator to 0.
values = values.add(trigger.choose(payment, new Scalar(0.0)));
exerciseIndicator = trigger.choose(zero, exerciseIndicator);
}
/*
* final redemption
*/
final RandomVariable worstPerformance = getWorstPerformance(model, maturity, strikeLevels);
RandomVariable payment = exerciseIndicator.mult(worstPerformance.mult(redemptionFinal));
payment = payment.div(model.getNumeraire(maturity));
values = values.add(payment);
/*
* numeraire at evaluationTime
*/
values = values.mult(model.getNumeraire(evaluationTime));
return values.getAverage();
}
/**
* @param model
* @param exerciseDate
* @param baseLevels
* @return
* @throws CalculationException
*/
private static RandomVariable getWorstPerformance(final HybridAssetLIBORModelMonteCarloSimulation model, final double exerciseDate, final double[] baseLevels) throws CalculationException {
RandomVariable worstPerformance = null;
for(int assetIndex=0; assetIndex<baseLevels.length; assetIndex++) {
final RandomVariable underlying = model.getAssetValue(exerciseDate, assetIndex);
final RandomVariable performance = underlying.div(baseLevels[assetIndex]);
worstPerformance = worstPerformance != null ? worstPerformance.cap(performance) : performance;
}
return worstPerformance;
}
}