public void testIntraday() { // Testing intraday information of dates Date d1 = new Date(12, Month.February, 2015, 10, 45, 12, 234); QAssert.IsTrue(d1.year() == 2015, "failed to reproduce year"); QAssert.IsTrue(d1.month() == (int)Month.February, "failed to reproduce month"); QAssert.IsTrue(d1.Day == 12, "failed to reproduce day"); QAssert.IsTrue(d1.hours == 10, "failed to reproduce hour of day"); QAssert.IsTrue(d1.minutes == 45, "failed to reproduce minute of hour"); QAssert.IsTrue(d1.seconds == 12, "failed to reproduce second of minute"); QAssert.IsTrue(d1.milliseconds == 234, "failed to reproduce number of milliseconds"); QAssert.IsTrue(d1.fractionOfSecond == 0.234, "failed to reproduce fraction of second"); Date d2 = new Date(28, Month.February, 2015, 4, 52, 57, 999); QAssert.IsTrue(d2.year() == 2015, "failed to reproduce year"); QAssert.IsTrue(d2.month() == (int)Month.February, "failed to reproduce month"); QAssert.IsTrue(d2.Day == 28, "failed to reproduce day"); QAssert.IsTrue(d2.hours == 4, "failed to reproduce hour of day"); QAssert.IsTrue(d2.minutes == 52, "failed to reproduce minute of hour"); QAssert.IsTrue(d2.seconds == 57, "failed to reproduce second of minute"); QAssert.IsTrue(d2.milliseconds == 999, "failed to reproduce number of milliseconds"); // test daysBetween when d2 time part is earlier in the day than d1 time part. d1 = new Date(new DateTime(2016, 1, 1, 18, 0, 0)); d2 = new Date(new DateTime(2016, 1, 2, 0, 0, 0)); QAssert.IsTrue(Date.daysBetween(d1, d2) == 0.25, "failed daysBetween"); }
public void testIntraday() { // Testing intraday behavior of day counter Date d1 = new Date(12, Month.February, 2015); Date d2 = new Date(14, Month.February, 2015, 12, 34, 17, 1); double tol = 100 * Const.QL_EPSILON; DayCounter[] dayCounters = { new ActualActual(), new Actual365Fixed(), new Actual360() }; for (int i = 0; i < dayCounters.Length; ++i) { DayCounter dc = dayCounters[i]; double expected = ((12 * 60 + 34) * 60 + 17 + 0.001) * dc.yearFraction(d1, d1 + 1) / 86400 + dc.yearFraction(d1, d1 + 2); QAssert.IsTrue(Math.Abs(dc.yearFraction(d1, d2) - expected) < tol, "can not reproduce result for day counter " + dc.name()); QAssert.IsTrue(Math.Abs(dc.yearFraction(d2, d1) + expected) < tol, "can not reproduce result for day counter " + dc.name()); } }
public void zciisconsistency() { CommonVars common = new CommonVars(); ZeroCouponInflationSwap.Type ztype = ZeroCouponInflationSwap.Type.Payer; double nominal = 1000000.0; Date startDate = new Date(common.evaluationDate); Date endDate = new Date(25, Month.November, 2059); Calendar cal = new UnitedKingdom(); BusinessDayConvention paymentConvention = BusinessDayConvention.ModifiedFollowing; DayCounter dummyDC = null, dc = new ActualActual(); Period observationLag = new Period(2, TimeUnit.Months); double quote = 0.03714; ZeroCouponInflationSwap zciis = new ZeroCouponInflationSwap(ztype, nominal, startDate, endDate, cal, paymentConvention, dc, quote, common.ii, observationLag); // simple structure so simple pricing engine - most work done by index DiscountingSwapEngine dse = new DiscountingSwapEngine(common.nominalUK); zciis.setPricingEngine(dse); QAssert.IsTrue(Math.Abs(zciis.NPV()) < 1e-3, "zciis does not reprice to zero"); List <Date> oneDate = new List <Date>(); oneDate.Add(endDate); Schedule schOneDate = new Schedule(oneDate, cal, paymentConvention); CPISwap.Type stype = CPISwap.Type.Payer; double inflationNominal = nominal; double floatNominal = inflationNominal * Math.Pow(1.0 + quote, 50); bool subtractInflationNominal = true; double dummySpread = 0.0, dummyFixedRate = 0.0; int fixingDays = 0; Date baseDate = startDate - observationLag; double baseCPI = common.ii.fixing(baseDate); IborIndex dummyFloatIndex = new IborIndex(); CPISwap cS = new CPISwap(stype, floatNominal, subtractInflationNominal, dummySpread, dummyDC, schOneDate, paymentConvention, fixingDays, dummyFloatIndex, dummyFixedRate, baseCPI, dummyDC, schOneDate, paymentConvention, observationLag, common.ii, InterpolationType.AsIndex, inflationNominal); cS.setPricingEngine(dse); QAssert.IsTrue(Math.Abs(cS.NPV()) < 1e-3, "CPISwap as ZCIIS does not reprice to zero"); for (int i = 0; i < 2; i++) { double cs = cS.legNPV(i).GetValueOrDefault(); double z = zciis.legNPV(i).GetValueOrDefault(); QAssert.IsTrue(Math.Abs(cs - z) < 1e-3, "zciis leg does not equal CPISwap leg"); } // remove circular refernce common.hcpi.linkTo(null); }
public void cpicapfloorpricesurface() { // check inflation leg vs calculation directly from inflation TS CommonVars common = new CommonVars(); double nominal = 1.0; InterpolatedCPICapFloorTermPriceSurface <Bilinear> cpiSurf = new InterpolatedCPICapFloorTermPriceSurface <Bilinear>( nominal, common.baseZeroRate, common.observationLag, common.calendar, common.convention, common.dcZCIIS, common.hii, common.nominalUK, common.cStrikesUK, common.fStrikesUK, common.cfMaturitiesUK, common.cPriceUK, common.fPriceUK); // test code - note order of indices for (int i = 0; i < common.fStrikesUK.Count; i++) { double qK = common.fStrikesUK[i]; int nMat = common.cfMaturitiesUK.Count; for (int j = 0; j < nMat; j++) { Period t = common.cfMaturitiesUK[j]; double a = common.fPriceUK[i, j]; double b = cpiSurf.floorPrice(t, qK); Utils.QL_REQUIRE(Math.Abs(a - b) < 1e-7, () => "cannot reproduce cpi floor data from surface: " + a + " vs constructed = " + b); } } for (int i = 0; i < common.cStrikesUK.Count; i++) { double qK = common.cStrikesUK[i]; int nMat = common.cfMaturitiesUK.Count; for (int j = 0; j < nMat; j++) { Period t = common.cfMaturitiesUK[j]; double a = common.cPriceUK[i, j]; double b = cpiSurf.capPrice(t, qK); QAssert.IsTrue(Math.Abs(a - b) < 1e-7, "cannot reproduce cpi cap data from surface: " + a + " vs constructed = " + b); } } // remove circular refernce common.hcpi.linkTo(null); }
public void testEquals() { Vector vector1 = new Vector(Data); Vector vector2 = new Vector(Data); Vector vector3 = new Vector(4); QAssert.IsTrue(vector1.Equals(vector1)); QAssert.IsTrue(vector1.Equals(vector2)); QAssert.IsFalse(vector1.Equals(vector3)); QAssert.IsFalse(vector1.Equals(null)); QAssert.IsFalse(vector1.Equals(2)); }
public void testClosestIndex() { // Testing that the returned index is closest to the requested time List <double> test_times = new List <double> { 1.0, 2.0, 5.0 }; TimeGrid tg = new TimeGrid(test_times); int expected_index = 3; QAssert.IsTrue(tg.closestIndex(4) == expected_index, "Expected index: " + expected_index + ", which does not match " + "the returned index: " + tg.closestIndex(4)); }
public void testClosestTime() { // Testing that the returned time matches the requested index List <double> test_times = new List <double> { 1.0, 2.0, 5.0 }; TimeGrid tg = new TimeGrid(test_times); int expected_time = 5; QAssert.IsTrue(tg.closestTime(4).IsEqual(expected_time), "Expected time of: " + expected_time + ", which does not match " + "the returned time: " + tg.closestTime(4)); }
public void testCDS2015Convention() { // Testing CDS2015 semi-annual rolling convention //From September 20th 2016 to March 19th 2017 of the next Year, //end date is December 20th 2021 for a 5 year Swap Schedule s1 = new MakeSchedule().from(new Date(12, Month.December, 2016)) .to(new Date(12, Month.December, 2016) + new Period(5, TimeUnit.Years)) .withCalendar(new WeekendsOnly()) .withTenor(new Period(3, TimeUnit.Months)) .withConvention(BusinessDayConvention.ModifiedFollowing) .withTerminationDateConvention(BusinessDayConvention.Unadjusted) .withRule(DateGeneration.Rule.CDS2015).value(); QAssert.IsTrue(s1.startDate() == new Date(20, Month.September, 2016)); QAssert.IsTrue(s1.endDate() == new Date(20, Month.December, 2021)); Schedule s2 = new MakeSchedule().from(new Date(1, Month.March, 2017)) .to(new Date(1, Month.March, 2017) + new Period(5, TimeUnit.Years)) .withCalendar(new WeekendsOnly()) .withTenor(new Period(3, TimeUnit.Months)) .withConvention(BusinessDayConvention.ModifiedFollowing) .withTerminationDateConvention(BusinessDayConvention.Unadjusted) .withRule(DateGeneration.Rule.CDS2015).value(); QAssert.IsTrue(s2.startDate() == new Date(20, Month.December, 2016)); QAssert.IsTrue(s2.endDate() == new Date(20, Month.December, 2021)); //From March 20th 2017 to September 19th 2017 //end date is June 20th 2022 for a 5 year Swap Schedule s3 = new MakeSchedule().from(new Date(20, Month.March, 2017)) .to(new Date(20, Month.March, 2017) + new Period(5, TimeUnit.Years)) .withCalendar(new WeekendsOnly()) .withTenor(new Period(3, TimeUnit.Months)) .withConvention(BusinessDayConvention.ModifiedFollowing) .withTerminationDateConvention(BusinessDayConvention.Unadjusted) .withRule(DateGeneration.Rule.CDS2015).value(); QAssert.IsTrue(s3.startDate() == new Date(20, Month.March, 2017)); QAssert.IsTrue(s3.endDate() == new Date(20, Month.June, 2022)); }
public void testIsdaEngine() { // Testing ISDA engine calculations for credit-default swaps SavedSettings backup = new SavedSettings(); Date tradeDate = new Date(21, Month.May, 2009); Settings.setEvaluationDate(tradeDate); //build an ISDA compliant yield curve //data comes from Markit published rates List <RateHelper> isdaRateHelpers = new List <RateHelper>(); int[] dep_tenors = { 1, 2, 3, 6, 9, 12 }; double[] dep_quotes = { 0.003081, 0.005525, 0.007163, 0.012413, 0.014, 0.015488 }; for (int i = 0; i < dep_tenors.Length; i++) { isdaRateHelpers.Add(new DepositRateHelper(dep_quotes[i], new Period(dep_tenors[i], TimeUnit.Months), 2, new WeekendsOnly(), BusinessDayConvention.ModifiedFollowing, false, new Actual360()) ); } int[] swap_tenors = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 15, 20, 25, 30 }; double[] swap_quotes = { 0.011907, 0.01699, 0.021198, 0.02444, 0.026937, 0.028967, 0.030504, 0.031719, 0.03279, 0.034535, 0.036217, 0.036981, 0.037246, 0.037605 }; IborIndex isda_ibor = new IborIndex("IsdaIbor", new Period(3, TimeUnit.Months), 2, new USDCurrency(), new WeekendsOnly(), BusinessDayConvention.ModifiedFollowing, false, new Actual360()); for (int i = 0; i < swap_tenors.Length; i++) { isdaRateHelpers.Add(new SwapRateHelper(swap_quotes[i], new Period(swap_tenors[i], TimeUnit.Years), new WeekendsOnly(), Frequency.Semiannual, BusinessDayConvention.ModifiedFollowing, new Thirty360(), isda_ibor)); } RelinkableHandle <YieldTermStructure> discountCurve = new RelinkableHandle <YieldTermStructure>(); discountCurve.linkTo(new PiecewiseYieldCurve <Discount, LogLinear>(0, new WeekendsOnly(), isdaRateHelpers, new Actual365Fixed())); RelinkableHandle <DefaultProbabilityTermStructure> probabilityCurve = new RelinkableHandle <DefaultProbabilityTermStructure>(); Date[] termDates = { new Date(20, Month.June, 2010), new Date(20, Month.June, 2011), new Date(20, Month.June, 2012), new Date(20, Month.June, 2016), new Date(20, Month.June, 2019) }; double[] spreads = { 0.001, 0.1 }; double[] recoveries = { 0.2, 0.4 }; double[] markitValues = { 97798.29358, //0.001 97776.11889, //0.001 -914971.5977, //0.1 -894985.6298, //0.1 186921.3594, //0.001 186839.8148, //0.001 -1646623.672, //0.1 -1579803.626, //0.1 274298.9203, 274122.4725, -2279730.93, -2147972.527, 592420.2297, 591571.2294, -3993550.206, -3545843.418, 797501.1422, 795915.9787, -4702034.688, -4042340.999 }; #if !QL_USE_INDEXED_COUPON double tolerance = 1.0e-2; //TODO Check calculation , tolerance must be 1.0e-6; #else /* The risk-free curve is a bit off. We might skip the tests * altogether and rely on running them with indexed coupons * disabled, but leaving them can be useful anyway. */ double tolerance = 1.0e-3; #endif int l = 0; for (int i = 0; i < termDates.Length; i++) { for (int j = 0; j < 2; j++) { for (int k = 0; k < 2; k++) { CreditDefaultSwap quotedTrade = new MakeCreditDefaultSwap(termDates[i], spreads[j]) .withNominal(10000000.0).value(); double h = quotedTrade.impliedHazardRate(0.0, discountCurve, new Actual365Fixed(), recoveries[k], 1e-10, PricingModel.ISDA); probabilityCurve.linkTo(new FlatHazardRate(0, new WeekendsOnly(), h, new Actual365Fixed())); IsdaCdsEngine engine = new IsdaCdsEngine(probabilityCurve, recoveries[k], discountCurve); CreditDefaultSwap conventionalTrade = new MakeCreditDefaultSwap(termDates[i], 0.01) .withNominal(10000000.0) .withPricingEngine(engine).value(); double x = conventionalTrade.notional().Value; double y = conventionalTrade.fairUpfront(); double calculated = Math.Abs((x * y) - markitValues[l]); QAssert.IsTrue(calculated <= tolerance); l++; } } } }
public void testConventions() { // Testing business day conventions... SingleCase[] testCases = { // Following new SingleCase(new SouthAfrica(), BusinessDayConvention.Following, new Date(3, Month.February, 2015), new Period(1, TimeUnit.Months), false, new Date(3, Month.March, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.Following, new Date(3, Month.February, 2015), new Period(4, TimeUnit.Days), false, new Date(9, Month.February, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.Following, new Date(31, Month.January, 2015), new Period(1, TimeUnit.Months), true, new Date(27, Month.February, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.Following, new Date(31, Month.January, 2015), new Period(1, TimeUnit.Months), false, new Date(2, Month.March, 2015)), //ModifiedFollowing new SingleCase(new SouthAfrica(), BusinessDayConvention.ModifiedFollowing, new Date(3, Month.February, 2015), new Period(1, TimeUnit.Months), false, new Date(3, Month.March, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.ModifiedFollowing, new Date(3, Month.February, 2015), new Period(4, TimeUnit.Days), false, new Date(9, Month.February, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.ModifiedFollowing, new Date(31, Month.January, 2015), new Period(1, TimeUnit.Months), true, new Date(27, Month.February, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.ModifiedFollowing, new Date(31, Month.January, 2015), new Period(1, TimeUnit.Months), false, new Date(27, Month.February, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.ModifiedFollowing, new Date(25, Month.March, 2015), new Period(1, TimeUnit.Months), false, new Date(28, Month.April, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.ModifiedFollowing, new Date(7, Month.February, 2015), new Period(1, TimeUnit.Months), false, new Date(9, Month.March, 2015)), //Preceding new SingleCase(new SouthAfrica(), BusinessDayConvention.Preceding, new Date(3, Month.March, 2015), new Period(-1, TimeUnit.Months), false, new Date(3, Month.February, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.Preceding, new Date(3, Month.February, 2015), new Period(-2, TimeUnit.Days), false, new Date(30, Month.January, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.Preceding, new Date(1, Month.March, 2015), new Period(-1, TimeUnit.Months), true, new Date(30, Month.January, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.Preceding, new Date(1, Month.March, 2015), new Period(-1, TimeUnit.Months), false, new Date(30, Month.January, 2015)), //ModifiedPreceding new SingleCase(new SouthAfrica(), BusinessDayConvention.ModifiedPreceding, new Date(3, Month.March, 2015), new Period(-1, TimeUnit.Months), false, new Date(3, Month.February, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.ModifiedPreceding, new Date(3, Month.February, 2015), new Period(-2, TimeUnit.Days), false, new Date(30, Month.January, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.ModifiedPreceding, new Date(1, Month.March, 2015), new Period(-1, TimeUnit.Months), true, new Date(2, Month.February, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.ModifiedPreceding, new Date(1, Month.March, 2015), new Period(-1, TimeUnit.Months), false, new Date(2, Month.February, 2015)), //Unadjusted new SingleCase(new SouthAfrica(), BusinessDayConvention.Unadjusted, new Date(3, Month.February, 2015), new Period(1, TimeUnit.Months), false, new Date(3, Month.March, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.Unadjusted, new Date(3, Month.February, 2015), new Period(4, TimeUnit.Days), false, new Date(9, Month.February, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.Unadjusted, new Date(31, Month.January, 2015), new Period(1, TimeUnit.Months), true, new Date(27, Month.February, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.Unadjusted, new Date(31, Month.January, 2015), new Period(1, TimeUnit.Months), false, new Date(28, Month.February, 2015)), //HalfMonthModifiedFollowing new SingleCase(new SouthAfrica(), BusinessDayConvention.HalfMonthModifiedFollowing, new Date(3, Month.February, 2015), new Period(1, TimeUnit.Months), false, new Date(3, Month.March, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.HalfMonthModifiedFollowing, new Date(3, Month.February, 2015), new Period(4, TimeUnit.Days), false, new Date(9, Month.February, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.HalfMonthModifiedFollowing, new Date(31, Month.January, 2015), new Period(1, TimeUnit.Months), true, new Date(27, Month.February, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.HalfMonthModifiedFollowing, new Date(31, Month.January, 2015), new Period(1, TimeUnit.Months), false, new Date(27, Month.February, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.HalfMonthModifiedFollowing, new Date(3, Month.January, 2015), new Period(1, TimeUnit.Weeks), false, new Date(12, Month.January, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.HalfMonthModifiedFollowing, new Date(21, Month.March, 2015), new Period(1, TimeUnit.Weeks), false, new Date(30, Month.March, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.HalfMonthModifiedFollowing, new Date(7, Month.February, 2015), new Period(1, TimeUnit.Months), false, new Date(9, Month.March, 2015)), //Nearest new SingleCase(new SouthAfrica(), BusinessDayConvention.Nearest, new Date(3, Month.February, 2015), new Period(1, TimeUnit.Months), false, new Date(3, Month.March, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.Nearest, new Date(3, Month.February, 2015), new Period(4, TimeUnit.Days), false, new Date(9, Month.February, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.Nearest, new Date(16, Month.April, 2015), new Period(1, TimeUnit.Months), false, new Date(15, Month.May, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.Nearest, new Date(17, Month.April, 2015), new Period(1, TimeUnit.Months), false, new Date(18, Month.May, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.Nearest, new Date(4, Month.March, 2015), new Period(1, TimeUnit.Months), false, new Date(2, Month.April, 2015)), new SingleCase(new SouthAfrica(), BusinessDayConvention.Nearest, new Date(2, Month.April, 2015), new Period(1, TimeUnit.Months), false, new Date(4, Month.May, 2015)) }; int n = testCases.Length; for (int i = 0; i < n; i++) { Calendar calendar = new Calendar(testCases[i].calendar); Date result = calendar.advance(testCases[i].start, testCases[i].period, testCases[i].convention, testCases[i].endOfMonth); QAssert.IsTrue(result == testCases[i].result, "\ncase " + i + ":\n" //<< j << " ("<< desc << "): " + "start date: " + testCases[i].start + "\n" + "calendar: " + calendar + "\n" + "period: " + testCases[i].period + ", end of month: " + testCases[i].endOfMonth + "\n" + "convention: " + testCases[i].convention + "\n" + "expected: " + testCases[i].result + " vs. actual: " + result); } }
public void testBMACurveConsistency <T, I, B>(CommonVars vars, I interpolator, double tolerance) where T : ITraits <YieldTermStructure>, new() where I : IInterpolationFactory, new() where B : IBootStrap <PiecewiseYieldCurve>, new() { // readjust settlement vars.calendar = new JointCalendar(new BMAIndex().fixingCalendar(), new USDLibor(new Period(3, TimeUnit.Months)).fixingCalendar(), JointCalendar.JointCalendarRule.JoinHolidays); vars.today = vars.calendar.adjust(Date.Today); Settings.setEvaluationDate(vars.today); vars.settlement = vars.calendar.advance(vars.today, vars.settlementDays, TimeUnit.Days); Handle <YieldTermStructure> riskFreeCurve = new Handle <YieldTermStructure>( new FlatForward(vars.settlement, 0.04, new Actual360())); BMAIndex bmaIndex = new BMAIndex(); IborIndex liborIndex = new USDLibor(new Period(3, TimeUnit.Months), riskFreeCurve); for (int i = 0; i < vars.bmas; ++i) { Handle <Quote> f = new Handle <Quote>(vars.fractions[i]); vars.bmaHelpers.Add(new BMASwapRateHelper(f, new Period(vars.bmaData[i].n, vars.bmaData[i].units), vars.settlementDays, vars.calendar, new Period(vars.bmaFrequency), vars.bmaConvention, vars.bmaDayCounter, bmaIndex, liborIndex)); } int w = vars.today.weekday(); Date lastWednesday = (w >= 4) ? vars.today - (w - 4) : vars.today + (4 - w - 7); Date lastFixing = bmaIndex.fixingCalendar().adjust(lastWednesday); bmaIndex.addFixing(lastFixing, 0.03); vars.termStructure = new PiecewiseYieldCurve <T, I, B>(vars.settlement, vars.bmaHelpers, new Actual360(), new List <Handle <Quote> >(), new List <Date>(), 1.0e-12, interpolator); RelinkableHandle <YieldTermStructure> curveHandle = new RelinkableHandle <YieldTermStructure>(); curveHandle.linkTo(vars.termStructure); // check BMA swaps BMAIndex bma = new BMAIndex(curveHandle); IborIndex libor3m = new USDLibor(new Period(3, TimeUnit.Months), riskFreeCurve); for (int i = 0; i < vars.bmas; i++) { Period tenor = new Period(vars.bmaData[i].n, vars.bmaData[i].units); Schedule bmaSchedule = new MakeSchedule().from(vars.settlement) .to(vars.settlement + tenor) .withFrequency(vars.bmaFrequency) .withCalendar(bma.fixingCalendar()) .withConvention(vars.bmaConvention) .backwards() .value(); Schedule liborSchedule = new MakeSchedule().from(vars.settlement) .to(vars.settlement + tenor) .withTenor(libor3m.tenor()) .withCalendar(libor3m.fixingCalendar()) .withConvention(libor3m.businessDayConvention()) .endOfMonth(libor3m.endOfMonth()) .backwards() .value(); BMASwap swap = new BMASwap(BMASwap.Type.Payer, 100.0, liborSchedule, 0.75, 0.0, libor3m, libor3m.dayCounter(), bmaSchedule, bma, vars.bmaDayCounter); swap.setPricingEngine(new DiscountingSwapEngine(libor3m.forwardingTermStructure())); double expectedFraction = vars.bmaData[i].rate / 100, estimatedFraction = swap.fairLiborFraction(); double error = Math.Abs(expectedFraction - estimatedFraction); QAssert.IsTrue(error < tolerance, vars.bmaData[i].n + " year(s) BMA swap:\n" + "\n estimated libor fraction: " + estimatedFraction + "\n expected libor fraction: " + expectedFraction + "\n error: " + error + "\n tolerance: " + tolerance); } // this is a workaround for grabage collection // garbage collection needs a proper solution IndexManager.instance().clearHistories(); }
public void testCurveConsistency <T, I, B>(CommonVars vars, I interpolator, double tolerance) where T : ITraits <YieldTermStructure>, new() where I : IInterpolationFactory, new() where B : IBootStrap <PiecewiseYieldCurve>, new() { vars.termStructure = new PiecewiseYieldCurve <T, I, B>(vars.settlement, vars.instruments, new Actual360(), new List <Handle <Quote> >(), new List <Date>(), 1.0e-12, interpolator); RelinkableHandle <YieldTermStructure> curveHandle = new RelinkableHandle <YieldTermStructure>(); curveHandle.linkTo(vars.termStructure); // check deposits for (int i = 0; i < vars.deposits; i++) { Euribor index = new Euribor(new Period(vars.depositData[i].n, vars.depositData[i].units), curveHandle); double expectedRate = vars.depositData[i].rate / 100, estimatedRate = index.fixing(vars.today); QAssert.IsTrue(Math.Abs(expectedRate - estimatedRate) < tolerance, vars.depositData[i].n + " " + (vars.depositData[i].units == TimeUnit.Weeks ? "week(s)" : "month(s)") + " deposit:" + "\n estimated rate: " + estimatedRate + "\n expected rate: " + expectedRate); } // check swaps IborIndex euribor6m = new Euribor6M(curveHandle); for (int i = 0; i < vars.swaps; i++) { Period tenor = new Period(vars.swapData[i].n, vars.swapData[i].units); VanillaSwap swap = new MakeVanillaSwap(tenor, euribor6m, 0.0) .withEffectiveDate(vars.settlement) .withFixedLegDayCount(vars.fixedLegDayCounter) .withFixedLegTenor(new Period(vars.fixedLegFrequency)) .withFixedLegConvention(vars.fixedLegConvention) .withFixedLegTerminationDateConvention(vars.fixedLegConvention); double expectedRate = vars.swapData[i].rate / 100, estimatedRate = swap.fairRate(); double error = Math.Abs(expectedRate - estimatedRate); QAssert.IsTrue(error < tolerance, vars.swapData[i].n + " year(s) swap:\n" + "\n estimated rate: " + estimatedRate + "\n expected rate: " + expectedRate + "\n error: " + error + "\n tolerance: " + tolerance); } // check bonds vars.termStructure = new PiecewiseYieldCurve <T, I, B>(vars.settlement, vars.bondHelpers, new Actual360(), new List <Handle <Quote> >(), new List <Date>(), 1.0e-12, interpolator); curveHandle.linkTo(vars.termStructure); for (int i = 0; i < vars.bonds; i++) { Date maturity = vars.calendar.advance(vars.today, vars.bondData[i].n, vars.bondData[i].units); Date issue = vars.calendar.advance(maturity, -vars.bondData[i].length, TimeUnit.Years); List <double> coupons = new List <double>() { vars.bondData[i].coupon / 100.0 }; FixedRateBond bond = new FixedRateBond(vars.bondSettlementDays, 100.0, vars.schedules[i], coupons, vars.bondDayCounter, vars.bondConvention, vars.bondRedemption, issue); IPricingEngine bondEngine = new DiscountingBondEngine(curveHandle); bond.setPricingEngine(bondEngine); double expectedPrice = vars.bondData[i].price, estimatedPrice = bond.cleanPrice(); QAssert.IsTrue(Math.Abs(expectedPrice - estimatedPrice) < tolerance, i + 1 + " bond failure:" + "\n estimated price: " + estimatedPrice + "\n expected price: " + expectedPrice); } // check FRA vars.termStructure = new PiecewiseYieldCurve <T, I, B>(vars.settlement, vars.fraHelpers, new Actual360(), new List <Handle <Quote> >(), new List <Date>(), 1.0e-12, interpolator); curveHandle.linkTo(vars.termStructure); IborIndex euribor3m = new Euribor3M(curveHandle); for (int i = 0; i < vars.fras; i++) { Date start = vars.calendar.advance(vars.settlement, vars.fraData[i].n, vars.fraData[i].units, euribor3m.businessDayConvention(), euribor3m.endOfMonth()); Date end = vars.calendar.advance(start, 3, TimeUnit.Months, euribor3m.businessDayConvention(), euribor3m.endOfMonth()); ForwardRateAgreement fra = new ForwardRateAgreement(start, end, Position.Type.Long, vars.fraData[i].rate / 100, 100.0, euribor3m, curveHandle); double expectedRate = vars.fraData[i].rate / 100, estimatedRate = fra.forwardRate().rate(); QAssert.IsTrue(Math.Abs(expectedRate - estimatedRate) < tolerance, i + 1 + " FRA failure:" + "\n estimated rate: " + estimatedRate + "\n expected rate: " + expectedRate); } }
public void testCatBondWithDoomOnceInTenYearsProportional() { // Testing floating-rate cat bond in a doom once in 10 years scenario with proportional notional reduction CommonVars vars = new CommonVars(); Date today = new Date(22, Month.November, 2004); Settings.setEvaluationDate(today); int settlementDays = 1; Handle <YieldTermStructure> riskFreeRate = new Handle <YieldTermStructure>(Utilities.flatRate(today, 0.025, new Actual360())); Handle <YieldTermStructure> discountCurve = new Handle <YieldTermStructure>(Utilities.flatRate(today, 0.03, new Actual360())); IborIndex index = new USDLibor(new Period(6, TimeUnit.Months), riskFreeRate); int fixingDays = 1; double tolerance = 1.0e-6; IborCouponPricer pricer = new BlackIborCouponPricer(new Handle <OptionletVolatilityStructure>()); Schedule sch = new Schedule(new Date(30, Month.November, 2004), new Date(30, Month.November, 2008), new Period(Frequency.Semiannual), new UnitedStates(UnitedStates.Market.GovernmentBond), BusinessDayConvention.ModifiedFollowing, BusinessDayConvention.ModifiedFollowing, DateGeneration.Rule.Backward, false); List <KeyValuePair <Date, double> > events = new List <KeyValuePair <Date, double> >(); events.Add(new KeyValuePair <Date, double>(new Date(30, Month.November, 2008), 1000)); CatRisk doomCatRisk = new EventSet(events, new Date(30, Month.November, 2004), new Date(30, Month.November, 2044)); CatRisk noCatRisk = new EventSet(new List <KeyValuePair <Date, double> > (), new Date(1, Month.Jan, 2000), new Date(31, Month.Dec, 2010)); EventPaymentOffset paymentOffset = new NoOffset(); NotionalRisk notionalRisk = new ProportionalNotionalRisk(paymentOffset, 500, 1500); FloatingCatBond catBond = new FloatingCatBond(settlementDays, vars.faceAmount, sch, index, new ActualActual(ActualActual.Convention.ISMA), notionalRisk, BusinessDayConvention.ModifiedFollowing, fixingDays, new List <double>(), new List <double>(), new List <double?>(), new List <double?>(), false, 100.0, new Date(30, Month.November, 2004)); IPricingEngine catBondEngine = new MonteCarloCatBondEngine(doomCatRisk, discountCurve); catBond.setPricingEngine(catBondEngine); Utils.setCouponPricer(catBond.cashflows(), pricer); double price = catBond.cleanPrice(); double yield = catBond.yield(new ActualActual(ActualActual.Convention.ISMA), Compounding.Simple, Frequency.Annual); double lossProbability = catBond.lossProbability(); double exhaustionProbability = catBond.exhaustionProbability(); double expectedLoss = catBond.expectedLoss(); QAssert.AreEqual(0.1, lossProbability, tolerance); QAssert.AreEqual(0.0, exhaustionProbability, tolerance); QAssert.AreEqual(0.05, expectedLoss, tolerance); IPricingEngine catBondEngineRF = new MonteCarloCatBondEngine(noCatRisk, discountCurve); catBond.setPricingEngine(catBondEngineRF); double riskFreePrice = catBond.cleanPrice(); double riskFreeYield = catBond.yield(new ActualActual(ActualActual.Convention.ISMA), Compounding.Simple, Frequency.Annual); double riskFreeLossProbability = catBond.lossProbability(); double riskFreeExpectedLoss = catBond.expectedLoss(); QAssert.AreEqual(0.0, riskFreeLossProbability, tolerance); QAssert.IsTrue(Math.Abs(riskFreeExpectedLoss) < tolerance); QAssert.AreEqual(riskFreePrice * 0.95, price, tolerance); QAssert.IsTrue(riskFreeYield < yield); }
public void testActualActualWithSemiannualSchedule() { // Testing actual/actual with schedule for undefined semiannual reference periods Calendar calendar = new UnitedStates(); Date fromDate = new Date(10, Month.January, 2017); Date firstCoupon = new Date(31, Month.August, 2017); Date quasiCoupon = new Date(28, Month.February, 2017); Date quasiCoupon2 = new Date(31, Month.August, 2016); Schedule schedule = new MakeSchedule() .from(fromDate) .withFirstDate(firstCoupon) .to(new Date(28, Month.February, 2026)) .withFrequency(Frequency.Semiannual) .withCalendar(calendar) .withConvention(BusinessDayConvention.Unadjusted) .backwards().endOfMonth(true).value(); Date testDate = schedule.date(1); DayCounter dayCounter = new ActualActual(ActualActual.Convention.ISMA, schedule); DayCounter dayCounterNoSchedule = new ActualActual(ActualActual.Convention.ISMA); Date referencePeriodStart = schedule.date(1); Date referencePeriodEnd = schedule.date(2); // Test QAssert.IsTrue(dayCounter.yearFraction(referencePeriodStart, referencePeriodStart).IsEqual(0.0), "This should be zero."); QAssert.IsTrue(dayCounterNoSchedule.yearFraction(referencePeriodStart, referencePeriodStart).IsEqual(0.0), "This should be zero"); QAssert.IsTrue(dayCounterNoSchedule.yearFraction(referencePeriodStart, referencePeriodStart, referencePeriodStart, referencePeriodStart).IsEqual(0.0), "This should be zero"); QAssert.IsTrue(dayCounter.yearFraction(referencePeriodStart, referencePeriodEnd).IsEqual(0.5), "This should be exact using schedule; " + referencePeriodStart + " to " + referencePeriodEnd + "Should be 0.5"); QAssert.IsTrue(dayCounterNoSchedule.yearFraction(referencePeriodStart, referencePeriodEnd, referencePeriodStart, referencePeriodEnd).IsEqual(0.5), "This should be exact for explicit reference periods with no schedule"); while (testDate < referencePeriodEnd) { double difference = dayCounter.yearFraction(testDate, referencePeriodEnd, referencePeriodStart, referencePeriodEnd) - dayCounter.yearFraction(testDate, referencePeriodEnd); if (Math.Abs(difference) > 1.0e-10) { QAssert.Fail("Failed to correctly use the schedule to find the reference period for Act/Act"); } testDate = calendar.advance(testDate, 1, TimeUnit.Days); } //Test long first coupon double calculatedYearFraction = dayCounter.yearFraction(fromDate, firstCoupon); double expectedYearFraction = 0.5 + ((double)dayCounter.dayCount(fromDate, quasiCoupon)) / (2 * dayCounter.dayCount(quasiCoupon2, quasiCoupon)); QAssert.IsTrue(Math.Abs(calculatedYearFraction - expectedYearFraction) < 1.0e-10, "Failed to compute the expected year fraction " + "\n expected: " + expectedYearFraction + "\n calculated: " + calculatedYearFraction); // test multiple periods schedule = new MakeSchedule() .from(new Date(10, Month.January, 2017)) .withFirstDate(new Date(31, Month.August, 2017)) .to(new Date(28, Month.February, 2026)) .withFrequency(Frequency.Semiannual) .withCalendar(calendar) .withConvention(BusinessDayConvention.Unadjusted) .backwards().endOfMonth(false).value(); Date periodStartDate = schedule.date(1); Date periodEndDate = schedule.date(2); dayCounter = new ActualActual(ActualActual.Convention.ISMA, schedule); while (periodEndDate < schedule.date(schedule.size() - 2)) { double expected = actualActualDaycountComputation(schedule, periodStartDate, periodEndDate); double calculated = dayCounter.yearFraction(periodStartDate, periodEndDate); if (Math.Abs(expected - calculated) > 1e-8) { QAssert.Fail("Failed to compute the correct year fraction " + "given a schedule: " + periodStartDate + " to " + periodEndDate + "\n expected: " + expected + " calculated: " + calculated); } periodEndDate = calendar.advance(periodEndDate, 1, TimeUnit.Days); } }
public void testFixings() { TestData d = new TestData(); 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); Settings.Instance.enforcesTodaysHistoricFixings = false; try { cms10y2y.fixing(d.refDate - 1); QAssert.Fail("fixing on refDate did not throwed an error."); } catch { } try { cms10y2y.fixing(d.refDate); } catch { QAssert.Fail("fixing on refDate throwed an error."); } QAssert.IsTrue(cms10y2y.fixing(d.refDate) == cms10y.fixing(d.refDate) - cms2y.fixing(d.refDate)); cms10y.addFixing(d.refDate, 0.05); QAssert.IsTrue(cms10y2y.fixing(d.refDate) == cms10y.fixing(d.refDate) - cms2y.fixing(d.refDate)); cms2y.addFixing(d.refDate, 0.04); QAssert.IsTrue(cms10y2y.fixing(d.refDate) == cms10y.fixing(d.refDate) - cms2y.fixing(d.refDate)); Date futureFixingDate = new TARGET().adjust(d.refDate + new Period(1, TimeUnit.Years)); QAssert.IsTrue(cms10y2y.fixing(futureFixingDate) == cms10y.fixing(futureFixingDate) - cms2y.fixing(futureFixingDate)); IndexManager.Instance.clearHistories(); Settings.Instance.enforcesTodaysHistoricFixings = true; try { cms10y2y.fixing(d.refDate); QAssert.Fail("fixing on refDate did not throwed an error."); } catch { } cms10y.addFixing(d.refDate, 0.05); try { cms10y2y.fixing(d.refDate); QAssert.Fail("fixing on refDate did not throwed an error."); } catch { } cms2y.addFixing(d.refDate, 0.04); QAssert.IsTrue(cms10y2y.fixing(d.refDate) == cms10y.fixing(d.refDate) - cms2y.fixing(d.refDate)); IndexManager.Instance.clearHistories(); }
public void cpicapfloorpricer() { CommonVars common = new CommonVars(); double nominal = 1.0; CPICapFloorTermPriceSurface cpiCFpriceSurf = new InterpolatedCPICapFloorTermPriceSurface <Bilinear>(nominal, common.baseZeroRate, common.observationLag, common.calendar, common.convention, common.dcZCIIS, common.hii, common.nominalUK, common.cStrikesUK, common.fStrikesUK, common.cfMaturitiesUK, common.cPriceUK, common.fPriceUK); common.cpiCFsurfUK = cpiCFpriceSurf; // interpolation pricer first // N.B. no new instrument required but we do need a new pricer Date startDate = Settings.evaluationDate(); Date maturity = (startDate + new Period(3, TimeUnit.Years)); Calendar fixCalendar = new UnitedKingdom(), payCalendar = new UnitedKingdom(); BusinessDayConvention fixConvention = BusinessDayConvention.Unadjusted, payConvention = BusinessDayConvention.ModifiedFollowing; double strike = 0.03; double baseCPI = common.hii.link.fixing(fixCalendar.adjust(startDate - common.observationLag, fixConvention)); InterpolationType observationInterpolation = InterpolationType.AsIndex; CPICapFloor aCap = new CPICapFloor(Option.Type.Call, nominal, startDate, // start date of contract (only) baseCPI, maturity, // this is pre-adjustment! fixCalendar, fixConvention, payCalendar, payConvention, strike, common.hii, common.observationLag, observationInterpolation); Handle <CPICapFloorTermPriceSurface> cpiCFsurfUKh = new Handle <CPICapFloorTermPriceSurface>(common.cpiCFsurfUK); IPricingEngine engine = new InterpolatingCPICapFloorEngine(cpiCFsurfUKh); aCap.setPricingEngine(engine); Date d = common.cpiCFsurfUK.cpiOptionDateFromTenor(new Period(3, TimeUnit.Years)); double cached = cpiCFsurfUKh.link.capPrice(d, strike); QAssert.IsTrue(Math.Abs(cached - aCap.NPV()) < 1e-10, "InterpolatingCPICapFloorEngine does not reproduce cached price: " + cached + " vs " + aCap.NPV()); // remove circular refernce common.hcpi.linkTo(null); }
public void cpibondconsistency() { CommonVars common = new CommonVars(); // ZeroInflationSwap aka CPISwap CPISwap.Type type = CPISwap.Type.Payer; double nominal = 1000000.0; bool subtractInflationNominal = true; // float+spread leg double spread = 0.0; DayCounter floatDayCount = new Actual365Fixed(); BusinessDayConvention floatPaymentConvention = BusinessDayConvention.ModifiedFollowing; int fixingDays = 0; IborIndex floatIndex = new GBPLibor(new Period(6, TimeUnit.Months), common.nominalUK); // fixed x inflation leg double fixedRate = 0.1; //1% would be 0.01 double baseCPI = 206.1; // would be 206.13871 if we were interpolating DayCounter fixedDayCount = new Actual365Fixed(); BusinessDayConvention fixedPaymentConvention = BusinessDayConvention.ModifiedFollowing; Calendar fixedPaymentCalendar = new UnitedKingdom(); ZeroInflationIndex fixedIndex = common.ii; Period contractObservationLag = common.contractObservationLag; InterpolationType observationInterpolation = common.contractObservationInterpolation; // set the schedules Date startDate = new Date(2, Month.October, 2007); Date endDate = new Date(2, Month.October, 2052); Schedule floatSchedule = new MakeSchedule().from(startDate).to(endDate) .withTenor(new Period(6, TimeUnit.Months)) .withCalendar(new UnitedKingdom()) .withConvention(floatPaymentConvention) .backwards().value(); Schedule fixedSchedule = new MakeSchedule().from(startDate).to(endDate) .withTenor(new Period(6, TimeUnit.Months)) .withCalendar(new UnitedKingdom()) .withConvention(BusinessDayConvention.Unadjusted) .backwards().value(); CPISwap zisV = new CPISwap(type, nominal, subtractInflationNominal, spread, floatDayCount, floatSchedule, floatPaymentConvention, fixingDays, floatIndex, fixedRate, baseCPI, fixedDayCount, fixedSchedule, fixedPaymentConvention, contractObservationLag, fixedIndex, observationInterpolation); double[] floatFix = { 0.06255, 0.05975, 0.0637, 0.018425, 0.0073438, -1, -1 }; double[] cpiFix = { 211.4, 217.2, 211.4, 213.4, -2, -2 }; for (int i = 0; i < floatSchedule.Count; i++) { if (floatSchedule[i] < common.evaluationDate) { floatIndex.addFixing(floatSchedule[i], floatFix[i], true);//true=overwrite } CPICoupon zic = zisV.cpiLeg()[i] as CPICoupon; if (zic != null) { if (zic.fixingDate() < (common.evaluationDate - new Period(1, TimeUnit.Months))) { fixedIndex.addFixing(zic.fixingDate(), cpiFix[i], true); } } } // simple structure so simple pricing engine - most work done by index DiscountingSwapEngine dse = new DiscountingSwapEngine(common.nominalUK); zisV.setPricingEngine(dse); // now do the bond equivalent List <double> fixedRates = new InitializedList <double>(1, fixedRate); int settlementDays = 1;// cannot be zero! bool growthOnly = true; CPIBond cpiB = new CPIBond(settlementDays, nominal, growthOnly, baseCPI, contractObservationLag, fixedIndex, observationInterpolation, fixedSchedule, fixedRates, fixedDayCount, fixedPaymentConvention); DiscountingBondEngine dbe = new DiscountingBondEngine(common.nominalUK); cpiB.setPricingEngine(dbe); QAssert.IsTrue(Math.Abs(cpiB.NPV() - zisV.legNPV(0).GetValueOrDefault()) < 1e-5, "cpi bond does not equal equivalent cpi swap leg"); // remove circular refernce common.hcpi.linkTo(null); }
public void consistency() { // check inflation leg vs calculation directly from inflation TS CommonVars common = new CommonVars(); // ZeroInflationSwap aka CPISwap CPISwap.Type type = CPISwap.Type.Payer; double nominal = 1000000.0; bool subtractInflationNominal = true; // float+spread leg double spread = 0.0; DayCounter floatDayCount = new Actual365Fixed(); BusinessDayConvention floatPaymentConvention = BusinessDayConvention.ModifiedFollowing; int fixingDays = 0; IborIndex floatIndex = new GBPLibor(new Period(6, TimeUnit.Months), common.nominalUK); // fixed x inflation leg double fixedRate = 0.1; //1% would be 0.01 double baseCPI = 206.1; // would be 206.13871 if we were interpolating DayCounter fixedDayCount = new Actual365Fixed(); BusinessDayConvention fixedPaymentConvention = BusinessDayConvention.ModifiedFollowing; Calendar fixedPaymentCalendar = new UnitedKingdom(); ZeroInflationIndex fixedIndex = common.ii; Period contractObservationLag = common.contractObservationLag; InterpolationType observationInterpolation = common.contractObservationInterpolation; // set the schedules Date startDate = new Date(2, Month.October, 2007); Date endDate = new Date(2, Month.October, 2052); Schedule floatSchedule = new MakeSchedule().from(startDate).to(endDate) .withTenor(new Period(6, TimeUnit.Months)) .withCalendar(new UnitedKingdom()) .withConvention(floatPaymentConvention) .backwards().value(); Schedule fixedSchedule = new MakeSchedule().from(startDate).to(endDate) .withTenor(new Period(6, TimeUnit.Months)) .withCalendar(new UnitedKingdom()) .withConvention(BusinessDayConvention.Unadjusted) .backwards().value(); CPISwap zisV = new CPISwap(type, nominal, subtractInflationNominal, spread, floatDayCount, floatSchedule, floatPaymentConvention, fixingDays, floatIndex, fixedRate, baseCPI, fixedDayCount, fixedSchedule, fixedPaymentConvention, contractObservationLag, fixedIndex, observationInterpolation); Date asofDate = Settings.evaluationDate(); double[] floatFix = { 0.06255, 0.05975, 0.0637, 0.018425, 0.0073438, -1, -1 }; double[] cpiFix = { 211.4, 217.2, 211.4, 213.4, -2, -2 }; for (int i = 0; i < floatSchedule.Count; i++) { if (floatSchedule[i] < common.evaluationDate) { floatIndex.addFixing(floatSchedule[i], floatFix[i], true);//true=overwrite } CPICoupon zic = zisV.cpiLeg()[i] as CPICoupon; if (zic != null) { if (zic.fixingDate() < (common.evaluationDate - new Period(1, TimeUnit.Months))) { fixedIndex.addFixing(zic.fixingDate(), cpiFix[i], true); } } } // simple structure so simple pricing engine - most work done by index DiscountingSwapEngine dse = new DiscountingSwapEngine(common.nominalUK); zisV.setPricingEngine(dse); // get float+spread & fixed*inflation leg prices separately double testInfLegNPV = 0.0; double diff; for (int i = 0; i < zisV.leg(0).Count; i++) { Date zicPayDate = (zisV.leg(0))[i].date(); if (zicPayDate > asofDate) { testInfLegNPV += (zisV.leg(0))[i].amount() * common.nominalUK.link.discount(zicPayDate); } CPICoupon zicV = zisV.cpiLeg()[i] as CPICoupon; if (zicV != null) { diff = Math.Abs(zicV.rate() - (fixedRate * (zicV.indexFixing() / baseCPI))); QAssert.IsTrue(diff < 1e-8, "failed " + i + "th coupon reconstruction as " + (fixedRate * (zicV.indexFixing() / baseCPI)) + " vs rate = " + zicV.rate() + ", with difference: " + diff); } } double error = Math.Abs(testInfLegNPV - zisV.legNPV(0).Value); QAssert.IsTrue(error < 1e-5, "failed manual inf leg NPV calc vs pricing engine: " + testInfLegNPV + " vs " + zisV.legNPV(0)); diff = Math.Abs(1 - zisV.NPV() / 4191660.0); #if QL_USE_INDEXED_COUPON double max_diff = 1e-5; #else double max_diff = 3e-5; #endif QAssert.IsTrue(diff < max_diff, "failed stored consistency value test, ratio = " + diff); // remove circular refernce common.hcpi.linkTo(null); }
public void testCachedValue() { // Testing Black yoy inflation cap/floor price against cached values... CommonVars vars = new CommonVars(); int whichPricer = 0; // black double K = 0.0295; // one centi-point is fair rate error i.e. < 1 cp int j = 2; List <CashFlow> leg = vars.makeYoYLeg(vars.evaluationDate, j); Instrument cap = vars.makeYoYCapFloor(CapFloorType.Cap, leg, K, 0.01, whichPricer); Instrument floor = vars.makeYoYCapFloor(CapFloorType.Floor, leg, K, 0.01, whichPricer); // close to atm prices double cachedCapNPVblack = 219.452; double cachedFloorNPVblack = 314.641; // N.B. notionals are 10e6. QAssert.IsTrue(Math.Abs(cap.NPV() - cachedCapNPVblack) < 0.02, "yoy cap cached NPV wrong " + cap.NPV() + " should be " + cachedCapNPVblack + " Black pricer" + " diff was " + (Math.Abs(cap.NPV() - cachedCapNPVblack))); QAssert.IsTrue(Math.Abs(floor.NPV() - cachedFloorNPVblack) < 0.02, "yoy floor cached NPV wrong " + floor.NPV() + " should be " + cachedFloorNPVblack + " Black pricer" + " diff was " + (Math.Abs(floor.NPV() - cachedFloorNPVblack))); whichPricer = 1; // dd cap = vars.makeYoYCapFloor(CapFloorType.Cap, leg, K, 0.01, whichPricer); floor = vars.makeYoYCapFloor(CapFloorType.Floor, leg, K, 0.01, whichPricer); // close to atm prices double cachedCapNPVdd = 9114.61; double cachedFloorNPVdd = 9209.8; // N.B. notionals are 10e6. QAssert.IsTrue(Math.Abs(cap.NPV() - cachedCapNPVdd) < 0.22, "yoy cap cached NPV wrong " + cap.NPV() + " should be " + cachedCapNPVdd + " dd Black pricer" + " diff was " + (Math.Abs(cap.NPV() - cachedCapNPVdd))); QAssert.IsTrue(Math.Abs(floor.NPV() - cachedFloorNPVdd) < 0.22, "yoy floor cached NPV wrong " + floor.NPV() + " should be " + cachedFloorNPVdd + " dd Black pricer" + " diff was " + (Math.Abs(floor.NPV() - cachedFloorNPVdd))); whichPricer = 2; // bachelier cap = vars.makeYoYCapFloor(CapFloorType.Cap, leg, K, 0.01, whichPricer); floor = vars.makeYoYCapFloor(CapFloorType.Floor, leg, K, 0.01, whichPricer); // close to atm prices double cachedCapNPVbac = 8852.4; double cachedFloorNPVbac = 8947.59; // N.B. notionals are 10e6. QAssert.IsTrue(Math.Abs(cap.NPV() - cachedCapNPVbac) < 0.22, "yoy cap cached NPV wrong " + cap.NPV() + " should be " + cachedCapNPVbac + " bac Black pricer" + " diff was " + (Math.Abs(cap.NPV() - cachedCapNPVbac))); QAssert.IsTrue(Math.Abs(floor.NPV() - cachedFloorNPVbac) < 0.22, "yoy floor cached NPV wrong " + floor.NPV() + " should be " + cachedFloorNPVbac + " bac Black pricer" + " diff was " + (Math.Abs(floor.NPV() - cachedFloorNPVbac))); // remove circular refernce vars.hy.linkTo(null); }
public void testCompositeZeroYieldStructures() { // Testing composite zero yield structures... Settings.setEvaluationDate(new Date(10, Month.Nov, 2017)); // First curve var dates = new List <Date> { new Date(10, Month.Nov, 2017), new Date(13, Month.Nov, 2017), new Date(12, Month.Feb, 2018), new Date(10, Month.May, 2018), new Date(10, Month.Aug, 2018), new Date(12, Month.Nov, 2018), new Date(21, Month.Dec, 2018), new Date(15, Month.Jan, 2020), new Date(31, Month.Mar, 2021), new Date(28, Month.Feb, 2023), new Date(21, Month.Dec, 2026), new Date(31, Month.Jan, 2030), new Date(28, Month.Feb, 2031), new Date(31, Month.Mar, 2036), new Date(28, Month.Feb, 2041), new Date(28, Month.Feb, 2048), new Date(31, Month.Dec, 2141) }; var rates = new List <double> { 0.0655823213132524, 0.0655823213132524, 0.0699455024156877, 0.0799107139233497, 0.0813931951022577, 0.0841615820666691, 0.0501297919004145, 0.0823483583439658, 0.0860720030924466, 0.0922887604375688, 0.10588902278996, 0.117021968693922, 0.109824660896137, 0.109231572878364, 0.119218123236241, 0.128647300167664, 0.0506086995288751 }; var termStructure1 = new InterpolatedForwardCurve <BackwardFlat>(dates, rates, new Actual365Fixed(), new NullCalendar()); // Second curve dates = new List <Date>(); rates = new List <double>(); dates.Add(new Date(10, Month.Nov, 2017)); dates.Add(new Date(13, Month.Nov, 2017)); dates.Add(new Date(11, Month.Dec, 2017)); dates.Add(new Date(12, Month.Feb, 2018)); dates.Add(new Date(10, Month.May, 2018)); dates.Add(new Date(31, Month.Jan, 2022)); dates.Add(new Date(7, Month.Dec, 2023)); dates.Add(new Date(31, Month.Jan, 2025)); dates.Add(new Date(31, Month.Mar, 2028)); dates.Add(new Date(7, Month.Dec, 2033)); dates.Add(new Date(1, Month.Feb, 2038)); dates.Add(new Date(2, Month.Apr, 2046)); dates.Add(new Date(2, Month.Jan, 2051)); dates.Add(new Date(31, Month.Dec, 2141)); rates.Add(0.056656806197189); rates.Add(0.056656806197189); rates.Add(0.0419541633454473); rates.Add(0.0286681050019797); rates.Add(0.0148840226959593); rates.Add(0.0246680238374363); rates.Add(0.0255349067810599); rates.Add(0.0298907184711927); rates.Add(0.0263943927922053); rates.Add(0.0291924526539802); rates.Add(0.0270049276163556); rates.Add(0.028775807327614); rates.Add(0.0293567711641792); rates.Add(0.010518655099659); var termStructure2 = new InterpolatedForwardCurve <BackwardFlat>(dates, rates, new Actual365Fixed(), new NullCalendar()); var compoundCurve = new CompositeZeroYieldStructure ( new Handle <YieldTermStructure>(termStructure1), new Handle <YieldTermStructure>(termStructure2), sub ); // Expected values dates = new List <Date>(); rates = new List <double>(); dates.Add(new Date(10, Month.Nov, 2017)); dates.Add(new Date(15, Month.Dec, 2017)); dates.Add(new Date(15, Month.Jun, 2018)); dates.Add(new Date(15, Month.Sep, 2029)); dates.Add(new Date(15, Month.Sep, 2038)); dates.Add(new Date(15, Month.Mar, 2046)); dates.Add(new Date(15, Month.Dec, 2141)); rates.Add(0.00892551511527986); rates.Add(0.0278755322562788); rates.Add(0.0512001768603456); rates.Add(0.0729941474263546); rates.Add(0.0778333309498459); rates.Add(0.0828451659139004); rates.Add(0.0503573807521742); double tolerance = 1.0e-10; for (var i = 0; i < dates.Count; ++i) { double actual = compoundCurve.zeroRate(dates[i], new Actual365Fixed(), Compounding.Continuous).rate(); double expected = rates[i]; QAssert.IsTrue(Math.Abs(actual - expected) <= tolerance, "unable to reproduce zero yield rate from composite input curve\n" + " calculated: " + actual + "\n" + " expected: " + expected); } }
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); }