public void testParity() { // Testing put-call parity for capped-floored CMS coupons CommonVars vars = new CommonVars(); List <Handle <SwaptionVolatilityStructure> > swaptionVols = new List <Handle <SwaptionVolatilityStructure> >(); swaptionVols.Add(vars.atmVol); swaptionVols.Add(vars.SabrVolCube1); swaptionVols.Add(vars.SabrVolCube2); SwapIndex swapIndex = new EuriborSwapIsdaFixA(new Period(10, TimeUnit.Years), vars.iborIndex.forwardingTermStructure()); Date startDate = vars.termStructure.link.referenceDate() + new Period(20, TimeUnit.Years); Date paymentDate = startDate + new Period(1, TimeUnit.Years); Date endDate = paymentDate; double nominal = 1.0; double?infiniteCap = null; double?infiniteFloor = null; double gearing = 1.0; double spread = 0.0; double discount = vars.termStructure.link.discount(paymentDate); CappedFlooredCmsCoupon swaplet = new CappedFlooredCmsCoupon(nominal, paymentDate, startDate, endDate, swapIndex.fixingDays(), swapIndex, gearing, spread, infiniteCap, infiniteFloor, startDate, endDate, vars.iborIndex.dayCounter()); for (double strike = .02; strike < .12; strike += 0.05) { CappedFlooredCmsCoupon caplet = new CappedFlooredCmsCoupon(nominal, paymentDate, startDate, endDate, swapIndex.fixingDays(), swapIndex, gearing, spread, strike, infiniteFloor, startDate, endDate, vars.iborIndex.dayCounter()); CappedFlooredCmsCoupon floorlet = new CappedFlooredCmsCoupon(nominal, paymentDate, startDate, endDate, swapIndex.fixingDays(), swapIndex, gearing, spread, infiniteCap, strike, startDate, endDate, vars.iborIndex.dayCounter()); for (int i = 0; i < swaptionVols.Count; ++i) { for (int j = 0; j < vars.yieldCurveModels.Count; ++j) { vars.numericalPricers[j].setSwaptionVolatility(swaptionVols[i]); vars.analyticPricers[j].setSwaptionVolatility(swaptionVols[i]); List <CmsCouponPricer> pricers = new List <CmsCouponPricer>(2); pricers.Add(vars.numericalPricers[j]); pricers.Add(vars.analyticPricers[j]); for (int k = 0; k < pricers.Count; ++k) { swaplet.setPricer(pricers[k]); caplet.setPricer(pricers[k]); floorlet.setPricer(pricers[k]); double swapletPrice = swaplet.price(vars.termStructure) + nominal * swaplet.accrualPeriod() * strike * discount; double capletPrice = caplet.price(vars.termStructure); double floorletPrice = floorlet.price(vars.termStructure); double difference = Math.Abs(capletPrice + floorletPrice - swapletPrice); double tol = 2.0e-5; bool linearTsr = k == 0 && j == vars.yieldCurveModels.Count - 1; if (linearTsr) { tol = 1.0e-7; } if (difference > tol) { QAssert.Fail("\nCoupon payment date: " + paymentDate + "\nCoupon start date: " + startDate + "\nCoupon gearing: " + (gearing) + "\nCoupon swap index: " + swapIndex.name() + "\nCoupon spread: " + (spread) + "\nstrike: " + (strike) + "\nCoupon DayCounter: " + vars.iborIndex.dayCounter() + "\nYieldCurve Model: " + vars.yieldCurveModels[j] + (k == 0 ? "\nNumerical Pricer" : "\nAnalytic Pricer") + (linearTsr ? " (Linear TSR Model)" : "") + "\nSwaplet price: " + (swapletPrice) + "\nCaplet price: " + (capletPrice) + "\nFloorlet price: " + (floorletPrice) + "\ndifference: " + difference + "\ntolerance: " + (tol)); } } } } } }
public void testCouponPricing() { TestData d = new TestData(); double tol = 1E-6; // abs tolerance coupon rate SwapIndex cms10y = new EuriborSwapIsdaFixA(new Period(10, TimeUnit.Years), d.yts2, d.yts2); SwapIndex cms2y = new EuriborSwapIsdaFixA(new Period(2, TimeUnit.Years), d.yts2, d.yts2); SwapSpreadIndex cms10y2y = new SwapSpreadIndex("cms10y2y", cms10y, cms2y); Date valueDate = cms10y2y.valueDate(d.refDate); Date payDate = valueDate + new Period(1, TimeUnit.Years); CmsCoupon cpn1a = new CmsCoupon(10000.0, payDate, valueDate, payDate, cms10y.fixingDays(), cms10y, 1.0, 0.0, null, null, new Actual360(), false); CmsCoupon cpn1b = new CmsCoupon(10000.0, payDate, valueDate, payDate, cms2y.fixingDays(), cms2y, 1.0, 0.0, null, null, new Actual360(), false); CmsSpreadCoupon cpn1 = new CmsSpreadCoupon( 10000.0, payDate, valueDate, payDate, cms10y2y.fixingDays(), cms10y2y, 1.0, 0.0, null, null, new Actual360(), false); QAssert.IsTrue(cpn1.fixingDate() == d.refDate); cpn1a.setPricer(d.cmsPricerLn); cpn1b.setPricer(d.cmsPricerLn); cpn1.setPricer(d.cmsspPricerLn); QAssert.IsTrue(cpn1.rate() == cpn1a.rate() - cpn1b.rate()); cms10y.addFixing(d.refDate, 0.05); QAssert.IsTrue(cpn1.rate() == cpn1a.rate() - cpn1b.rate()); cms2y.addFixing(d.refDate, 0.03); QAssert.IsTrue(cpn1.rate() == cpn1a.rate() - cpn1b.rate()); IndexManager.Instance.clearHistories(); CmsCoupon cpn2a = new CmsCoupon(10000.0, new Date(23, Month.February, 2029), new Date(23, Month.February, 2028), new Date(23, Month.February, 2029), 2, cms10y, 1.0, 0.0, null, null, new Actual360(), false); CmsCoupon cpn2b = new CmsCoupon(10000.0, new Date(23, Month.February, 2029), new Date(23, Month.February, 2028), new Date(23, Month.February, 2029), 2, cms2y, 1.0, 0.0, null, null, new Actual360(), false); CappedFlooredCmsSpreadCoupon plainCpn = new CappedFlooredCmsSpreadCoupon( new Date(23, Month.February, 2029), 10000.0, new Date(23, Month.February, 2028), new Date(23, Month.February, 2029), 2, cms10y2y, 1.0, 0.0, null, null, null, null, new Actual360(), false); CappedFlooredCmsSpreadCoupon cappedCpn = new CappedFlooredCmsSpreadCoupon( new Date(23, Month.February, 2029), 10000.0, new Date(23, Month.February, 2028), new Date(23, Month.February, 2029), 2, cms10y2y, 1.0, 0.0, 0.03, null, null, null, new Actual360(), false); CappedFlooredCmsSpreadCoupon flooredCpn = new CappedFlooredCmsSpreadCoupon( new Date(23, Month.February, 2029), 10000.0, new Date(23, Month.February, 2028), new Date(23, Month.February, 2029), 2, cms10y2y, 1.0, 0.0, null, 0.01, null, null, new Actual360(), false); CappedFlooredCmsSpreadCoupon collaredCpn = new CappedFlooredCmsSpreadCoupon( new Date(23, Month.February, 2029), 10000.0, new Date(23, Month.February, 2028), new Date(23, Month.February, 2029), 2, cms10y2y, 1.0, 0.0, 0.03, 0.01, null, null, new Actual360(), false); cpn2a.setPricer(d.cmsPricerLn); cpn2b.setPricer(d.cmsPricerLn); plainCpn.setPricer(d.cmsspPricerLn); cappedCpn.setPricer(d.cmsspPricerLn); flooredCpn.setPricer(d.cmsspPricerLn); collaredCpn.setPricer(d.cmsspPricerLn); QAssert.IsTrue( Math.Abs(plainCpn.rate() - mcReferenceValue(cpn2a, cpn2b, Double.MaxValue, -Double.MaxValue, d.swLn, d.correlation.currentLink().value())) < tol); QAssert.IsTrue( Math.Abs(cappedCpn.rate() - mcReferenceValue(cpn2a, cpn2b, 0.03, -Double.MaxValue, d.swLn, d.correlation.currentLink().value())) < tol); QAssert.IsTrue( Math.Abs(flooredCpn.rate() - mcReferenceValue(cpn2a, cpn2b, Double.MaxValue, 0.01, d.swLn, d.correlation.currentLink().value())) < tol); QAssert.IsTrue( Math.Abs(collaredCpn.rate() - mcReferenceValue(cpn2a, cpn2b, 0.03, 0.01, d.swLn, d.correlation.currentLink().value())) < tol); cpn2a.setPricer(d.cmsPricerSln); cpn2b.setPricer(d.cmsPricerSln); plainCpn.setPricer(d.cmsspPricerSln); cappedCpn.setPricer(d.cmsspPricerSln); flooredCpn.setPricer(d.cmsspPricerSln); collaredCpn.setPricer(d.cmsspPricerSln); QAssert.IsTrue( Math.Abs(plainCpn.rate() - mcReferenceValue(cpn2a, cpn2b, Double.MaxValue, -Double.MaxValue, d.swSln, d.correlation.currentLink().value())) < tol); QAssert.IsTrue( Math.Abs(cappedCpn.rate() - mcReferenceValue(cpn2a, cpn2b, 0.03, -Double.MaxValue, d.swSln, d.correlation.currentLink().value())) < tol); QAssert.IsTrue( Math.Abs(flooredCpn.rate() - mcReferenceValue(cpn2a, cpn2b, Double.MaxValue, 0.01, d.swSln, d.correlation.currentLink().value())) < tol); QAssert.IsTrue( Math.Abs(collaredCpn.rate() - mcReferenceValue(cpn2a, cpn2b, 0.03, 0.01, d.swSln, d.correlation.currentLink().value())) < tol); cpn2a.setPricer(d.cmsPricerN); cpn2b.setPricer(d.cmsPricerN); plainCpn.setPricer(d.cmsspPricerN); cappedCpn.setPricer(d.cmsspPricerN); flooredCpn.setPricer(d.cmsspPricerN); collaredCpn.setPricer(d.cmsspPricerN); QAssert.IsTrue( Math.Abs(plainCpn.rate() - mcReferenceValue(cpn2a, cpn2b, Double.MaxValue, -Double.MaxValue, d.swN, d.correlation.currentLink().value())) < tol); QAssert.IsTrue( Math.Abs(cappedCpn.rate() - mcReferenceValue(cpn2a, cpn2b, 0.03, -Double.MaxValue, d.swN, d.correlation.currentLink().value())) < tol); QAssert.IsTrue(Math.Abs(flooredCpn.rate() - mcReferenceValue(cpn2a, cpn2b, Double.MaxValue, 0.01, d.swN, d.correlation.currentLink().value())) < tol); QAssert.IsTrue(Math.Abs(collaredCpn.rate() - mcReferenceValue(cpn2a, cpn2b, 0.03, 0.01, d.swN, d.correlation.currentLink().value())) < tol); }