YieldCurve.java
package net.finmath.equities.marketdata;
import java.time.LocalDate;
import java.util.Arrays;
import net.finmath.marketdata.model.curves.CurveInterpolation.ExtrapolationMethod;
import net.finmath.marketdata.model.curves.CurveInterpolation.InterpolationEntity;
import net.finmath.marketdata.model.curves.CurveInterpolation.InterpolationMethod;
import net.finmath.marketdata.model.curves.DiscountCurveInterpolation;
import net.finmath.time.daycount.DayCountConvention;
/**
* Class to provide methods of a yield curve.
*
* @author Andreas Grotz
*/
public class YieldCurve {
private final LocalDate referenceDate;
private final LocalDate[] discountDates;
private final DayCountConvention dayCounter;
private final DiscountCurveInterpolation baseCurve;
public YieldCurve(
final String name,
final LocalDate referenceDate,
final DayCountConvention dayCounter,
final LocalDate[] discountDates,
final double[] discountFactors) {
this.dayCounter = dayCounter;
this.discountDates = discountDates;
final double[] times = new double[discountDates.length];
final boolean[] isParameter = new boolean[discountDates.length];
for(int i = 0; i < times.length; i++) {
times[i] = dayCounter.getDaycountFraction(referenceDate, discountDates[i]);
}
baseCurve = DiscountCurveInterpolation.createDiscountCurveFromDiscountFactors(
name,
referenceDate,
times,
discountFactors,
isParameter,
InterpolationMethod.LINEAR,
ExtrapolationMethod.CONSTANT,
InterpolationEntity.LOG_OF_VALUE_PER_TIME);
this.referenceDate = referenceDate;
}
public LocalDate getReferenceDate() {
return referenceDate;
}
public LocalDate[] getDiscountDates() {
return discountDates;
}
public DayCountConvention getDayCounter() {
return dayCounter;
}
public DiscountCurveInterpolation getBaseCurve() {
return baseCurve;
}
public YieldCurve rollToDate(LocalDate date) {
assert date.isAfter(referenceDate) : "can only roll to future dates";
final LocalDate[] rolledDiscountDates = Arrays.stream(discountDates)
.filter(p -> p.isAfter(date))
.toArray(LocalDate[]::new);
final double[] rolledDiscountFactors = new double[rolledDiscountDates.length];
for(int i = 0; i < rolledDiscountDates.length; i++) {
rolledDiscountFactors[i] = getForwardDiscountFactor(date, rolledDiscountDates[i]);
}
return new YieldCurve(baseCurve.getName(), date, dayCounter, rolledDiscountDates, rolledDiscountFactors);
}
public double getRate(double maturity) {
assert maturity >= 0.0 : "maturity must be positive";
return baseCurve.getZeroRate(maturity);
}
public double getRate(LocalDate date) {
return baseCurve.getZeroRate(dayCounter.getDaycountFraction(referenceDate, date));
}
public double getDiscountFactor(double maturity) {
assert maturity >= 0.0 : "maturity must be positive";
return baseCurve.getDiscountFactor(maturity);
}
public double getForwardDiscountFactor(double start, double expiry) {
assert start >= 0.0 : "start must be positive";
assert expiry >= start : "start must be before expiry";
return getDiscountFactor(expiry) / getDiscountFactor(start);
}
public double getDiscountFactor(LocalDate date) {
return baseCurve.getDiscountFactor(dayCounter.getDaycountFraction(referenceDate, date));
}
public double getForwardDiscountFactor(LocalDate startDate, LocalDate endDate) {
assert !startDate.isBefore(referenceDate) : "start date must be after curve date";
assert !endDate.isBefore(startDate) : "end date must be after start date";
return getDiscountFactor(endDate) / getDiscountFactor(startDate);
}
}