/*
* Created on 15.09.2006
*
* (c) Copyright Christian P. Fries, Germany. All rights reserved. Contact: email@christian-fries.de.
*/
package net.finmath.montecarlo.interestrate.products.indices;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import net.finmath.exception.CalculationException;
import net.finmath.montecarlo.interestrate.LIBORModelMonteCarloSimulationInterface;
import net.finmath.stochastic.RandomVariableInterface;
/**
* An idealized (single curve) CMS index with given maturity and given period length.
*
* @author Christian Fries
*/
public class ConstantMaturitySwaprate extends AbstractIndex {
private static final long serialVersionUID = -5353191308059733179L;
final double fixingOffset;
final double[] periodLengths;
/**
* Create a CMS index with given fixing offset and given period lengths.
*
* @param name The name of the underlying index.
* @param currency The currency of the underlying index, if any.
* @param fixingOffset Fixing offset of this index.
* @param periodLengths Period length of underlying swap, used for the swap annuity calculation.
*/
public ConstantMaturitySwaprate(String name, String currency, double fixingOffset, double[] periodLengths) {
super(name, currency);
this.fixingOffset = fixingOffset;
this.periodLengths = periodLengths;
}
/**
* Create a CMS index with given fixing offset and given period lengths.
*
* @param fixingOffset Fixing offset of this index.
* @param periodLengths Period length of underlying swap, used for the swap annuity calculation.
*/
public ConstantMaturitySwaprate(double fixingOffset, double[] periodLengths) {
this(null, null, fixingOffset, periodLengths);
}
/**
* Create a CMS index with given period lengths.
*
* @param periodLengths Period length of underlying swap, used for the swap annuity calculation.
*/
public ConstantMaturitySwaprate(double[] periodLengths) {
this(0.0, periodLengths);
}
/**
* Create a CMS index with given fixing offset and given maturity and given period length.
* Note that maturity must be a multiple of the period length.
*
* @param name The name of the underlying index.
* @param currency The currency of the underlying index, if any.
* @param fixingOffset Fixing offset of this index.
* @param maturity The maturity.
* @param periodLength Period length of underlying swap, used for the swap annuity calculation.
*/
public ConstantMaturitySwaprate(String name, String currency, double fixingOffset, double maturity, double periodLength) {
super(name, currency);
this.fixingOffset = fixingOffset;
int numberOfPeriods = (int) (maturity / periodLength + 0.5);
if(numberOfPeriods * periodLength != maturity) throw new IllegalArgumentException("matruity not divisible by periodLength");
this.periodLengths = new double[numberOfPeriods];
Arrays.fill(this.periodLengths,periodLength);
}
/**
* Create a CMS index with given fixing offset and given maturity and given period length.
* Note that maturity must be a multiple of the period length.
*
* @param fixingOffset Fixing offset of this index.
* @param maturity The maturity.
* @param periodLength Period length of underlying swap, used for the swap annuity calculation.
*/
public ConstantMaturitySwaprate(double fixingOffset, double maturity, double periodLength) {
this(null, null, fixingOffset, maturity, periodLength);
}
/**
* Create a CMS index with given maturity and given period length. Note that maturity must be a multiple of the period length.
*
* @param maturity Maturity of the swap rate.
* @param periodLength Period length of the fixed size (determines the swap annuity used)
*/
public ConstantMaturitySwaprate(double maturity, double periodLength) {
this(0.0, maturity, periodLength);
}
@Override
public RandomVariableInterface getValue(double evaluationTime, LIBORModelMonteCarloSimulationInterface model) throws CalculationException {
// Fetch curve
RandomVariableInterface forwardRates[] = new RandomVariableInterface[periodLengths.length];
double periodStart = evaluationTime+fixingOffset;
for(int periodIndex = 0; periodIndex < periodLengths.length; periodIndex++) {
forwardRates[periodIndex] = model.getLIBOR(evaluationTime+fixingOffset, periodStart, periodStart+periodLengths[periodIndex]);
periodStart += periodLengths[periodIndex];
}
// Calculate float leg value (single curve/classical) and annuity.
RandomVariableInterface forwardBondInverse = model.getRandomVariableForConstant(1.0);
RandomVariableInterface forwardAnnuityInverse = model.getRandomVariableForConstant(periodLengths[periodLengths.length-1]);
for(int periodIndex = periodLengths.length-1; periodIndex>= 1; periodIndex--) {
RandomVariableInterface forwardBondOnePeriodInverse = (forwardRates[periodIndex]).mult(periodLengths[periodIndex]).add(1.0);
forwardBondInverse = forwardBondInverse.mult(forwardBondOnePeriodInverse);
forwardAnnuityInverse = forwardAnnuityInverse.addProduct(forwardBondInverse, periodLengths[periodIndex]);
}
RandomVariableInterface forwardBondOnePeriodInverse = (forwardRates[0]).mult(periodLengths[0]).add(1.0);
forwardBondInverse = forwardBondInverse.mult(forwardBondOnePeriodInverse);
RandomVariableInterface swaprate = forwardBondInverse.sub(1.0).div(forwardAnnuityInverse);
return swaprate;
}
@Override
public Set queryUnderlyings() {
Set underlyingNames = new HashSet();
underlyingNames.add(getName());
return underlyingNames;
}
@Override
public String toString() {
return "ConstantMaturitySwaprate [fixingOffset=" + fixingOffset
+ ", periodLengths=" + Arrays.toString(periodLengths) + "]";
}
}
Ads help maintain this website.