final double[] times = PREMIUM_LEG_SCHEDULE_CALCULATOR.convertTenorsToDoubles(calibrationTenors, valuationDate, ACT_365);
final DoublesCurve spreadCurve = InterpolatedDoublesCurve.fromSorted(times, marketSpreads, INTERPOLATOR);
final NormalDistribution normal = new NormalDistribution(0.0, 1.0);
double presentValue = 0.0;
double frontendProtection = 0.0;
// ----------------------------------------------------------------------------------------------------------------------------------------
// Create a copy of the underlying CDS for the purposes of calibration of the hazard rate term structure
final LegacyVanillaCreditDefaultSwapDefinition underlyingCalibrationCDS = (LegacyVanillaCreditDefaultSwapDefinition) cdsSwaption.getUnderlyingCDS();
// Build a hazard rate curve object based on the input market data
//final HazardRateCurve calibratedHazardRateCurve = creditDefaultSwap.calibrateHazardRateCurve(valuationDate, underlyingCalibrationCDS, calibrationTenors, marketSpreads, yieldCurve);
final HazardRateCurve calibratedHazardRateCurve = cdsCalibrator.isdaCalibrateHazardRateCurve(valuationDate, underlyingCalibrationCDS, calibrationTenors, marketSpreads, yieldCurve);
// ----------------------------------------------------------------------------------------------------------------------------------------
// Get the underlying CDS in the swaption contract (don't really need to do this if we fix the LegacyVanilla issue above)
final CreditDefaultSwapDefinition underlyingCDS = cdsSwaption.getUnderlyingCDS();
CreditDefaultSwapDefinition shortCDS = cdsSwaption.getUnderlyingCDS();
shortCDS = shortCDS.withStartDate(cdsSwaption.getStartDate());
shortCDS = shortCDS.withEffectiveDate(cdsSwaption.getStartDate().plusDays(1));
shortCDS = shortCDS.withMaturityDate(cdsSwaption.getOptionExerciseDate());
// Generate the cashflow schedule for the (forward) premium leg
final ZonedDateTime[] underlyingCDSPremiumLegSchedule = PREMIUM_LEG_SCHEDULE_CALCULATOR.constructCreditDefaultSwapPremiumLegSchedule(underlyingCDS);
final ZonedDateTime[] shortCDSPremiumLegSchedule = PREMIUM_LEG_SCHEDULE_CALCULATOR.constructCreditDefaultSwapPremiumLegSchedule(shortCDS);
// Get the option expiry date
final ZonedDateTime optionExpiryDate = cdsSwaption.getOptionExerciseDate();
// Get the maturity date of the underlying CDS
final ZonedDateTime cdsMaturityDate = cdsSwaption.getUnderlyingCDS().getMaturityDate();
// Get the option strike
final double optionStrike = cdsSwaption.getOptionStrike() / 10000.0;
// Calculate the remaining time to option expiry (as a double)
final double optionExpiryTime = TimeCalculator.getTimeBetween(valuationDate, cdsSwaption.getOptionExerciseDate());
// ----------------------------------------------------------------------------------------------------------------------------------------
// If we are not exactly at the option expiry time ...
if (Double.doubleToLongBits(optionExpiryTime) != 0) {
// ... the option still has some value (and the calculation shouldn't fall over)
// Calculate the forward risky dV01 as seen at the valuation date for the period [optionExpiryDate, cdsMaturityDate]
final double riskydV01 = calculateForwardRiskydV01(
valuationDate,
optionExpiryDate,
cdsMaturityDate,
cdsSwaption,
underlyingCDSPremiumLegSchedule,
yieldCurve,
calibratedHazardRateCurve/*hazardRateCurve*/);
// Calculate the forward spread as seen at the valuation date for the period [optionExpiryDate, cdsMaturityDate]
final double forwardSpread = calculateForwardSpread(
valuationDate,
optionExpiryDate,
cdsMaturityDate,
cdsSwaption,
underlyingCDSPremiumLegSchedule,
shortCDSPremiumLegSchedule,
spreadCurve,
yieldCurve,
calibratedHazardRateCurve/*hazardRateCurve*/) / 10000.0;
// ----------------------------------------------------------------------------------------------------------------------------------------
// Calculate the value of the CDS swaption
final double d1 = (Math.log(forwardSpread / optionStrike) + 0.5 * sigma * sigma * optionExpiryTime) / (sigma * Math.sqrt(optionExpiryTime));
final double d2 = (Math.log(forwardSpread / optionStrike) - 0.5 * sigma * sigma * optionExpiryTime) / (sigma * Math.sqrt(optionExpiryTime));
if (cdsSwaption.isPayer()) {
presentValue = riskydV01 * (forwardSpread * normal.getCDF(d1) - optionStrike * normal.getCDF(d2));
} else {
presentValue = riskydV01 * (optionStrike * normal.getCDF(-d2) - forwardSpread * normal.getCDF(-d1));
}
// Do we need to add the front end protection
if (!cdsSwaption.isKnockOut()) {
frontendProtection = calculateFrontendProtection(valuationDate, cdsSwaption, yieldCurve, calibratedHazardRateCurve/*hazardRateCurve*/);