public virtual void parSpreadTest()
        {
            LocalDate   valuationDate    = LocalDate.of(2013, 2, 27);
            DoubleArray ycTime           = DoubleArray.ofUnsafe(new double[] { 0.09041095890410959, 0.1726027397260274, 0.26301369863013696, 0.5123287671232877, 0.7616438356164383, 1.010958904109589, 2.008219178082192, 3.008219178082192, 4.008219178082192, 5.008219178082192, 6.008219178082192, 7.013698630136987, 8.01095890410959, 9.01095890410959, 10.01095890410959, 12.01917808219178, 15.016438356164384, 20.01917808219178, 25.021917808219175, 30.027397260273972 });
            DoubleArray ycRate           = DoubleArray.ofUnsafe(new double[] { 0.0020651105531615476, 0.0024506037920717797, 0.0028872269869485313, 0.004599628230463427, 0.006160809466806469, 0.0075703969168129295, 0.003965128877560435, 0.005059104202201957, 0.0069669135253734825, 0.009361825469323602, 0.011916895611422482, 0.014311922779901886, 0.016519187063048578, 0.018512121993907647, 0.020289623737560873, 0.02329885162861984, 0.026399509889410745, 0.029087919732133784, 0.03037740056662963, 0.03110021763406523 });
            IsdaCreditDiscountFactors yc = IsdaCreditDiscountFactors.of(EUR, valuationDate, CurveName.of("yc_usd"), ycTime, ycRate, ACT_365F);

            double[] timeNodeExp   = new double[] { 0.5616438356164384, 1.0575342465753426, 2.0575342465753423, 3.0602739726027397, 4.06027397260274, 5.06027397260274, 6.06027397260274, 7.063013698630137, 8.063013698630137, 9.063013698630137, 10.063013698630137 };
            double[] rateNodeExp   = new double[] { 0.00876054089781935, 0.011037345646850688, 0.015955126945240167, 0.020617953392829177, 0.025787811343896218, 0.030329992053915133, 0.03313419899444371, 0.03528129159875671, 0.03675340516560903, 0.037946169956317416, 0.038951101800190346 };
            double[] rateNodeExpMf = new double[] { 0.008754510260229803, 0.011030502992814844, 0.01594817866773906, 0.02060947097554756, 0.025776720596175737, 0.030316032527460755, 0.03311839631615255, 0.03526404051997617, 0.03673513322394772, 0.03792689865945585, 0.03893107891569398 };
            ImmutableCreditRatesProvider ratesProvider = ImmutableCreditRatesProvider.builder().valuationDate(valuationDate).discountCurves(ImmutableMap.of(EUR, yc)).recoveryRateCurves(ImmutableMap.of(LEGAL_ENTITY, ConstantRecoveryRates.of(LEGAL_ENTITY, valuationDate, 0.25))).creditCurves(ImmutableMap.of()).build();
            LocalDate startDate = LocalDate.of(2012, 12, 20);

            LocalDate[] pillarDates = new LocalDate[] { LocalDate.of(2013, 9, 20), LocalDate.of(2014, 3, 20), LocalDate.of(2015, 3, 20), LocalDate.of(2016, 3, 20), LocalDate.of(2017, 3, 20), LocalDate.of(2018, 3, 20), LocalDate.of(2019, 3, 20), LocalDate.of(2020, 3, 20), LocalDate.of(2021, 3, 20), LocalDate.of(2022, 3, 20), LocalDate.of(2023, 3, 20) };
            int         nPillars    = pillarDates.Length;
            ImmutableMarketDataBuilder     builderCredit = ImmutableMarketData.builder(valuationDate);
            IList <CdsIsdaCreditCurveNode> nodes         = new List <CdsIsdaCreditCurveNode>(nPillars);

            double[] quotes = new double[] { 0.006485, 0.008163, 0.011763, 0.015136, 0.018787, 0.021905, 0.023797, 0.025211, 0.02617, 0.026928, 0.027549 };
            for (int i = 0; i < nPillars; ++i)
            {
                CdsConvention conv = ImmutableCdsConvention.of("conv", EUR, ACT_360, Frequency.P3M, BUS_ADJ, CDS_SETTLE_STD);
                CdsTemplate   temp = DatesCdsTemplate.of(startDate, pillarDates[i], conv);
                QuoteId       id   = QuoteId.of(StandardId.of("OG", pillarDates[i].ToString()));
                nodes.Add(CdsIsdaCreditCurveNode.ofParSpread(temp, id, LEGAL_ENTITY));
                builderCredit.addValue(id, quotes[i]);
            }
            ImmutableMarketData              marketData      = builderCredit.build();
            IsdaCreditCurveDefinition        curveDefinition = IsdaCreditCurveDefinition.of(CurveName.of("zz"), EUR, valuationDate, ACT_365F, nodes, true, true);
            LegalEntitySurvivalProbabilities cc = BUILDER_ISDA.calibrate(curveDefinition, marketData, ratesProvider, REF_DATA);
            NodalCurve resCurve = ((IsdaCreditDiscountFactors)cc.SurvivalProbabilities).Curve;

            for (int i = 0; i < nPillars; ++i)
            {
                ParameterMetadata param = resCurve.getParameterMetadata(i);
                assertTrue(param is ResolvedTradeParameterMetadata);
                ResolvedTradeParameterMetadata tradeParam = (ResolvedTradeParameterMetadata)param;
                assertTrue(tradeParam.Trade is ResolvedCdsTrade);
            }
            assertTrue(DoubleArrayMath.fuzzyEquals(resCurve.XValues.toArray(), timeNodeExp, TOL));
            assertTrue(DoubleArrayMath.fuzzyEquals(resCurve.YValues.toArray(), rateNodeExp, TOL));
            testJacobian(BUILDER_ISDA, cc, ratesProvider, nodes, quotes, 1d, EPS);
            LegalEntitySurvivalProbabilities ccMf = BUILDER_MARKIT.calibrate(curveDefinition, marketData, ratesProvider, REF_DATA);
            NodalCurve resCurveMf = ((IsdaCreditDiscountFactors)ccMf.SurvivalProbabilities).Curve;

            assertTrue(DoubleArrayMath.fuzzyEquals(resCurveMf.XValues.toArray(), timeNodeExp, TOL));
            assertTrue(DoubleArrayMath.fuzzyEquals(resCurveMf.YValues.toArray(), rateNodeExpMf, TOL));
            testJacobian(BUILDER_MARKIT, ccMf, ratesProvider, nodes, quotes, 1d, EPS);
        }
        public virtual void pufTest()
        {
            LocalDate   valuationDate    = LocalDate.of(2013, 4, 10);
            DoubleArray ycTime           = DoubleArray.ofUnsafe(new double[] { 0.09041095890410959, 0.1726027397260274, 0.2547945205479452, 0.5123287671232877, 0.7616438356164383, 1.010958904109589, 2.008219178082192, 3.008219178082192, 4.008219178082192, 5.008219178082192, 6.008219178082192, 7.013698630136987, 8.01095890410959, 9.01095890410959, 10.01095890410959, 12.01917808219178, 15.016438356164384, 20.01917808219178, 25.021917808219175, 30.027397260273972 });
            DoubleArray ycRate           = DoubleArray.ofUnsafe(new double[] { 0.0020205071813561414, 0.0024226927083852126, 0.00280147037504029, 0.004449041082144009, 0.005821804782808804, 0.007254879152733453, 0.00378133614924816, 0.004815163234294319, 0.006576302084547871, 0.00884241431837336, 0.011358805989279104, 0.013793391727035883, 0.016014197840890115, 0.01801564209277191, 0.019757164421290663, 0.022773295945438254, 0.025862337032619587, 0.02848646344754061, 0.029753383126110852, 0.03045277462637107 });
            IsdaCreditDiscountFactors yc = IsdaCreditDiscountFactors.of(EUR, valuationDate, CurveName.of("yc_usd"), ycTime, ycRate, ACT_365F);

            double[] timeNodeExp   = new double[] { 0.19452054794520549, 0.4465753424657534, 0.6958904109589041, 0.9424657534246575, 1.1945205479452055, 1.4465753424657535, 1.6958904109589041, 1.9424657534246574, 2.1945205479452055, 2.4465753424657533, 2.695890410958904, 2.9452054794520546, 3.197260273972603, 3.4493150684931506, 3.6986301369863015, 3.9452054794520546, 4.197260273972603, 4.449315068493151, 4.698630136986301, 4.945205479452055, 5.197260273972603, 5.449315068493151, 5.698630136986301, 5.945205479452055, 6.197260273972603, 6.449315068493151, 6.698630136986301, 6.947945205479452, 7.2, 7.4520547945205475, 7.701369863013698, 7.947945205479452, 8.2, 8.452054794520548, 8.7013698630137, 8.947945205479453, 9.2, 9.452054794520548, 9.7013698630137, 9.947945205479453, 10.2 };
            double[] rateNodeExp   = new double[] { 0.11219168510100914, 0.11085321179769615, 0.11753783265486063, 0.11806409789291543, 0.12007843111645247, 0.12273722191216528, 0.12541993298405366, 0.12773640093265545, 0.1290535220739981, 0.13294183149211675, 0.13659302947963856, 0.13988488561043758, 0.1429469312254705, 0.14606538453369572, 0.14916286828444447, 0.15219682906227, 0.1548315745851032, 0.158141193071526, 0.16163981714033765, 0.1650400193930357, 0.1682351993447916, 0.1683744003954113, 0.168657453080796, 0.16915067878510565, 0.1694852880010724, 0.16990705130936645, 0.1704456138969621, 0.17105852486248443, 0.1717088423125347, 0.1727906445582425, 0.17407566745397665, 0.17547300248653266, 0.17679395545074758, 0.17769841457372118, 0.1788064602071617, 0.18001498257267778, 0.18123747758791092, 0.18253661761388457, 0.18406319235262744, 0.18582983758830868, 0.18750386499176422 };
            double[] rateNodeExpMf = new double[] { 0.11107220823737506, 0.11011543264900588, 0.11685607164947402, 0.11742079953945683, 0.1194445192166302, 0.12220026187805585, 0.12494798294628297, 0.12731185688090763, 0.12860146674492023, 0.1325216904413876, 0.1362014254649678, 0.13951646788193767, 0.14254141853655264, 0.14567581048732742, 0.1487851622438674, 0.15182838855605538, 0.15442415754322128, 0.15774061191016645, 0.16124288871765308, 0.1646451035564102, 0.167796451103847, 0.16794456750248196, 0.16823438468063495, 0.1687328171292339, 0.16904360885724334, 0.16947020572961907, 0.17001201556723175, 0.17062724832190826, 0.17125190473373603, 0.17233319414449558, 0.17361785479583028, 0.1750136127341691, 0.17630530410589512, 0.17720871748506664, 0.17831270423353415, 0.17951604233911425, 0.18070939732103264, 0.18200162521943403, 0.18351891000003046, 0.1852740041292825, 0.18691086960422418 };
            ImmutableCreditRatesProvider ratesProvider = ImmutableCreditRatesProvider.builder().valuationDate(valuationDate).discountCurves(ImmutableMap.of(EUR, yc)).recoveryRateCurves(ImmutableMap.of(LEGAL_ENTITY, ConstantRecoveryRates.of(LEGAL_ENTITY, valuationDate, 0.4))).creditCurves(ImmutableMap.of()).build();
            LocalDate startDate = LocalDate.of(2013, 3, 20);

            LocalDate[] pillarDate = new LocalDate[] { LocalDate.of(2013, 6, 20), LocalDate.of(2013, 9, 20), LocalDate.of(2013, 12, 20), LocalDate.of(2014, 3, 20), LocalDate.of(2014, 6, 20), LocalDate.of(2014, 9, 20), LocalDate.of(2014, 12, 20), LocalDate.of(2015, 3, 20), LocalDate.of(2015, 6, 20), LocalDate.of(2015, 9, 20), LocalDate.of(2015, 12, 20), LocalDate.of(2016, 3, 20), LocalDate.of(2016, 6, 20), LocalDate.of(2016, 9, 20), LocalDate.of(2016, 12, 20), LocalDate.of(2017, 3, 20), LocalDate.of(2017, 6, 20), LocalDate.of(2017, 9, 20), LocalDate.of(2017, 12, 20), LocalDate.of(2018, 3, 20), LocalDate.of(2018, 6, 20), LocalDate.of(2018, 9, 20), LocalDate.of(2018, 12, 20), LocalDate.of(2019, 3, 20), LocalDate.of(2019, 6, 20), LocalDate.of(2019, 9, 20), LocalDate.of(2019, 12, 20), LocalDate.of(2020, 3, 20), LocalDate.of(2020, 6, 20), LocalDate.of(2020, 9, 20), LocalDate.of(2020, 12, 20), LocalDate.of(2021, 3, 20), LocalDate.of(2021, 6, 20), LocalDate.of(2021, 9, 20), LocalDate.of(2021, 12, 20), LocalDate.of(2022, 3, 20), LocalDate.of(2022, 6, 20), LocalDate.of(2022, 9, 20), LocalDate.of(2022, 12, 20), LocalDate.of(2023, 3, 20), LocalDate.of(2023, 6, 20) };
            int         nPillars   = pillarDate.Length;
            double      coupon     = 500d * ONE_BP;
            ImmutableMarketDataBuilder     builderCredit = ImmutableMarketData.builder(valuationDate);
            IList <CdsIsdaCreditCurveNode> nodes         = new List <CdsIsdaCreditCurveNode>(nPillars);

            double[] quotes = new double[] { 0.32, 0.69, 1.32, 1.79, 2.36, 3.01, 3.7, 4.39, 5.02, 5.93, 6.85, 7.76, 8.67, 9.6, 10.53, 11.45, 12.33, 13.29, 14.26, 15.2, 16.11, 16.62, 17.12, 17.62, 18.09, 18.55, 19, 19.44, 19.87, 20.33, 20.79, 21.24, 21.67, 22.04, 22.41, 22.77, 23.12, 23.46, 23.8, 24.14, 24.46 };
            for (int i = 0; i < nPillars; ++i)
            {
                CdsConvention conv = ImmutableCdsConvention.of("conv", EUR, ACT_360, Frequency.P3M, BUS_ADJ, CDS_SETTLE_STD);
                CdsTemplate   temp = DatesCdsTemplate.of(startDate, pillarDate[i], conv);
                QuoteId       id   = QuoteId.of(StandardId.of("OG", pillarDate[i].ToString()));
                nodes.Add(CdsIsdaCreditCurveNode.ofPointsUpfront(temp, id, LEGAL_ENTITY, coupon));
                builderCredit.addValue(id, quotes[i] * ONE_PC);
            }
            ImmutableMarketData              marketData      = builderCredit.build();
            IsdaCreditCurveDefinition        curveDefinition = IsdaCreditCurveDefinition.of(CurveName.of("cc"), EUR, valuationDate, ACT_365F, nodes, true, false);
            LegalEntitySurvivalProbabilities cc = BUILDER_ISDA.calibrate(curveDefinition, marketData, ratesProvider, REF_DATA);
            NodalCurve resCurve = ((IsdaCreditDiscountFactors)cc.SurvivalProbabilities).Curve;

            assertTrue(DoubleArrayMath.fuzzyEquals(resCurve.XValues.toArray(), timeNodeExp, TOL));
            assertTrue(DoubleArrayMath.fuzzyEquals(resCurve.YValues.toArray(), rateNodeExp, TOL));
            testJacobian(BUILDER_ISDA, cc, ratesProvider, nodes, quotes, ONE_PC, EPS);
            LegalEntitySurvivalProbabilities ccMf = BUILDER_MARKIT.calibrate(curveDefinition, marketData, ratesProvider, REF_DATA);
            NodalCurve resCurveMf = ((IsdaCreditDiscountFactors)ccMf.SurvivalProbabilities).Curve;

            assertTrue(DoubleArrayMath.fuzzyEquals(resCurveMf.XValues.toArray(), timeNodeExp, TOL));
            assertTrue(DoubleArrayMath.fuzzyEquals(resCurveMf.YValues.toArray(), rateNodeExpMf, TOL));
            testJacobian(BUILDER_MARKIT, ccMf, ratesProvider, nodes, quotes, ONE_PC, EPS);
        }
        static IsdaCompliantCreditCurveCalibratorBase()
        {
            ImmutableList.Builder <IsdaCreditCurveNode> dscNodeBuilder = ImmutableList.builder();
            for (int i = 0; i < NUM_MM; i++)
            {
                Tenor tenor = Tenor.ofMonths(MM_MONTHS[i]);
                dscNodeBuilder.add(DepositIsdaCreditCurveNode.of(QuoteId.of(StandardId.of("OG", ID_VALUES[i])), ADJ_3D, BUS_ADJ, tenor, ACT_360));
            }
            for (int i = NUM_MM; i < NUM_INSTRUMENTS; i++)
            {
                Tenor tenor = Tenor.ofYears(SWAP_YEARS[i - NUM_MM]);
                dscNodeBuilder.add(SwapIsdaCreditCurveNode.of(QuoteId.of(StandardId.of("OG", ID_VALUES[i])), ADJ_3D, BUS_ADJ, tenor, THIRTY_U_360, Frequency.P12M));
            }
            DSC_NODES       = dscNodeBuilder.build();
            EXP_NODE_CDS    = new ResolvedCdsTrade[NUM_TESTS][];
            NODE_CDS        = new CdsIsdaCreditCurveNode[NUM_TESTS][];
            CDS_MARKET_DATA = new ImmutableMarketData[NUM_TESTS];
            SPREADS         = new double[NUM_TESTS][];
            YIELD_CURVES    = new ImmutableCreditRatesProvider[NUM_TESTS];
            // case0
            LocalDate tradeDate0 = LocalDate.of(2011, 6, 19);
            LocalDate startDate0 = LocalDate.of(2011, 3, 21);

            YIELD_CURVES[0] = createRatesProvider(tradeDate0, tradeDate0, 1d, 0.4);
            Period[] tenors  = new Period[] { Period.ofMonths(6), Period.ofYears(1), Period.ofYears(3), Period.ofYears(5), Period.ofYears(7), Period.ofYears(10) };
            int      nTenors = tenors.Length;

            EXP_NODE_CDS[0] = new ResolvedCdsTrade[nTenors];
            NODE_CDS[0]     = new CdsIsdaCreditCurveNode[nTenors];
            ImmutableMarketDataBuilder builderCredit0 = ImmutableMarketData.builder(tradeDate0);

            SPREADS[0] = new double[] { 0.00886315689995649, 0.00886315689995649, 0.0133044689825873, 0.0171490070952563, 0.0183903639181293, 0.0194721890639724 };
            for (int i = 0; i < nTenors; ++i)
            {
                Cds product = Cds.of(BUY, LEGAL_ENTITY, EUR, 1d, startDate0, LocalDate.of(2011, 6, 20).plus(tenors[i]), Frequency.P3M, DEFAULT_CALENDAR, SPREADS[0][i]);
                EXP_NODE_CDS[0][i] = CdsTrade.builder().info(TradeInfo.builder().settlementDate(product.SettlementDateOffset.adjust(tradeDate0, REF_DATA)).build()).product(product).build().resolve(REF_DATA);
                CdsConvention conv = ImmutableCdsConvention.of("conv", EUR, ACT_360, Frequency.P3M, BUS_ADJ, CDS_SETTLE_STD);
                CdsTemplate   temp = DatesCdsTemplate.of(startDate0, LocalDate.of(2011, 6, 20).plus(tenors[i]), conv);
                QuoteId       id   = QuoteId.of(StandardId.of("OG", tenors[i].ToString()));
                NODE_CDS[0][i] = CdsIsdaCreditCurveNode.ofParSpread(temp, id, LEGAL_ENTITY);
                builderCredit0.addValue(id, SPREADS[0][i]);
            }
            CDS_MARKET_DATA[0] = builderCredit0.build();
            // case1
            LocalDate tradeDate1 = LocalDate.of(2011, 3, 21);
            LocalDate snapDate1  = LocalDate.of(2011, 3, 18);
            LocalDate effDate1   = LocalDate.of(2011, 3, 20);   //note this is a Sunday - for a standard CDS this would roll to the Monday.

            YIELD_CURVES[1] = createRatesProvider(tradeDate1, snapDate1, 1d, 0.4);
            tenors          = new Period[] { Period.ofMonths(6), Period.ofYears(1), Period.ofYears(3), Period.ofYears(5), Period.ofYears(7), Period.ofYears(10) };
            nTenors         = tenors.Length;
            NODE_CDS[1]     = new CdsIsdaCreditCurveNode[nTenors];
            ImmutableMarketDataBuilder builderCredit1 = ImmutableMarketData.builder(tradeDate1);

            EXP_NODE_CDS[1] = new ResolvedCdsTrade[nTenors];
            SPREADS[1]      = new double[] { 0.027, 0.018, 0.012, 0.009, 0.007, 0.006 };
            for (int i = 0; i < nTenors; ++i)
            {
                Cds product = Cds.of(BUY, LEGAL_ENTITY, EUR, 1d, effDate1, LocalDate.of(2011, 6, 20).plus(tenors[i]), P3M, DEFAULT_CALENDAR, SPREADS[1][i]);
                EXP_NODE_CDS[1][i] = CdsTrade.builder().info(TradeInfo.builder().settlementDate(product.SettlementDateOffset.adjust(tradeDate1, REF_DATA)).build()).product(product).build().resolve(REF_DATA);
                CdsConvention conv = ImmutableCdsConvention.builder().name("conv").currency(EUR).dayCount(ACT_360).paymentFrequency(P3M).startDateBusinessDayAdjustment(BusinessDayAdjustment.NONE).businessDayAdjustment(BUS_ADJ).settlementDateOffset(CDS_SETTLE_STD).build();
                CdsTemplate   temp = DatesCdsTemplate.of(effDate1, LocalDate.of(2011, 6, 20).plus(tenors[i]), conv);
                QuoteId       id   = QuoteId.of(StandardId.of("OG", tenors[i].ToString()));
                NODE_CDS[1][i] = CdsIsdaCreditCurveNode.ofParSpread(temp, id, LEGAL_ENTITY);
                builderCredit1.addValue(id, SPREADS[1][i]);
            }
            CDS_MARKET_DATA[1] = builderCredit1.build();
            // case2
            LocalDate tradeDate2 = LocalDate.of(2011, 5, 30);
            LocalDate snapDate2  = LocalDate.of(2011, 5, 29);

            YIELD_CURVES[2] = createRatesProvider(tradeDate2, snapDate2, 1d, 0.25);
            LocalDate[] matDates2  = new LocalDate[] { LocalDate.of(2011, 6, 20), LocalDate.of(2012, 5, 30), LocalDate.of(2014, 6, 20), LocalDate.of(2016, 6, 20), LocalDate.of(2018, 6, 20) };
            int         nMatDates2 = matDates2.Length;

            NODE_CDS[2] = new CdsIsdaCreditCurveNode[nMatDates2];
            ImmutableMarketDataBuilder builderCredit2 = ImmutableMarketData.builder(tradeDate2);

            EXP_NODE_CDS[2] = new ResolvedCdsTrade[nMatDates2];
            SPREADS[2]      = new double[] { 0.05, 0.05, 0.05, 0.05, 0.05 };
            for (int i = 0; i < nMatDates2; ++i)
            {
                Cds product = Cds.of(BUY, LEGAL_ENTITY, EUR, 1d, tradeDate2.plusDays(1), matDates2[i], P3M, DEFAULT_CALENDAR, SPREADS[2][i]).toBuilder().dayCount(THIRTY_U_360).build();
                EXP_NODE_CDS[2][i] = CdsTrade.builder().info(TradeInfo.builder().settlementDate(product.SettlementDateOffset.adjust(tradeDate2, REF_DATA)).build()).product(product).build().resolve(REF_DATA);
                CdsConvention conv = ImmutableCdsConvention.builder().name("conv").currency(EUR).dayCount(THIRTY_U_360).paymentFrequency(P3M).rollConvention(RollConventions.NONE).businessDayAdjustment(BUS_ADJ).settlementDateOffset(CDS_SETTLE_STD).build();
                CdsTemplate   temp = DatesCdsTemplate.of(tradeDate2.plusDays(1), matDates2[i], conv);
                QuoteId       id   = QuoteId.of(StandardId.of("OG", matDates2[i].ToString()));
                NODE_CDS[2][i] = CdsIsdaCreditCurveNode.ofParSpread(temp, id, LEGAL_ENTITY);
                builderCredit2.addValue(id, SPREADS[2][i]);
            }
            CDS_MARKET_DATA[2] = builderCredit2.build();
            // case3
            LocalDate tradeDate3 = LocalDate.of(2011, 5, 30);
            LocalDate snapDate3  = LocalDate.of(2011, 5, 29);
            LocalDate effDate3   = LocalDate.of(2011, 7, 31);

            YIELD_CURVES[3] = createRatesProvider(tradeDate3, snapDate3, 1d, 0.25);
            LocalDate[] matDates3  = new LocalDate[] { LocalDate.of(2011, 11, 30), LocalDate.of(2012, 5, 30), LocalDate.of(2014, 5, 30), LocalDate.of(2016, 5, 30), LocalDate.of(2018, 5, 30), LocalDate.of(2021, 5, 30) };
            int         nMatDates3 = matDates3.Length;

            NODE_CDS[3] = new CdsIsdaCreditCurveNode[nMatDates3];
            ImmutableMarketDataBuilder builderCredit3 = ImmutableMarketData.builder(tradeDate3);

            EXP_NODE_CDS[3] = new ResolvedCdsTrade[nMatDates3];
            SPREADS[3]      = new double[] { 0.07, 0.06, 0.05, 0.055, 0.06, 0.065 };
            for (int i = 0; i < nMatDates3; ++i)
            {
                Cds product = Cds.builder().buySell(BUY).legalEntityId(LEGAL_ENTITY).currency(EUR).dayCount(ACT_365F).fixedRate(SPREADS[3][i]).notional(1d).paymentSchedule(PeriodicSchedule.builder().businessDayAdjustment(BusinessDayAdjustment.of(FOLLOWING, DEFAULT_CALENDAR)).startDate(effDate3).endDate(matDates3[i]).startDateBusinessDayAdjustment(BusinessDayAdjustment.NONE).endDateBusinessDayAdjustment(BusinessDayAdjustment.NONE).frequency(Frequency.P6M).rollConvention(RollConventions.NONE).stubConvention(StubConvention.LONG_INITIAL).build()).paymentOnDefault(PaymentOnDefault.ACCRUED_PREMIUM).protectionStart(ProtectionStartOfDay.BEGINNING).stepinDateOffset(DaysAdjustment.ofCalendarDays(1)).settlementDateOffset(CDS_SETTLE_STD).build();
                EXP_NODE_CDS[3][i] = CdsTrade.builder().info(TradeInfo.builder().settlementDate(product.SettlementDateOffset.adjust(tradeDate3, REF_DATA)).build()).product(product).build().resolve(REF_DATA);
                CdsConvention conv = ImmutableCdsConvention.builder().name("conv").currency(EUR).dayCount(ACT_365F).paymentFrequency(Frequency.P6M).rollConvention(RollConventions.NONE).stubConvention(StubConvention.LONG_INITIAL).startDateBusinessDayAdjustment(BusinessDayAdjustment.NONE).businessDayAdjustment(BusinessDayAdjustment.of(FOLLOWING, DEFAULT_CALENDAR)).settlementDateOffset(CDS_SETTLE_STD).build();
                CdsTemplate   temp = DatesCdsTemplate.of(effDate3, matDates3[i], conv);
                QuoteId       id   = QuoteId.of(StandardId.of("OG", matDates3[i].ToString()));
                NODE_CDS[3][i] = CdsIsdaCreditCurveNode.ofParSpread(temp, id, LEGAL_ENTITY);
                builderCredit3.addValue(id, SPREADS[3][i]);
            }
            CDS_MARKET_DATA[3] = builderCredit3.build();
            // case4: designed to trip the low rates/low spreads branch
            LocalDate tradeDate4 = LocalDate.of(2014, 1, 14);
            LocalDate snapDate4  = LocalDate.of(2014, 1, 13);

            YIELD_CURVES[4] = createRatesProvider(tradeDate4, snapDate4, 1d / 1000d, 0.4);
            int nSpreads4 = 6;

            NODE_CDS[4] = new CdsIsdaCreditCurveNode[nSpreads4];
            ImmutableMarketDataBuilder builderCredit4 = ImmutableMarketData.builder(tradeDate4);

            SPREADS[4] = new double[nSpreads4];
            Arrays.fill(SPREADS[4], 1.0e-4);
            EXP_NODE_CDS[4] = new ResolvedCdsTrade[nSpreads4];
            for (int i = 0; i < nSpreads4; ++i)
            {
                Cds product = Cds.of(BUY, LEGAL_ENTITY, EUR, 1d, LocalDate.of(2013, 12, 20), LocalDate.of(2014, 3, 20).plus(tenors[i]), P3M, DEFAULT_CALENDAR, SPREADS[4][i]);
                EXP_NODE_CDS[4][i] = CdsTrade.builder().info(TradeInfo.builder().settlementDate(product.SettlementDateOffset.adjust(tradeDate4, REF_DATA)).build()).product(product).build().resolve(REF_DATA);
                CdsConvention conv = ImmutableCdsConvention.of("conv", EUR, ACT_360, P3M, BUS_ADJ, CDS_SETTLE_STD);
                CdsTemplate   temp = DatesCdsTemplate.of(LocalDate.of(2013, 12, 20), LocalDate.of(2014, 3, 20).plus(tenors[i]), conv);
                QuoteId       id   = QuoteId.of(StandardId.of("OG", tenors[i].ToString()));
                NODE_CDS[4][i] = CdsIsdaCreditCurveNode.ofParSpread(temp, id, LEGAL_ENTITY);
                builderCredit4.addValue(id, SPREADS[4][i]);
            }
            CDS_MARKET_DATA[4] = builderCredit4.build();
        }