package net.finmath.marketdata.model.curves;
import java.io.Serializable;
import java.util.Date;
import org.joda.time.LocalDate;
import net.finmath.marketdata.model.AnalyticModelInterface;
/**
*
* @author Alessandro Gnoatto
*
*/
public class HazardCurve extends Curve implements Serializable, HazardCurveInterface{
private static final long serialVersionUID = 8538289748469149026L;
/**
* Create an empty discount curve using default interpolation and extrapolation methods.
*
* @param name The name of this hazard curve.
*/
private HazardCurve(String name){
super(name,null,InterpolationMethod.LINEAR,ExtrapolationMethod.CONSTANT,InterpolationEntity.LOG_OF_VALUE_PER_TIME);
}
/**
* Create an empty hazard curve using given interpolation and extrapolation methods.
*
* @param name The name of this discount curve.
* @param interpolationMethod The interpolation method used for the curve.
* @param extrapolationMethod The extrapolation method used for the curve.
* @param interpolationEntity The entity interpolated/extrapolated.
*/
private HazardCurve(String name, InterpolationMethod interpolationMethod,
ExtrapolationMethod extrapolationMethod, InterpolationEntity interpolationEntity){
super(name, null, interpolationMethod, extrapolationMethod, interpolationEntity);
}
/**
* Create an empty hazard curve using given interpolation and extrapolation methods.
*
* @param name The name of this hazard curve.
* @param referenceDate The reference date for this curve, i.e., the date which defined t=0.
* @param interpolationMethod The interpolation method used for the curve.
* @param extrapolationMethod The extrapolation method used for the curve.
* @param interpolationEntity The entity interpolated/extrapolated.
*/
private HazardCurve(String name, LocalDate referenceDate, InterpolationMethod interpolationMethod,
ExtrapolationMethod extrapolationMethod, InterpolationEntity interpolationEntity){
super(name, referenceDate, interpolationMethod, extrapolationMethod, interpolationEntity);
}
/**
* Create a hazard curve from given times and given survival probabilities using given interpolation and extrapolation methods.
*
* @param name The name of this discount curve.
* @param referenceDate The reference date for this curve, i.e., the date which defined t=0.
* @param times Array of times as doubles.
* @param givenSurvivalProbabilities Array of corresponding survival probabilities.
* @param isParameter Array of booleans specifying whether this point is served "as as parameter", e.g., whether it is calibrates (e.g. using CalibratedCurves).
* @param interpolationMethod The interpolation method used for the curve.
* @param extrapolationMethod The extrapolation method used for the curve.
* @param interpolationEntity The entity interpolated/extrapolated.
* @return A new hazard curve object.
*/
public static HazardCurve createHazardCurveFromSurvivalProbabilities(
String name, LocalDate referenceDate,
double[] times, double[] givenSurvivalProbabilities, boolean[] isParameter,
InterpolationMethod interpolationMethod, ExtrapolationMethod extrapolationMethod, InterpolationEntity interpolationEntity) {
//We check that all input survival probabilities are in the range [0,1]
for( int i = 0; i < givenSurvivalProbabilities.length; i++){
if(givenSurvivalProbabilities[i] < 0 || givenSurvivalProbabilities[i] > 1)
throw new IllegalArgumentException("Survival Probabilities must be between 0 and 1");
}
HazardCurve survivalProbabilities = new HazardCurve(name, referenceDate, interpolationMethod, extrapolationMethod, interpolationEntity);
for(int timeIndex=0; timeIndex<times.length;timeIndex++) {
survivalProbabilities.addSurvivalProbability(times[timeIndex], givenSurvivalProbabilities[timeIndex], isParameter != null && isParameter[timeIndex]);
}
return survivalProbabilities;
}
/**
* Create a hazard curve from given times and given survival probabilities using given interpolation and extrapolation methods.
*
* @param name The name of this discount curve.
* @param times Array of times as doubles.
* @param givenSurvivalProbabilities Array of corresponding survival probabilities.
* @param isParameter Array of booleans specifying whether this point is served "as as parameter", e.g., whether it is calibrates (e.g. using CalibratedCurves).
* @param interpolationMethod The interpolation method used for the curve.
* @param extrapolationMethod The extrapolation method used for the curve.
* @param interpolationEntity The entity interpolated/extrapolated.
* @return A new hazard curve object.
*/
public static HazardCurve createHazardCurveFromSurvivalProbabilities(
String name,
double[] times,
double[] givenSurvivalProbabilities,
boolean[] isParameter,
InterpolationMethod interpolationMethod, ExtrapolationMethod extrapolationMethod, InterpolationEntity interpolationEntity) {
return createHazardCurveFromSurvivalProbabilities(name, null, times, givenSurvivalProbabilities, isParameter, interpolationMethod, extrapolationMethod, interpolationEntity);
}
/**
* Create a hazard curve from given times and given survival probabilities using given interpolation and extrapolation methods.
*
* @param name The name of this discount curve.
* @param times Array of times as doubles.
* @param givenSurvivalProbabilities Array of corresponding survival probabilities.
* @param interpolationMethod The interpolation method used for the curve.
* @param extrapolationMethod The extrapolation method used for the curve.
* @param interpolationEntity The entity interpolated/extrapolated.
* @return A new discount factor object.
*/
public static HazardCurve createHazardCurveFromSurvivalProbabilities(
String name,
double[] times,
double[] givenSurvivalProbabilities,
InterpolationMethod interpolationMethod, ExtrapolationMethod extrapolationMethod, InterpolationEntity interpolationEntity) {
boolean[] isParameter = new boolean[times.length];
for(int timeIndex=0; timeIndex<times.length;timeIndex++) {
isParameter[timeIndex] = times[timeIndex] > 0;
}
return createHazardCurveFromSurvivalProbabilities(name, times, givenSurvivalProbabilities, isParameter, interpolationMethod, extrapolationMethod, interpolationEntity);
}
/**
* Create a hazard curve from given times and given discount factors using default interpolation and extrapolation methods.
*
* @param name The name of this discount curve.
* @param times Array of times as doubles.
* @param givenSurvivalProbabilities Array of corresponding survival probabilities.
* @return A new discount factor object.
*/
public static HazardCurve createHazardCurveFromSurvivalProbabilities(String name, double[] times, double[] givenSurvivalProbabilities){
HazardCurve survivalProbabilities = new HazardCurve(name);
for(int timeIndex=0; timeIndex<times.length;timeIndex++) {
survivalProbabilities.addSurvivalProbability(times[timeIndex], givenSurvivalProbabilities[timeIndex], times[timeIndex] > 0);
}
return survivalProbabilities;
}
/**
* Create a hazard curve from given times and given hazard rates using given interpolation and extrapolation methods.
* The discount factor is determined by
* <code>
* givenSurvivalProbabilities[timeIndex] = givenSurvivalProbabilities[timeIndex-1] * Math.exp(- givenHazardRates[timeIndex] * (times[timeIndex]-times[timeIndex-1]));
* </code>
*
* @param name The name of this discount curve.
* @param referenceDate The reference date for this curve, i.e., the date which defined t=0.
* @param times Array of times as doubles.
* @param givenSurvivalProbabilities Array of corresponding hazard rates.
* @param isParameter Array of booleans specifying whether this point is served "as as parameter", e.g., whether it is calibrates (e.g. using CalibratedCurves).
* @param interpolationMethod The interpolation method used for the curve.
* @param extrapolationMethod The extrapolation method used for the curve.
* @param interpolationEntity The entity interpolated/extrapolated.
* @return A new discount factor object.
*/
public static HazardCurve createHazardCurveFromHazardRate(
String name, LocalDate referenceDate,
double[] times, double[] givenHazardRates, boolean[] isParameter,
InterpolationMethod interpolationMethod, ExtrapolationMethod extrapolationMethod, InterpolationEntity interpolationEntity){
double[] givenSurvivalProbabilities = new double[givenHazardRates.length];
if(givenHazardRates[0]<0)
throw new IllegalArgumentException("First hazard rate is not positive");
//initialize the term structure
givenSurvivalProbabilities[0] = Math.exp(- givenHazardRates[0] * times[0]);
/*
* Construct the hazard curve by numerically integrating the hazard rates.
* At each step check if the input hazard rate is positive.
*/
for(int timeIndex=1; timeIndex<times.length;timeIndex++) {
if(givenHazardRates[timeIndex]<0)
throw new IllegalArgumentException("The " + timeIndex + "-th hazard rate is not positive");
givenSurvivalProbabilities[timeIndex] = givenSurvivalProbabilities[timeIndex-1] * Math.exp(- givenHazardRates[timeIndex] * (times[timeIndex]-times[timeIndex-1]));
}
return createHazardCurveFromSurvivalProbabilities(name, referenceDate, times, givenSurvivalProbabilities, isParameter, interpolationMethod, extrapolationMethod, interpolationEntity);
}
/**
* Create a hazard curve from given times and given zero rates using given interpolation and extrapolation methods.
* The discount factor is determined by
* <code>
* givenSurvivalProbabilities[timeIndex] = givenSurvivalProbabilities[timeIndex-1] * Math.exp(- givenHazardRates[timeIndex] * (times[timeIndex]-times[timeIndex-1]));
* </code>
*
* @param name The name of this discount curve.
* @param referenceDate The reference date for this curve, i.e., the date which defined t=0.
* @param times Array of times as doubles.
* @param givenHazardRates Array of corresponding survival probabilities.
* @param isParameter Array of booleans specifying whether this point is served "as as parameter", e.g., whether it is calibrates (e.g. using CalibratedCurves).
* @param interpolationMethod The interpolation method used for the curve.
* @param extrapolationMethod The extrapolation method used for the curve.
* @param interpolationEntity The entity interpolated/extrapolated.
* @return A new discount factor object.
*/
public static HazardCurve createHazardCurveFromHazardRate(
String name, Date referenceDate,
double[] times, double[] givenHazardRates, boolean[] isParameter,
InterpolationMethod interpolationMethod, ExtrapolationMethod extrapolationMethod, InterpolationEntity interpolationEntity) {
return createHazardCurveFromHazardRate(name, new LocalDate(referenceDate), times, givenHazardRates, isParameter, interpolationMethod, extrapolationMethod, interpolationEntity);
}
/**
* Create a discount curve from given times and given zero rates using given interpolation and extrapolation methods.
* The discount factor is determined by
* <code>
* givenSurvivalProbabilities[timeIndex] = givenSurvivalProbabilities[timeIndex-1] * Math.exp(- givenHazardRates[timeIndex] * (times[timeIndex]-times[timeIndex-1]));
* </code>
*
* @param name The name of this discount curve.
* @param referenceDate The reference date for this curve, i.e., the date which defined t=0.
* @param times Array of times as doubles.
* @param givenZeroRates Array of corresponding zero rates.
* @param interpolationMethod The interpolation method used for the curve.
* @param extrapolationMethod The extrapolation method used for the curve.
* @param interpolationEntity The entity interpolated/extrapolated.
* @return A new discount factor object.
*/
public static HazardCurve createHazardCurveFromHazardRate(
String name, LocalDate referenceDate,
double[] times, double[] givenHazardRates,
InterpolationMethod interpolationMethod, ExtrapolationMethod extrapolationMethod, InterpolationEntity interpolationEntity){
boolean[] isParameter = new boolean[givenHazardRates.length];
double[] givenSurvivalProbabilities = new double[givenHazardRates.length];
if(givenHazardRates[0]<0)
throw new IllegalArgumentException("First hazard rate is not positive");
//initialize the term structure
givenSurvivalProbabilities[0] = Math.exp(- givenHazardRates[0] * times[0]);
/*
* Construct the hazard curve by numerically integrating the hazard rates.
* At each step check if the input hazard rate is positive.
*/
for(int timeIndex=1; timeIndex<times.length;timeIndex++) {
if(givenHazardRates[timeIndex]<0)
throw new IllegalArgumentException("The " + timeIndex + "-th hazard rate is not positive");
givenSurvivalProbabilities[timeIndex] = givenSurvivalProbabilities[timeIndex-1] * Math.exp(- givenHazardRates[timeIndex] * (times[timeIndex]-times[timeIndex-1]));
}
return createHazardCurveFromSurvivalProbabilities(name, referenceDate, times, givenSurvivalProbabilities, isParameter, interpolationMethod, extrapolationMethod, interpolationEntity);
}
/**
* Create a discount curve from given times and given zero rates using default interpolation and extrapolation methods.
* The discount factor is determined by
* <code>
* givenSurvivalProbabilities[timeIndex] = givenSurvivalProbabilities[timeIndex-1] * Math.exp(- givenHazardRates[timeIndex] * (times[timeIndex]-times[timeIndex-1]));
* </code>
*
* @param name The name of this discount curve.
* @param times Array of times as doubles.
* @param givenZeroRates Array of corresponding zero rates.
* @return A new discount factor object.
*/
public static HazardCurve createHazardCurveFromHazardRate(String name, double[] times, double[] givenHazardRates){
double[] givenSurvivalProbabilities = new double[givenHazardRates.length];
if(givenHazardRates[0]<0)
throw new IllegalArgumentException("First hazard rate is not positive");
//initialize the term structure
givenSurvivalProbabilities[0] = Math.exp(- givenHazardRates[0] * times[0]);
/*
* Construct the hazard curve by numerically integrating the hazard rates.
* At each step check if the input hazard rate is positive.
*/
for(int timeIndex=1; timeIndex<times.length;timeIndex++) {
if(givenHazardRates[timeIndex]<0)
throw new IllegalArgumentException("The " + timeIndex + "-th hazard rate is not positive");
givenSurvivalProbabilities[timeIndex] = givenSurvivalProbabilities[timeIndex-1] * Math.exp(- givenHazardRates[timeIndex] * (times[timeIndex]-times[timeIndex-1]));
}
return createHazardCurveFromSurvivalProbabilities(name, times, givenSurvivalProbabilities);
}
@Override
public double getSurvivalProbability(AnalyticModelInterface model, double maturity) {
double candidateSurvivalProbability = super.getValue(model, maturity);
/*
* A probability must be in the interval [0,1] this guarantees also that hazard rates are positive.
* In this way the optimizer should always be able to continue without applying bogus probabilities to the CDS instrument.
*/
if(candidateSurvivalProbability >= 1){
return 1;
}else if (candidateSurvivalProbability <= 0){
return 1E-20;
}else{
return candidateSurvivalProbability;
}
}
public double getHazardRate(AnalyticModelInterface model, double maturity){
if(maturity == 0) return 1.0E-14;
return -Math.log(getSurvivalProbability(model, maturity))/maturity;
}
protected void addSurvivalProbability(double maturity, double survivalProbability, boolean isParameter) {
this.addPoint(maturity, survivalProbability, isParameter);
}
@Override
public double getValue(AnalyticModelInterface model, double time){
double myHazard = -Math.abs(this.getHazardRate(model, time));
return Math.exp(myHazard*time);
}
@Override
public String toString() {
return super.toString();
}
}