/*
* (c) Copyright Christian P. Fries, Germany. All rights reserved. Contact: email@christian-fries.de.
*
* Created on 15.02.2004
*/
package net.finmath.montecarlo.interestrate.products;
import java.util.Arrays;
import net.finmath.exception.CalculationException;
import net.finmath.functions.AnalyticFormulas;
import net.finmath.marketdata.model.curves.ForwardCurveInterface;
import net.finmath.marketdata.products.Swap;
import net.finmath.marketdata.products.SwapAnnuity;
import net.finmath.montecarlo.interestrate.LIBORModelMonteCarloSimulationInterface;
import net.finmath.stochastic.RandomVariableInterface;
import net.finmath.time.TimeDiscretization;
import net.finmath.time.TimeDiscretizationInterface;
/**
* Implements the valuation of a swaption under a LIBORModelMonteCarloSimulationInterface
*
* @author Christian Fries
* @version 1.1
*/
public class Swaption extends AbstractLIBORMonteCarloProduct {
private double exerciseDate; // Exercise date
private double[] fixingDates; // Vector of fixing dates (must be sorted)
private double[] paymentDates; // Vector of payment dates (same length as fixing dates)
private double[] periodLengths; // Vector of payment dates (same length as fixing dates)
private double[] swaprates; // Vector of strikes
/**
* Create a swaption.
*
* @param exerciseDate Vector of exercise dates.
* @param fixingDates Vector of fixing dates.
* @param paymentDates Vector of payment dates (must have same length as fixing dates).
* @param periodLengths Vector of period lengths.
* @param swaprates Vector of strikes (must have same length as fixing dates).
*/
public Swaption(double exerciseDate, double[] fixingDates, double[] paymentDates, double[] periodLengths, double[] swaprates) {
super();
this.exerciseDate = exerciseDate;
this.fixingDates = fixingDates;
this.paymentDates = paymentDates;
this.periodLengths = periodLengths;
this.swaprates = swaprates;
}
/**
* Create a swaption.
*
* @param exerciseDate Vector of exercise dates.
* @param fixingDates Vector of fixing dates.
* @param paymentDates Vector of payment dates (must have same length as fixing dates).
* @param swaprates Vector of strikes (must have same length as fixing dates).
*/
public Swaption(
double exerciseDate,
double[] fixingDates,
double[] paymentDates,
double[] swaprates) {
super();
this.exerciseDate = exerciseDate;
this.fixingDates = fixingDates;
this.paymentDates = paymentDates;
this.periodLengths = null;
this.swaprates = swaprates;
}
/**
* Creates a swaption using a TimeDiscretization
*
* @param exerciseDate Exercise date.
* @param swapTenor Object specifying period start and end dates.
* @param swaprate Strike.
*/
public Swaption(
double exerciseDate,
TimeDiscretizationInterface swapTenor,
double swaprate) {
super();
this.exerciseDate = exerciseDate;
this.fixingDates = new double[swapTenor.getNumberOfTimeSteps()];
this.paymentDates = new double[swapTenor.getNumberOfTimeSteps()];
for(int periodIndex=0; periodIndexcause() method.
*/
@Override
public RandomVariableInterface getValue(double evaluationTime, LIBORModelMonteCarloSimulationInterface model) throws CalculationException {
/*
* Calculate value of the swap at exercise date on each path (beware of perfect foresight - all rates are simulationTime=exerciseDate)
*/
RandomVariableInterface valueOfSwapAtExerciseDate = model.getRandomVariableForConstant(/*fixingDates[fixingDates.length-1],*/0.0);
// Calculate the value of the swap by working backward through all periods
for(int period=fixingDates.length-1; period>=0; period--)
{
double fixingDate = fixingDates[period];
double paymentDate = paymentDates[period];
double swaprate = swaprates[period];
double periodLength = periodLengths != null ? periodLengths[period] : paymentDate - fixingDate;
// Get random variables - note that this is the rate at simulation time = exerciseDate
RandomVariableInterface libor = model.getLIBOR(exerciseDate, fixingDate, paymentDate);
// Add payment received at end of period
RandomVariableInterface payoff = libor.sub(swaprate).mult(periodLength);
valueOfSwapAtExerciseDate = valueOfSwapAtExerciseDate.add(payoff);
// Discount back to beginning of period
valueOfSwapAtExerciseDate = valueOfSwapAtExerciseDate.discount(libor, paymentDate - fixingDate);
}
// If the exercise date is not the first periods start date, then discount back to the exercise date (calculate the forward starting swap)
if(fixingDates[0] != exerciseDate) {
RandomVariableInterface libor = model.getLIBOR(exerciseDate, exerciseDate, fixingDates[0]);
double periodLength = fixingDates[0] - exerciseDate;
// Discount back to beginning of period
valueOfSwapAtExerciseDate = valueOfSwapAtExerciseDate.discount(libor, periodLength);
}
/*
* Calculate swaption value
*/
RandomVariableInterface values = valueOfSwapAtExerciseDate.floor(0.0);
RandomVariableInterface numeraire = model.getNumeraire(exerciseDate);
RandomVariableInterface monteCarloProbabilities = model.getMonteCarloWeights(model.getTimeIndex(exerciseDate));
values = values.div(numeraire).mult(monteCarloProbabilities);
RandomVariableInterface numeraireAtZero = model.getNumeraire(evaluationTime);
RandomVariableInterface monteCarloProbabilitiesAtZero = model.getMonteCarloWeights(evaluationTime);
values = values.mult(numeraireAtZero).div(monteCarloProbabilitiesAtZero);
return values;
}
/**
* This method returns the value of the product using a Black-Scholes model for the swap rate
* The model is determined by a discount factor curve and a swap rate volatility.
*
* @param forwardCurve The forward curve on which to value the swap.
* @param swaprateVolatility The Black volatility.
* @return Value of this product
*/
public double getValue(ForwardCurveInterface forwardCurve, double swaprateVolatility) {
double swaprate = swaprates[0];
for (double swaprate1 : swaprates)
if (swaprate1 != swaprate)
throw new RuntimeException("Uneven swaprates not allows for analytical pricing.");
double[] swapTenor = new double[fixingDates.length+1];
System.arraycopy(fixingDates, 0, swapTenor, 0, fixingDates.length);
swapTenor[swapTenor.length-1] = paymentDates[paymentDates.length-1];
double forwardSwapRate = Swap.getForwardSwapRate(new TimeDiscretization(swapTenor), new TimeDiscretization(swapTenor), forwardCurve);
double swapAnnuity = SwapAnnuity.getSwapAnnuity(new TimeDiscretization(swapTenor), forwardCurve);
return AnalyticFormulas.blackModelSwaptionValue(forwardSwapRate, swaprateVolatility, exerciseDate, swaprate, swapAnnuity);
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
return super.toString()
+ "\n" + "exerciseDate: " + exerciseDate
+ "\n" + "fixingDates: " + Arrays.toString(fixingDates)
+ "\n" + "paymentDates: " + Arrays.toString(paymentDates)
+ "\n" + "periodLengths: " + Arrays.toString(periodLengths)
+ "\n" + "swaprates: " + Arrays.toString(swaprates);
}
}
Ads help maintain this website.