net.finmath.marketdata.model.cds.CDS Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of finmath-lib Show documentation
Show all versions of finmath-lib Show documentation
finmath lib is a Mathematical Finance Library in Java.
It provides algorithms and methodologies related to mathematical finance.
package net.finmath.marketdata.model.cds;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import net.finmath.marketdata.model.AnalyticModel;
import net.finmath.marketdata.model.AnalyticModelFromCurvesAndVols;
import net.finmath.marketdata.model.curves.Curve;
import net.finmath.marketdata.model.curves.DiscountCurve;
import net.finmath.marketdata.model.curves.DiscountCurveInterpolation;
import net.finmath.marketdata.model.curves.ForwardCurve;
import net.finmath.marketdata.products.AbstractAnalyticProduct;
import net.finmath.marketdata.products.AnalyticProduct;
import net.finmath.time.FloatingpointDate;
import net.finmath.time.Period;
import net.finmath.time.Schedule;
import net.finmath.time.ScheduleFromPeriods;
import net.finmath.time.businessdaycalendar.BusinessdayCalendarExcludingWeekends;
import net.finmath.time.daycount.DayCountConvention;
/**
* Implements the valuation of a CDS (fixed-fee CDS, floating-fee CDS, with upfront or without)
* from the perspective of the protection buyer with unit notional of 1 using curves:
*
* - a forward curve, if the bond has floating rate coupons
* - a discount curve as a base curve for discounting
* - a survival probability curve for additional credit risk related discount factor
* - a recovery rate curve to model a non-constant recovery rate term-structure
*
*
* Support for day counting is provided via the class implementing
* ScheduleFromPeriods
.
*
* @author Matthias Föhr
* @author Christian Fries
*/
public class CDS extends AbstractAnalyticProduct implements AnalyticProduct{
private final Schedule schedule;
private final String discountCurveName;
private final String forwardCurveName; //Set null if fixed-fee CDS
private final String survivalProbabilityCurveName;
private final String recoveryRateCurveName;
private final double fixedFee; //Set equal zero if floating rate CDS
private final double floatingFeeSpread;
private final double upfrontPayment; //From the perspective of the protection buyer (<0 if upfront is recieved)! Set equal to 0 if conventional CDS spread is considered
private final LocalDate tradeDate; // Trading Date of the CDS contract
private final CDS.ValuationModel valuationModel; // Either DISCRETE, JPM or JPM_NOACCFEE (DISCRETE = fee and recovery payments only at tenor dates, JPM = fee and recovery payments every business day according to JP Morgan Modell, JPM_NOACCFEE = JPM with fee payments only at tenor dates)
private final CDS.DirtyCleanPrice dirtyCleanPrice; // Either CLEAN or DIRTY price
private final boolean useFinerDiscretization;
/**
* Creates a CDS.
*
* @param schedule Schedule of the CDS.
* @param discountCurveName Name of the discount curve.
* @param forwardCurveName Name of the forward curve, leave empty if this is a fixed fee CDS
* @param survivalProbabilityCurveName Name of the survival probability curve.
* @param recoveryRateCurveName Name of the Recovery Rate CurveFromInterpolationPoints (1 Recovery Rate for each timestep in the scheduleFromPeriods).
* @param fixedFee The fixed fee of the CDS expressed as absolute value.
* @param floatingFeeSpread The floating fee spread of the CDS expressed as absolute value.
* @param upfrontPayment The initial upfront payment of the CDS from the perspective of the protection buyer(Nonzero if fee != conventional CDS spread).
* @param tradeDate Trading Date of the CDS contract
* @param valuationModel Defines the valuation model used (DISCRETE, JPM, JPM_NOACCFEE)
* @param dirtyCleanPrice Defines if CLEAN or DIRTY price is considered
* @param useFinerDiscretization Boolean if finer Discretization (discountCurve Dates + CDS Dates) is used
*/
private CDS(Schedule schedule,
String discountCurveName,
String forwardCurveName,
String survivalProbabilityCurveName,
String recoveryRateCurveName,
double fixedFee,
double floatingFeeSpread,
double upfrontPayment,
LocalDate tradeDate,
CDS.ValuationModel valuationModel,
CDS.DirtyCleanPrice dirtyCleanPrice,
boolean useFinerDiscretization)
{
super();
this.schedule = schedule;
this.discountCurveName = discountCurveName;
this.forwardCurveName = forwardCurveName;
this.survivalProbabilityCurveName = survivalProbabilityCurveName;
this.recoveryRateCurveName = recoveryRateCurveName;
this.fixedFee = fixedFee;
this.floatingFeeSpread = floatingFeeSpread;
this.upfrontPayment = upfrontPayment;
this.tradeDate = tradeDate;
this.valuationModel = valuationModel;
this.dirtyCleanPrice = dirtyCleanPrice;
this.useFinerDiscretization = useFinerDiscretization;
}
/**
* Creates a CDS with a fixed fee, no upfront.
*
* @param schedule Schedule of the CDS.
* @param discountCurveName Name of the discount curve.
* @param survivalProbabilityCurveName Name of the survival probability curve.
* @param recoveryRateCurveName Name of the Recovery Rate CurveFromInterpolationPoints (1 Recovery Rate for each timestep in the scheduleFromPeriods).
* @param fixedFee The fixed fee of the CDS expressed as absolute value.
* @param tradeDate Trading Date of the CDS contract
* @param valuationModel Defines the valuation model used (DISCRETE, JPM, JPM_NOACCFEE)
* @param dirtyCleanPrice Defines if CLEAN or DIRTY price is considered
* @param useFinerDiscretization Boolean if finer Discretization (discountCurve Dates + CDS Dates) is used
*/
public CDS(Schedule schedule, String discountCurveName, String survivalProbabilityCurveName, String recoveryRateCurveName, double fixedFee, LocalDate tradeDate, CDS.ValuationModel valuationModel, CDS.DirtyCleanPrice dirtyCleanPrice, boolean useFinerDiscretization) {
this(schedule, discountCurveName, null,survivalProbabilityCurveName, recoveryRateCurveName, fixedFee, 0, 0, tradeDate, valuationModel, dirtyCleanPrice, useFinerDiscretization );
}
/**
* Creates a CDS with a fixed fee, with upfront.
*
* @param schedule Schedule of the CDS.
* @param discountCurveName Name of the discount curve.
* @param survivalProbabilityCurveName Name of the survival probability curve.
* @param recoveryRateCurveName Name of the Recovery Rate CurveFromInterpolationPoints (1 Recovery Rate for each timestep in the scheduleFromPeriods).
* @param fixedFee The fixed fee of the CDS expressed as absolute value.
* @param tradeDate Trading Date of the CDS contract
* @param upfrontPayment The initial upfront payment of the CDS from the perspective of the protection buyer(Nonzero if fee != conventional CDS spread).
* @param valuationModel Defines the valuation model used (DISCRETE, JPM, JPM_NOACCFEE)
* @param dirtyCleanPrice Defines if CLEAN or DIRTY price is considered
* @param useFinerDiscretization Boolean if finer Discretization (discountCurve Dates + CDS Dates) is used
*/
public CDS(Schedule schedule, String discountCurveName, String survivalProbabilityCurveName, String recoveryRateCurveName, double fixedFee, double upfrontPayment, LocalDate tradeDate, CDS.ValuationModel valuationModel, CDS.DirtyCleanPrice dirtyCleanPrice, boolean useFinerDiscretization) {
this(schedule, discountCurveName, null,survivalProbabilityCurveName, recoveryRateCurveName, fixedFee, 0, upfrontPayment, tradeDate, valuationModel, dirtyCleanPrice, useFinerDiscretization );
}
/**
* Creates a CDS with a floating fee, no upfront.
*
* @param schedule Schedule of the CDS.
* @param discountCurveName Name of the discount curve.
* @param forwardCurveName Name of the forward curve, leave empty if this is a fixed fee CDS
* @param survivalProbabilityCurveName Name of the survival probability curve.
* @param recoveryRateCurveName Name of the Recovery Rate CurveFromInterpolationPoints (1 Recovery Rate for each timestep in the scheduleFromPeriods).
* @param floatingFeeSpread The floating fee spread of the CDS expressed as absolute value.
* @param tradeDate Trading Date of the CDS contract
* @param valuationModel Defines the valuation model used (DISCRETE, JPM, JPM_NOACCFEE)
* @param dirtyCleanPrice Defines if CLEAN or DIRTY price is considered
* @param useFinerDiscretization Boolean if finer Discretization (discountCurve Dates + CDS Dates) is used
*/
public CDS(ScheduleFromPeriods schedule, String discountCurveName, String forwardCurveName, String survivalProbabilityCurveName, String recoveryRateCurveName, double floatingFeeSpread, LocalDate tradeDate, CDS.ValuationModel valuationModel, CDS.DirtyCleanPrice dirtyCleanPrice, boolean useFinerDiscretization) {
this(schedule, discountCurveName, forwardCurveName, survivalProbabilityCurveName, recoveryRateCurveName, 0, floatingFeeSpread, 0, tradeDate, valuationModel, dirtyCleanPrice, useFinerDiscretization );
}
/**
* Creates a CDS with a floating fee, with upfront.
*
* @param schedule Schedule of the CDS.
* @param discountCurveName Name of the discount curve.
* @param forwardCurveName Name of the forward curve, leave empty if this is a fixed fee CDS
* @param survivalProbabilityCurveName Name of the survival probability curve.
* @param recoveryRateCurveName Name of the Recovery Rate CurveFromInterpolationPoints (1 Recovery Rate for each timestep in the scheduleFromPeriods).
* @param floatingFeeSpread The floating fee spread of the CDS expressed as absolute value.
* @param upfrontPayment The initial upfront payment of the CDS from the perspective of the protection buyer(Nonzero if fee != conventional CDS spread).
* @param tradeDate Trading Date of the CDS contract
* @param valuationModel Defines the valuation model used (DISCRETE, JPM, JPM_NOACCFEE)
* @param dirtyCleanPrice Defines if CLEAN or DIRTY price is considered
* @param useFinerDiscretization Boolean if finer Discretization (discountCurve Dates + CDS Dates) is used
*/
public CDS(ScheduleFromPeriods schedule, String discountCurveName, String forwardCurveName, String survivalProbabilityCurveName, String recoveryRateCurveName, double floatingFeeSpread, double upfrontPayment, LocalDate tradeDate, CDS.ValuationModel valuationModel, CDS.DirtyCleanPrice dirtyCleanPrice, boolean useFinerDiscretization) {
this(schedule, discountCurveName, forwardCurveName, survivalProbabilityCurveName, recoveryRateCurveName, 0, floatingFeeSpread, upfrontPayment, tradeDate, valuationModel, dirtyCleanPrice, useFinerDiscretization );
}
/**
* Evaluates the CDS at the evaluationTime according to a Analytic Model.
*
* @param evaluationTime Evaluation time of the pricing.
* @param model Analytic Model, within the CDS is priced.
*/
@Override
public double getValue(double evaluationTime, AnalyticModel model) {
if(model==null) {
throw new IllegalArgumentException("model==null");
}
final ForwardCurve forwardCurveInterpolation = model.getForwardCurve(forwardCurveName);
if(forwardCurveInterpolation == null && forwardCurveName != null && forwardCurveName.length() > 0) {
throw new IllegalArgumentException("No forward curve with name '" + forwardCurveName + "' was found in the model:\n" + model.toString());
}
// TODO Remove cast.
final DiscountCurveInterpolation discountCurve = (DiscountCurveInterpolation) model.getDiscountCurve(discountCurveName);
if(discountCurve == null) {
throw new IllegalArgumentException("No discount curve with name '" + discountCurveName + "' was found in the model:\n" + model.toString());
}
final Curve survivalProbabilityCurve = model.getCurve(survivalProbabilityCurveName);
if(survivalProbabilityCurve == null) {
throw new IllegalArgumentException("No survival probability curve with name '" + survivalProbabilityCurveName + "' was found in the model:\n" + model.toString());
}
final Curve recoveryRateCurve = model.getCurve(recoveryRateCurveName);
if(recoveryRateCurve == null) {
throw new IllegalArgumentException("No recovery rate curve with name '" + recoveryRateCurveName + "' was found in the model:\n" + model.toString());
}
final BusinessdayCalendarExcludingWeekends businessdayCalendarExcludingWeekends = new BusinessdayCalendarExcludingWeekends();
final LocalDate effectiveDate = businessdayCalendarExcludingWeekends.getRolledDate(tradeDate, 1); // Effective Date is Business Day after trading date [IGNORES HOLIDAYS]
// Create joint array of discountfactor times and payment dates
final Set jointTimeDiscretizationSet = new HashSet();
final double[] timesDiscountCurve = discountCurve.getTimes();
for(int i=0; i Adjust period Length in first period [First coupon not paid in full]
if (periodIndex == 0 && dirtyCleanPrice == DirtyCleanPrice.CLEAN) {
periodLength = schedule.getDaycountconvention().getDaycountFraction(effectiveDate, schedule.getPeriod(0).getPeriodEnd());
}
// Adjust period Length in last period by 1 businessday (CDS convention)
if (periodIndex == schedule.getNumberOfPeriods() - 1) {
periodLength += schedule.getDaycountconvention().getDaycountFraction(schedule.getPeriod(periodIndex).getPeriodEnd(), schedule.getPeriod(periodIndex).getPeriodEnd().plusDays(1));
}
// The protection in the first period starts at the effective date = trade date + 1 business day
final double previousPaymentDate = periodIndex > 0 ? schedule.getPayment(periodIndex - 1) : 0.0 + schedule.getDaycountconvention().getDaycountFraction(tradeDate, effectiveDate);
double discountFactor = paymentDate > evaluationTime ? discountCurve.getDiscountFactor(model, paymentDate) : 0.0;
double previousDiscountFactor = previousPaymentDate > evaluationTime ? discountCurve.getDiscountFactor(model, previousPaymentDate) : 1.0;
double survivalProbabilityFactor = paymentDate > evaluationTime ? survivalProbabilityCurve.getValue(model, paymentDate) : 0.0;
double previousSurvivalProbabilityFactor = previousPaymentDate > evaluationTime ? survivalProbabilityCurve.getValue(model, previousPaymentDate) : 1.0;
//Fee to be paid
double feePayment = fixedFee;
if (forwardCurveInterpolation != null) {
feePayment = floatingFeeSpread + forwardCurveInterpolation.getForward(model, schedule.getFixing(periodIndex));
}
// Recovery rate in case of default
final double recoveryRate = recoveryRateCurve.getValue(model, paymentDate);
// Precomputation for JPM and JPM_NOACCFEE model
final double periodStartTime = Math.max(schedule.getPeriodStart(periodIndex), evaluationTime);
final double periodEndTime = Math.max(schedule.getPeriodEnd(periodIndex), evaluationTime);
double forwardInterestRateFactor = (Math.log(discountCurve.getValue(model, periodStartTime)) - Math.log(discountCurve.getValue(model, periodEndTime))) / (periodEndTime - periodStartTime);
double hazardRateFactor = (Math.log(survivalProbabilityCurve.getValue(model, periodStartTime)) - Math.log(survivalProbabilityCurve.getValue(model, periodEndTime))) / (periodEndTime - periodStartTime);
double accruedFactorJPM = hazardRateFactor * (1 / Math.pow(forwardInterestRateFactor + hazardRateFactor, 2) - ((periodEndTime - periodStartTime) / (forwardInterestRateFactor + hazardRateFactor) + 1 / Math.pow(forwardInterestRateFactor + hazardRateFactor, 2)) * (Math.exp(-(forwardInterestRateFactor + hazardRateFactor) * (periodEndTime - periodStartTime))));
// Switch valuation models
switch (valuationModel) {
case DISCRETE:
value += -feePayment * periodLength * discountFactor * survivalProbabilityFactor; // Fee payment [Protection Buyer View]
value += Math.max(1.0 - recoveryRate,0) * discountFactor * (previousSurvivalProbabilityFactor - survivalProbabilityFactor); // Recovery payment [Protection Buyer View]
break;
case JPM:
if (useFinerDiscretization) {
value += -feePayment * periodLength * discountFactor * survivalProbabilityFactor; // Fee payment [Protection Buyer View]
// JPM Model on jointTimeDiscretization
final int startIndex = Arrays.binarySearch(jointTimeDiscretization, periodStartTime); // was ArrayUtils.indexOf
final int endIndex = Arrays.binarySearch(jointTimeDiscretization, periodEndTime); // was ArrayUtils.indexOf
// Loop over subperiods
for (int subTimeIndex = startIndex; subTimeIndex < endIndex; subTimeIndex++) {
final double subPeriodStartTime = jointTimeDiscretization[subTimeIndex];
final double subPeriodEndTime = jointTimeDiscretization[subTimeIndex + 1];
final double subPeriodLength = subPeriodEndTime - subPeriodStartTime;
discountFactor = discountCurve.getDiscountFactor(model, subPeriodEndTime);
previousDiscountFactor = discountCurve.getDiscountFactor(model, subPeriodStartTime);
survivalProbabilityFactor = survivalProbabilityCurve.getValue(model, subPeriodEndTime);
previousSurvivalProbabilityFactor = survivalProbabilityCurve.getValue(model, subPeriodStartTime);
forwardInterestRateFactor = (Math.log(discountCurve.getValue(model, subPeriodStartTime)) - Math.log(discountCurve.getValue(model, subPeriodEndTime))) / (subPeriodEndTime - subPeriodStartTime);
hazardRateFactor = (Math.log(survivalProbabilityCurve.getValue(model, subPeriodStartTime)) - Math.log(survivalProbabilityCurve.getValue(model, subPeriodEndTime))) / (subPeriodEndTime - subPeriodStartTime);
accruedFactorJPM = hazardRateFactor * (1 / Math.pow(forwardInterestRateFactor + hazardRateFactor, 2) - ((subPeriodEndTime - subPeriodStartTime) / (forwardInterestRateFactor + hazardRateFactor) + 1 / Math.pow(forwardInterestRateFactor + hazardRateFactor, 2)) * (Math.exp(-(forwardInterestRateFactor + hazardRateFactor) * (subPeriodEndTime - subPeriodStartTime))));
value += -feePayment * subPeriodLength * previousDiscountFactor * previousSurvivalProbabilityFactor * accruedFactorJPM; // Expected accrued fee according to JPM model
value += Math.max(1.0 - recoveryRate,0) * (previousDiscountFactor * previousSurvivalProbabilityFactor - discountFactor * survivalProbabilityFactor) * hazardRateFactor / (hazardRateFactor + forwardInterestRateFactor); // Adjusted Recovery payment [Protection Buyer View]
}
}
else {
value += -feePayment * periodLength * discountFactor * survivalProbabilityFactor; // Fee payment [Protection Buyer View]
value += -feePayment * periodLength * previousDiscountFactor * previousSurvivalProbabilityFactor * accruedFactorJPM; // Expected accrued fee according to JPM model
value += Math.max(1.0 - recoveryRate,0) * (previousDiscountFactor * previousSurvivalProbabilityFactor - discountFactor * survivalProbabilityFactor) * hazardRateFactor / (hazardRateFactor + forwardInterestRateFactor); // Adjusted Recovery payment [Protection Buyer View]
}
break;
case JPM_NOACCFEE:
if (useFinerDiscretization) {
value += -feePayment * periodLength * discountFactor * survivalProbabilityFactor;
// JPM Model on jointTimeDiscretization
final int startIndex = Arrays.binarySearch(jointTimeDiscretization, periodStartTime);
final int endIndex = Arrays.binarySearch(jointTimeDiscretization, periodEndTime);
// Loop over subperiods
for (int subTimeIndex = startIndex; subTimeIndex < endIndex; subTimeIndex++) {
final double subPeriodStartTime = jointTimeDiscretization[subTimeIndex];
final double subPeriodEndTime = jointTimeDiscretization[subTimeIndex + 1];
discountFactor = discountCurve.getDiscountFactor(model, subPeriodEndTime);
previousDiscountFactor = discountCurve.getDiscountFactor(model, subPeriodStartTime);
survivalProbabilityFactor = survivalProbabilityCurve.getValue(model, subPeriodEndTime);
previousSurvivalProbabilityFactor = survivalProbabilityCurve.getValue(model, subPeriodStartTime);
forwardInterestRateFactor = (Math.log(discountCurve.getValue(model, subPeriodStartTime)) - Math.log(discountCurve.getValue(model, subPeriodEndTime))) / (subPeriodEndTime - subPeriodStartTime);
hazardRateFactor = (Math.log(survivalProbabilityCurve.getValue(model, subPeriodStartTime)) - Math.log(survivalProbabilityCurve.getValue(model, subPeriodEndTime))) / (subPeriodEndTime - subPeriodStartTime);
value += Math.max(1.0 - recoveryRate,0) * (previousDiscountFactor * previousSurvivalProbabilityFactor - discountFactor * survivalProbabilityFactor) * hazardRateFactor / (hazardRateFactor + forwardInterestRateFactor); // Adjusted Recovery payment [Protection Buyer View]
}
}
else{
value += -feePayment * periodLength * discountFactor * survivalProbabilityFactor; // Fee payment [Protection Buyer View]
value += Math.max(1.0 - recoveryRate,0) * (previousDiscountFactor * previousSurvivalProbabilityFactor - discountFactor * survivalProbabilityFactor) * hazardRateFactor / (hazardRateFactor + forwardInterestRateFactor); // Adjusted Recovery payment [Protection Buyer View]
}
break;
default:
throw new UnsupportedOperationException("Unknown valuation model: " + valuationModel);
}
}
return value / discountCurve.getDiscountFactor(model, evaluationTime);
}
/**
* Calculates the conventional CDS spread, i.e. the fee payment such that the CDS is valued at 0 (and no upfront).
* Treats conventional CDS spread as a FIXED fee, not floating.
*
* @param evaluationTime Evaluation time of the pricing.
* @param calibratedModelJPM Analytic Model, within the CDS is priced.
* @return The conventional CDS spread.
*/
public double getConventionalSpread( double evaluationTime, AnalyticModel calibratedModelJPM ){
final ForwardCurve forwardCurveInterpolation = calibratedModelJPM.getForwardCurve(forwardCurveName);
if(forwardCurveInterpolation == null && forwardCurveName != null && forwardCurveName.length() > 0) {
throw new IllegalArgumentException("No forward curve with name '" + forwardCurveName + "' was found in the model:\n" + calibratedModelJPM.toString());
}
final DiscountCurve discountCurveInterpolation = calibratedModelJPM.getDiscountCurve(discountCurveName);
if(discountCurveInterpolation == null) {
throw new IllegalArgumentException("No discount curve with name '" + discountCurveName + "' was found in the model:\n" + calibratedModelJPM.toString());
}
final Curve survivalProbabilityCurve = calibratedModelJPM.getCurve(survivalProbabilityCurveName);
if(survivalProbabilityCurve == null) {
throw new IllegalArgumentException("No survival probability curve with name '" + survivalProbabilityCurveName + "' was found in the model:\n" + calibratedModelJPM.toString());
}
final Curve recoveryRateCurve = calibratedModelJPM.getCurve(recoveryRateCurveName);
if(recoveryRateCurve == null) {
throw new IllegalArgumentException("No recovery rate curve with name '" + recoveryRateCurveName + "' was found in the model:\n" + calibratedModelJPM.toString());
}
double valueFloatingLeg = 0.0;
double valueFixedLeg = 0.0;
for(int periodIndex=0; periodIndex < schedule.getNumberOfPeriods(); periodIndex++){
final double paymentDate = schedule.getPayment(periodIndex);
final double periodLength = schedule.getPeriodLength(periodIndex);
final double discountFactor = paymentDate > evaluationTime ? discountCurveInterpolation.getDiscountFactor(calibratedModelJPM, paymentDate) : 0.0;
final double survivalProbabilityFactor = paymentDate > evaluationTime ? survivalProbabilityCurve.getValue(calibratedModelJPM, paymentDate) : 0.0;
valueFixedLeg += periodLength * discountFactor * survivalProbabilityFactor;
double previousPaymentDate = 0 ;
if(periodIndex>0) {
previousPaymentDate = schedule.getPayment(periodIndex-1);
}
final double previousSurvivalProbabilityFactor = previousPaymentDate > evaluationTime ? survivalProbabilityCurve.getValue(calibratedModelJPM, previousPaymentDate) : 1.0;
valueFloatingLeg += (1.0 - recoveryRateCurve.getValue(calibratedModelJPM,paymentDate)) * discountFactor * (previousSurvivalProbabilityFactor- survivalProbabilityFactor);
}
final double conventionalSpread = valueFloatingLeg/ valueFixedLeg;
return conventionalSpread;
}
/**
* Returns the CDS fee payment of the period with the given index. The analytic model is needed in case of a floating fee.
*
* @param periodIndex The index of the period of interest.
* @param model The model under which the product is valued.
* @return The value of the fee payment in the given period.
*/
public double getFeePayment(int periodIndex, AnalyticModel model) {
final ForwardCurve forwardCurveInterpolation = model.getForwardCurve(forwardCurveName);
if(forwardCurveInterpolation == null && forwardCurveName != null && forwardCurveName.length() > 0) {
throw new IllegalArgumentException("No forward curve with name '" + forwardCurveName + "' was found in the model:\n" + model.toString());
}
final double periodLength = schedule.getPeriodLength(periodIndex);
double couponPayment = fixedFee;
if(forwardCurveInterpolation != null ) {
couponPayment = floatingFeeSpread+forwardCurveInterpolation.getForward(model, schedule.getFixing(periodIndex));
}
return couponPayment*periodLength;
}
/**
* Returns the accrued fee of the CDS for a given date.
*
* @param date The date of interest.
* @param model The model under which the product is valued.
* @return The accrued fee.
*/
public double getAccruedFee(LocalDate date, AnalyticModel model) {
final int periodIndex=schedule.getPeriodIndex(date);
final Period period=schedule.getPeriod(periodIndex);
final DayCountConvention dcc= schedule.getDaycountconvention();
final double accruedFee = getFeePayment(periodIndex, model)*(dcc.getDaycountFraction(period.getPeriodStart(), date))/schedule.getPeriodLength(periodIndex);
return accruedFee;
}
/**
* Returns the accrued interest of the bond for a given time.
*
* @param time The time of interest as double.
* @param model The model under which the product is valued.
* @return The accrued interest.
*/
public double getAccruedFee(double time, AnalyticModelFromCurvesAndVols model) {
final LocalDate date= FloatingpointDate.getDateFromFloatingPointDate(schedule.getReferenceDate(), time);
return getAccruedFee(date, model);
}
public Schedule getSchedule() {
return schedule;
}
public String getDiscountCurveName() {
return discountCurveName;
}
public String getForwardCurveName() {
return forwardCurveName;
}
public String getSurvivalProbabilityCurveName() {
return survivalProbabilityCurveName;
}
public String getRecoveryRateCurveName() {
return recoveryRateCurveName;
}
public double getFixedFee() {
return fixedFee;
}
public double getFloatingFeeSpread() {
return floatingFeeSpread;
}
public double getUpfrontPayment() {
return upfrontPayment;
}
public LocalDate getTradeDate() { return tradeDate; }
public ValuationModel getValuationModel() { return valuationModel; }
public DirtyCleanPrice getDirtyCleanPrice() { return dirtyCleanPrice; }
public boolean isUseFinerDiscretization() { return useFinerDiscretization; }
@Override
public String toString() {
return "CouponBond [ScheduleFromPeriods=" + schedule
+ ", discountCurveName=" + discountCurveName
+ ", forwardCurveName=" + forwardCurveName
+ ", survivalProbabilityCurveName=" + survivalProbabilityCurveName
+ ", recoveryRateCurve=" + recoveryRateCurveName
+ ", fixedFee=" + fixedFee
+ ", floatingFeeSpread=" + floatingFeeSpread
+ ", upfrontPayment=" + upfrontPayment
+ ", tradeDate=" + tradeDate
+ ", pricingModel=" + valuationModel
+ ", dirtyCleanPrice=" + dirtyCleanPrice
+ ", useFinerDiscretization=" + useFinerDiscretization + "]";
}
public enum ValuationModel{
DISCRETE,
JPM,
JPM_NOACCFEE
}
public enum DirtyCleanPrice {
CLEAN,
DIRTY,
}
}