//! Conventional/standard upfront-to-spread conversion /*! Under a standard ISDA model and a set of standardised * instrument characteristics, it is the running only quoted * spread that will make a CDS contract have an NPV of 0 when * quoted for that running only spread. Refer to: "ISDA * Standard CDS converter specification." May 2009. * * The conventional recovery rate to apply in the calculation * is as specified by ISDA, not necessarily equal to the * market-quoted one. It is typically 0.4 for SeniorSec and * 0.2 for subordinate. * * \note The conversion employs a flat hazard rate. As a result, * you will not recover the market quotes. * * \note This method performs the calculation with the * instrument characteristics. It will coincide with * the ISDA calculation if your object has the standard * characteristics. Notably: * - The calendar should have no bank holidays, just * weekends. * - The yield curve should be LIBOR piecewise ant * in fwd rates, with a discount factor of 1 on the * calculation date, which coincides with the trade * date. * - Convention should be Following for yield curve and * contract cashflows. * - The CDS should pay accrued and mature on standard * IMM dates, settle on trade date +1 and upfront * settle on trade date +3. */ public double?conventionalSpread(double conventionalRecovery, Handle <YieldTermStructure> discountCurve, DayCounter dayCounter) { double flatHazardRate = impliedHazardRate(0.0, discountCurve, dayCounter, conventionalRecovery); Handle <DefaultProbabilityTermStructure> probability = new Handle <DefaultProbabilityTermStructure>( new FlatHazardRate(0, new WeekendsOnly(), flatHazardRate, dayCounter)); MidPointCdsEngine engine = new MidPointCdsEngine(probability, conventionalRecovery, discountCurve, true); setupArguments(engine.getArguments()); engine.calculate(); CreditDefaultSwap.Results results = engine.getResults() as CreditDefaultSwap.Results; return(results.fairSpread); }
/// <summary> /// Implied hazard rate calculation /// </summary> /// <remarks> /// This method performs the calculation with the /// instrument characteristics. It will coincide with /// the ISDA calculation if your object has the standard /// characteristics. Notably: /// - The calendar should have no bank holidays, just /// weekends. /// - The yield curve should be LIBOR piecewise ant /// in fwd rates, with a discount factor of 1 on the /// calculation date, which coincides with the trade /// date. /// - Convention should be Following for yield curve and /// contract cashflows. /// - The CDS should pay accrued and mature on standard /// IMM dates, settle on trade date +1 and upfront /// settle on trade date +3. /// </remarks> /// <param name="targetNPV"></param> /// <param name="discountCurve"></param> /// <param name="dayCounter"></param> /// <param name="recoveryRate"></param> /// <param name="accuracy"></param> /// <returns></returns> public double impliedHazardRate(double targetNPV, Handle <YieldTermStructure> discountCurve, DayCounter dayCounter, double recoveryRate = 0.4, double accuracy = 1.0e-6, PricingModel model = PricingModel.Midpoint) { SimpleQuote flatRate = new SimpleQuote(0.0); Handle <DefaultProbabilityTermStructure> probability = new Handle <DefaultProbabilityTermStructure>( new FlatHazardRate(0, new WeekendsOnly(), new Handle <Quote>(flatRate), dayCounter)); IPricingEngine engine = null; switch (model) { case PricingModel.Midpoint: engine = new MidPointCdsEngine(probability, recoveryRate, discountCurve); break; case PricingModel.ISDA: engine = new IsdaCdsEngine(probability, recoveryRate, discountCurve); break; default: Utils.QL_FAIL("unknown CDS pricing model: " + model); break; } setupArguments(engine.getArguments()); CreditDefaultSwap.Results results = engine.getResults() as CreditDefaultSwap.Results; ObjectiveFunction f = new ObjectiveFunction(targetNPV, flatRate, engine, results); double guess = runningSpread_ / (1 - recoveryRate) * 365.0 / 360.0; double step = guess * 0.1; return(new Brent().solve(f, accuracy, guess, step)); }
public double impliedHazardRate(double targetNPV, Handle <YieldTermStructure> discountCurve, DayCounter dayCounter, double recoveryRate = 0.4, double accuracy = 1.0e-6) { SimpleQuote flatRate = new SimpleQuote(0.0); Handle <DefaultProbabilityTermStructure> probability = new Handle <DefaultProbabilityTermStructure>( new FlatHazardRate(0, new WeekendsOnly(), new Handle <Quote>(flatRate), dayCounter)); MidPointCdsEngine engine = new MidPointCdsEngine(probability, recoveryRate, discountCurve); setupArguments(engine.getArguments()); CreditDefaultSwap.Results results = engine.getResults() as CreditDefaultSwap.Results; ObjectiveFunction f = new ObjectiveFunction(targetNPV, flatRate, engine, results); double guess = 0.001; double step = guess * 0.1; return(new Brent().solve(f, accuracy, guess, step)); }
public void testFairUpfront() { // Testing fair-upfront calculation for credit-default swaps... SavedSettings backup = new SavedSettings(); // Initialize curves Calendar calendar = new TARGET(); Date today = calendar.adjust(Date.Today); Settings.setEvaluationDate(today); Handle<Quote> hazardRate = new Handle<Quote>(new SimpleQuote(0.01234)); RelinkableHandle<DefaultProbabilityTermStructure> probabilityCurve = new RelinkableHandle<DefaultProbabilityTermStructure>(); probabilityCurve.linkTo(new FlatHazardRate(0, calendar, hazardRate, new Actual360())); RelinkableHandle<YieldTermStructure> discountCurve = new RelinkableHandle<YieldTermStructure>(); discountCurve.linkTo(new FlatForward(today,0.06,new Actual360())); // Build the schedule Date issueDate = today; Date maturity = calendar.advance(issueDate, 10, TimeUnit.Years); BusinessDayConvention convention = BusinessDayConvention.Following; Schedule schedule = new MakeSchedule().from(issueDate) .to(maturity) .withFrequency(Frequency.Quarterly) .withCalendar(calendar) .withTerminationDateConvention(convention) .withRule(DateGeneration.Rule.TwentiethIMM).value(); // Build the CDS double fixedRate = 0.05; double upfront = 0.001; DayCounter dayCount = new Actual360(); double notional = 10000.0; double recoveryRate = 0.4; IPricingEngine engine = new MidPointCdsEngine(probabilityCurve, recoveryRate, discountCurve, true); CreditDefaultSwap cds = new CreditDefaultSwap(Protection.Side.Seller, notional, upfront, fixedRate, schedule, convention, dayCount, true, true); cds.setPricingEngine(engine); double fairUpfront = cds.fairUpfront(); CreditDefaultSwap fairCds = new CreditDefaultSwap(Protection.Side.Seller, notional, fairUpfront, fixedRate, schedule, convention, dayCount, true, true); fairCds.setPricingEngine(engine); double fairNPV = fairCds.NPV(); double tolerance = 1e-10; if (Math.Abs(fairNPV) > tolerance) Assert.Fail( "Failed to reproduce null NPV with calculated fair upfront\n" + " calculated upfront: " + fairUpfront + "\n" + " calculated NPV: " + fairNPV); // same with null upfront to begin with upfront = 0.0; CreditDefaultSwap cds2 = new CreditDefaultSwap(Protection.Side.Seller, notional, upfront, fixedRate, schedule, convention, dayCount, true, true); cds2.setPricingEngine(engine); fairUpfront = cds2.fairUpfront(); CreditDefaultSwap fairCds2 = new CreditDefaultSwap(Protection.Side.Seller, notional, fairUpfront, fixedRate, schedule, convention, dayCount, true, true); fairCds2.setPricingEngine(engine); fairNPV = fairCds2.NPV(); if (Math.Abs(fairNPV) > tolerance) Assert.Fail( "Failed to reproduce null NPV with calculated fair upfront\n" + " calculated upfront: " + fairUpfront + "\n" + " calculated NPV: " + fairNPV); }