Exemple #1
0
        public void testCachedValue()
        {
            //"Testing swaption value against cached value...");

            CommonVars vars = new CommonVars();

            vars.today = new Date(13, 3, 2002);
            vars.settlement = new Date(15, 3, 2002);
            Settings.setEvaluationDate( vars.today);
            vars.termStructure.linkTo(Utilities.flatRate(vars.settlement, 0.05, new Actual365Fixed()));
            Date exerciseDate = vars.calendar.advance(vars.settlement, new Period(5,TimeUnit.Years));
            Date startDate = vars.calendar.advance(exerciseDate,
                                                   vars.settlementDays,TimeUnit.Days);
            VanillaSwap swap =
                new MakeVanillaSwap(new Period(10,TimeUnit.Years), vars.index, 0.06)
                .withEffectiveDate(startDate);

            Swaption swaption =
                vars.makeSwaption(swap, exerciseDate, 0.20);
            //#if QL_USE_INDEXED_COUPON
                double cachedNPV = 0.036418158579;
            //#else
            //    double cachedNPV = 0.036421429684;
            //#endif

            // FLOATING_POINT_EXCEPTION
            if (Math.Abs(swaption.NPV()-cachedNPV) > 1.0e-12)
                Assert.Fail ("failed to reproduce cached swaption value:\n" +
                            //QL_FIXED + std::setprecision(12) +
                            "\ncalculated: " + swaption.NPV() +
                            "\nexpected:   " + cachedNPV);
        }
Exemple #2
0
        public RendistatoCalculator(RendistatoBasket basket, Euribor euriborIndex, Handle <YieldTermStructure> discountCurve)
        {
            basket_            = basket;
            euriborIndex_      = euriborIndex;
            discountCurve_     = discountCurve;
            yields_            = new InitializedList <double>(basket_.size(), 0.05);
            durations_         = new List <double>(basket_.size());
            nSwaps_            = 15; // TODO: generalize number of swaps and their lenghts
            swaps_             = new List <VanillaSwap>(nSwaps_);
            swapLenghts_       = new List <double>(nSwaps_);
            swapBondDurations_ = new InitializedList <double?>(nSwaps_, null);
            swapBondYields_    = new InitializedList <double?>(nSwaps_, 0.05);
            swapRates_         = new InitializedList <double?>(nSwaps_, null);

            basket_.registerWith(update);
            euriborIndex_.registerWith(update);
            discountCurve_.registerWith(update);

            double dummyRate = 0.05;

            for (int i = 0; i < nSwaps_; ++i)
            {
                swapLenghts_[i] = (i + 1);
                swaps_[i]       = new MakeVanillaSwap(new Period((int)swapLenghts_[i], TimeUnit.Years),
                                                      euriborIndex_, dummyRate, new Period(1, TimeUnit.Days))
                                  .withDiscountingTermStructure(discountCurve_);
            }
        }
Exemple #3
0
 public MakeCapFloor(CapFloorType capFloorType, Period tenor, IborIndex iborIndex, double?strike = null,
                     Period forwardStart = null)
 {
     capFloorType_        = capFloorType;
     strike_              = strike;
     firstCapletExcluded_ = (forwardStart == new Period(0, TimeUnit.Days));
     asOptionlet_         = false;
     makeVanillaSwap_     = new MakeVanillaSwap(tenor, iborIndex, 0.0, forwardStart);
 }
Exemple #4
0
        public Swaption value()
        {
            Date     evaluationDate = Settings.evaluationDate();
            Calendar fixingCalendar = swapIndex_.fixingCalendar();

            fixingDate_ = fixingCalendar.advance(evaluationDate, optionTenor_, optionConvention_);

            if (exerciseDate_ == null)
            {
                exercise_ = new EuropeanExercise(fixingDate_);
            }
            else
            {
                Utils.QL_REQUIRE(exerciseDate_ <= fixingDate_, () =>
                                 "exercise date (" + exerciseDate_ + ") must be less " + "than or equal to fixing date (" + fixingDate_ + ")");
                exercise_ = new EuropeanExercise(exerciseDate_);
            }

            double usedStrike;

            if (strike_ == null)
            {
                // ATM on the forecasting curve
                Utils.QL_REQUIRE(!swapIndex_.forwardingTermStructure().empty(), () =>
                                 "no forecasting term structure set to " + swapIndex_.name());
                VanillaSwap temp = swapIndex_.underlyingSwap(fixingDate_);
                temp.setPricingEngine(new DiscountingSwapEngine(swapIndex_.forwardingTermStructure()));
                usedStrike = temp.fairRate();
            }
            else
            {
                usedStrike = strike_.Value;
            }

            BusinessDayConvention bdc = swapIndex_.fixedLegConvention();

            underlyingSwap_ = new MakeVanillaSwap(swapIndex_.tenor(),
                                                  swapIndex_.iborIndex(),
                                                  usedStrike)
                              .withEffectiveDate(swapIndex_.valueDate(fixingDate_))
                              .withFixedLegCalendar(swapIndex_.fixingCalendar())
                              .withFixedLegDayCount(swapIndex_.dayCounter())
                              .withFixedLegConvention(bdc)
                              .withFixedLegTerminationDateConvention(bdc);

            Swaption swaption = new Swaption(underlyingSwap_, exercise_, delivery_);

            swaption.setPricingEngine(engine_);
            return(swaption);
        }
Exemple #5
0
        public void testImpliedVolatility()
        {
            //"Testing implied volatility for swaptions...";

            CommonVars vars=new CommonVars();

            int maxEvaluations = 100;
            double tolerance = 1.0e-08;

            Settlement.Type[] types = { Settlement.Type.Physical, Settlement.Type.Cash };
            // test data
            double[] strikes = { 0.02, 0.03, 0.04, 0.05, 0.06, 0.07 };
            double[] vols = { 0.01, 0.05, 0.10, 0.20, 0.30, 0.70, 0.90 };

            for (int i = 0; i < exercises.Length; i++)
            {
                for (int j = 0; j < lengths.Length; j++)
                {
                    Date exerciseDate = vars.calendar.advance(vars.today, exercises[i]);
                    Date startDate = vars.calendar.advance(exerciseDate,
                                                           vars.settlementDays, TimeUnit.Days);
                    Date maturity = vars.calendar.advance(startDate, lengths[j],
                                                          vars.floatingConvention);
                    for (int t = 0; t < strikes.Length; t++)
                    {
                        for (int k = 0; k < type.Length; k++)
                        {
                            VanillaSwap swap = new MakeVanillaSwap(lengths[j], vars.index, strikes[t])
                                        .withEffectiveDate(startDate)
                                        .withFloatingLegSpread(0.0)
                                        .withType(type[k]);
                            for (int h = 0; h < types.Length; h++)
                            {
                                for (int u = 0; u < vols.Length; u++)
                                {
                                    Swaption swaption = vars.makeSwaption(swap, exerciseDate,
                                                                            vols[u], types[h]);
                                    // Black price
                                    double value = swaption.NPV();
                                    double implVol = 0.0;
                                    try
                                    {
                                        implVol =
                                          swaption.impliedVolatility(value,
                                                                      vars.termStructure,
                                                                      0.10,
                                                                      tolerance,
                                                                      maxEvaluations);
                                    }
                                    catch (System.Exception e)
                                    {
                                        // couldn't bracket?
                                        swaption.setPricingEngine(vars.makeEngine(0.0));
                                        double value2 = swaption.NPV();
                                        if (Math.Abs(value - value2) < tolerance)
                                        {
                                            // ok, just skip:
                                            continue;
                                        }
                                        // otherwise, report error
                                        Assert.Fail("implied vol failure: " +
                                                    exercises[i] + "x" + lengths[j] + " " + type[k] +
                                                    "\nsettlement: " + types[h] +
                                                    "\nstrike      " + strikes[t] +
                                                    "\natm level:  " + swap.fairRate() +
                                                    "\nvol:        " + vols[u] +
                                                    "\nprice:      " + value +
                                                    "\n" + e.Message.ToString());
                                    }
                                    if (Math.Abs(implVol - vols[u]) > tolerance)
                                    {
                                        // the difference might not matter
                                        swaption.setPricingEngine(vars.makeEngine(implVol));
                                        double value2 = swaption.NPV();
                                        if (Math.Abs(value - value2) > tolerance)
                                        {
                                            Assert.Fail("implied vol failure: " +
                                                exercises[i] + "x" + lengths[j] + " " + type[k] +
                                                "\nsettlement:    " + types[h] +
                                                "\nstrike         " + strikes[t] +
                                                "\natm level:     " + swap.fairRate() +
                                                "\nvol:           " + vols[u] +
                                                "\nprice:         " + value +
                                                "\nimplied vol:   " + implVol +
                                                "\nimplied price: " + value2);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Exemple #6
0
        public void testVega()
        {
            //"Testing swaption vega...";

            CommonVars vars = new CommonVars();

            Settlement.Type[] types = { Settlement.Type.Physical, Settlement.Type.Cash };
            double[] strikes = { 0.03, 0.04, 0.05, 0.06, 0.07 };
            double[] vols = { 0.01, 0.20, 0.30, 0.70, 0.90 };
            double shift = 1e-8;
            for (int i=0; i<exercises.Length ; i++) {
                Date exerciseDate = vars.calendar.advance(vars.today, exercises[i]);
                // A VERIFIER§§§§
                Date startDate = vars.calendar.advance(exerciseDate,
                                                   vars.settlementDays, TimeUnit.Days);
                for (int j=0; j<lengths.Length ; j++) {
                    for (int t=0; t<strikes.Length ; t++) {
                        for (int h=0; h<type.Length ; h++) {
                            VanillaSwap swap =
                                new MakeVanillaSwap(lengths[j], vars.index, strikes[t])
                                        .withEffectiveDate(startDate)
                                        .withFloatingLegSpread(0.0)
                                        .withType(type[h]);
                            for (int u=0; u<vols.Length ; u++) {
                                Swaption swaption =
                                    vars.makeSwaption(swap, exerciseDate,
                                                      vols[u], types[h]);
                                // FLOATING_POINT_EXCEPTION
                                Swaption swaption1 =
                                    vars.makeSwaption(swap, exerciseDate,
                                                      vols[u]-shift, types[h]);
                                Swaption swaption2 =
                                    vars.makeSwaption(swap, exerciseDate,
                                                      vols[u]+shift, types[h]);

                                double swaptionNPV = swaption.NPV();
                                double numericalVegaPerPoint =
                                    (swaption2.NPV()-swaption1.NPV())/(200.0*shift);
                                // check only relevant vega
                                if (numericalVegaPerPoint/swaptionNPV>1.0e-7) {
                                    double analyticalVegaPerPoint =
                                        (double)swaption.result("vega")/100.0;
                                    double discrepancy = Math.Abs(analyticalVegaPerPoint
                                        - numericalVegaPerPoint);
                                    discrepancy /= numericalVegaPerPoint;
                                    double tolerance = 0.015;
                                    if (discrepancy > tolerance)
                                        Assert.Fail ("failed to compute swaption vega:" +
                                            "\n  option tenor:    " + exercises[i] +
                                            "\n  volatility:      " + vols[u] +
                                            "\n  option type:     " + swaption.type() +
                                            "\n  swap tenor:      " + lengths[j] +
                                            "\n  strike:          " + strikes[t] +
                                            "\n  settlement:      " + types[h] +
                                            "\n  nominal:         " + swaption.underlyingSwap().nominal +
                                            "\n  npv:             " + swaptionNPV +
                                            "\n  calculated vega: " + analyticalVegaPerPoint +
                                            "\n  expected vega:   " + numericalVegaPerPoint +
                                            "\n  discrepancy:     " + discrepancy +
                                            "\n  tolerance:       " + tolerance);
                                }
                            }
                        }
                    }
                }
            }
        }
Exemple #7
0
        public void testStrikeDependency()
        {
            //("Testing swaption dependency on strike......");

            CommonVars vars = new CommonVars();
            double[] strikes = new double[] { 0.03, 0.04, 0.05, 0.06, 0.07 };

            for (int i = 0; i <  exercises.Length; i++)  {
                for (int j = 0; j < lengths.Length; j++) {
                    for (int k=0; k < type.Length ; k++) {
                        Date exerciseDate = vars.calendar.advance(vars.today,
                                                          exercises[i]);
                        Date startDate = vars.calendar.advance(exerciseDate,
                                         vars.settlementDays, TimeUnit.Days);
                        // store the results for different rates...
                        List<double> values = new InitializedList<double>(strikes.Length);
                        List<double> values_cash = new InitializedList<double>(strikes.Length);
                        double vol = 0.20;

                        for (int l=0; l< strikes.Length ; l++) {
                            VanillaSwap swap    = new MakeVanillaSwap(lengths[j], vars.index, strikes[l])
                                                    .withEffectiveDate(startDate)
                                                    .withFloatingLegSpread(0.0)
                                                    .withType(type[k]);
                            Swaption swaption   = vars.makeSwaption(swap,exerciseDate,vol);
                            // FLOATING_POINT_EXCEPTION
                            values[l]=swaption.NPV();
                            Swaption swaption_cash = vars.makeSwaption( swap,exerciseDate,vol,
                                                                        Settlement.Type.Cash);
                            values_cash[l]=swaption_cash.NPV();
                        }

                        // and check that they go the right way
                        if (type[k]==VanillaSwap.Type.Payer) {
                            for (int z = 0; z < values.Count - 1; z++)
                            {
                                if( values[z]<values[z+1]){
                                Assert.Fail("NPV of Payer swaption with delivery settlement"+
                                            "is increasing with the strike:" +
                                            "\noption tenor: " + exercises[i] +
                                            "\noption date:  " + exerciseDate +
                                            "\nvolatility:   " + vol +
                                            "\nswap tenor:   " + lengths[j] +
                                            "\nvalue:        " + values[z  ] +" at strike: " + strikes[z  ] +
                                            "\nvalue:        " + values[z+1] + " at strike: " + strikes[z+1]);
                                }
                            }
                            for (int z = 0; z < values_cash.Count - 1; z++)
                            {
                                if (values_cash[z] < values_cash[z + 1])
                                {
                                    Assert.Fail("NPV of Payer swaption with cash settlement" +
                                        "is increasing with the strike:" +
                                        "\noption tenor: " + exercises[i] +
                                        "\noption date:  " + exerciseDate +
                                        "\nvolatility:   " + vol +
                                        "\nswap tenor:   " + lengths[j] +
                                        "\nvalue:        " + values_cash[z] + " at strike: " + strikes[z] +
                                        "\nvalue:        " + values_cash[z + 1] + " at strike: " + strikes[z + 1]);
                                }
                            }
                        }
                        else {
                            for (int z = 0; z < values.Count - 1; z++){
                                if (values[z] > values[z+1]){
                                    Assert.Fail("NPV of Receiver swaption with delivery settlement" +
                                                "is increasing with the strike:" +
                                                "\noption tenor: " + exercises[i] +
                                                "\noption date:  " + exerciseDate +
                                                "\nvolatility:   " + vol +
                                                "\nswap tenor:   " + lengths[j] +
                                                "\nvalue:        " + values[z] + " at strike: " + strikes[z] +
                                                "\nvalue:        " + values[z + 1] + " at strike: " + strikes[z + 1]);
                                }
                            }
                            for (int z = 0; z < values_cash.Count - 1; z++)
                            {
                                if (values[z] > values[z+1])
                                {
                                    Assert.Fail("NPV of Receiver swaption with cash settlement" +
                                        "is increasing with the strike:" +
                                        "\noption tenor: " + exercises[i] +
                                        "\noption date:  " + exerciseDate +
                                        "\nvolatility:   " + vol +
                                        "\nswap tenor:   " + lengths[j] +
                                        "\nvalue:        " + values_cash[z] + " at strike: " + strikes[z] +
                                        "\nvalue:        " + values_cash[z + 1] + " at strike: " + strikes[z + 1]);
                                }
                            }
                        }
                    }
                }
            }
        }
Exemple #8
0
        public void testSpreadTreatment()
        {
            //"Testing swaption treatment of spread...";

            CommonVars vars = new CommonVars();

            double[] spreads = { -0.002, -0.001, 0.0, 0.001, 0.002 };

            for (int i=0; i<exercises.Length; i++) {
                for (int j=0; j<lengths.Length ; j++) {
                    for (int k=0; k<type.Length ; k++) {
                        Date exerciseDate = vars.calendar.advance(vars.today,
                                                                  exercises[i]);
                        Date startDate =
                            vars.calendar.advance(exerciseDate,
                                                  vars.settlementDays,TimeUnit.Days);
                        for (int l=0; l<spreads.Length ; l++) {
                            VanillaSwap swap =
                                new MakeVanillaSwap(lengths[j], vars.index, 0.06)
                                        .withEffectiveDate(startDate)
                                        .withFloatingLegSpread(spreads[l])
                                        .withType(type[k]);
                            // FLOATING_POINT_EXCEPTION
                            double correction = spreads[l] *
                                                swap.floatingLegBPS() /
                                                swap.fixedLegBPS();
                            VanillaSwap equivalentSwap =
                                new MakeVanillaSwap(lengths[j], vars.index, 0.06+correction)
                                        .withEffectiveDate(startDate)
                                        .withFloatingLegSpread(0.0)
                                        .withType(type[k]);
                            Swaption swaption1 =
                                vars.makeSwaption(swap,exerciseDate,0.20);
                            Swaption swaption2 =
                                vars.makeSwaption(equivalentSwap,exerciseDate,0.20);
                            Swaption swaption1_cash =
                                vars.makeSwaption(swap,exerciseDate,0.20,
                                                  Settlement.Type.Cash);
                            Swaption swaption2_cash =
                                vars.makeSwaption(equivalentSwap,exerciseDate,0.20,
                                                  Settlement.Type.Cash);
                            if (Math.Abs(swaption1.NPV()-swaption2.NPV()) > 1.0e-6)
                                Assert.Fail("wrong spread treatment:" +
                                    "\nexercise: " + exerciseDate +
                                    "\nlength:   " + lengths[j] +
                                    "\ntype      " + type[k] +
                                    "\nspread:   " + spreads[l] +
                                    "\noriginal swaption value:   " + swaption1.NPV() +
                                    "\nequivalent swaption value: " + swaption2.NPV());

                            if (Math.Abs(swaption1_cash.NPV()-swaption2_cash.NPV()) > 1.0e-6)
                                Assert.Fail("wrong spread treatment:" +
                                    "\nexercise date: " + exerciseDate +
                                    "\nlength: " + lengths[j] +
                                    //"\npay " + (type[k] ? "fixed" : "floating") +
                                    "\nspread: " + spreads[l] +
                                    "\nvalue of original swaption:   "  + swaption1_cash.NPV() +
                                    "\nvalue of equivalent swaption: "  + swaption2_cash.NPV());
                        }
                    }
                }
            }
        }
Exemple #9
0
        public void testSpreadDependency()
        {
            //"Testing swaption dependency on spread...";

            CommonVars vars = new CommonVars();

            double[] spreads = { -0.002, -0.001, 0.0, 0.001, 0.002 };

            for (int i=0; i<exercises.Length ; i++) {
                for (int j=0; j<lengths.Length ; j++) {
                    for (int k=0; k<type.Length ; k++) {
                        Date exerciseDate = vars.calendar.advance(vars.today,
                                                                  exercises[i]);
                        Date startDate =
                            vars.calendar.advance(exerciseDate,
                                                  vars.settlementDays,TimeUnit.Days);
                        // store the results for different rates...
                        List<double> values=new InitializedList<double>(spreads.Length);
                        List<double> values_cash = new InitializedList<double>(spreads.Length);
                        for (int l=0; l<spreads.Length; l++) {
                             VanillaSwap swap =
                               new MakeVanillaSwap(lengths[j], vars.index, 0.06)
                                        .withEffectiveDate(startDate)
                                        .withFloatingLegSpread(spreads[l])
                                        .withType(type[k]);
                             Swaption swaption =
                                vars.makeSwaption(swap,exerciseDate,0.20);
                            // FLOATING_POINT_EXCEPTION
                            values[l]=swaption.NPV();
                            Swaption swaption_cash =
                                vars.makeSwaption(swap,exerciseDate,0.20,
                                                  Settlement.Type.Cash);
                            values_cash[l]=swaption_cash.NPV();
                        }
                        // and check that they go the right way
                        if (type[k]==VanillaSwap.Type.Payer) {
                            for (int n = 0; n < spreads.Length - 1; n++)
                            {
                                if (values[n] > values[n + 1])
                                    Assert.Fail("NPV is decreasing with the spread " +
                                        "in a payer swaption (physical delivered):" +
                                        "\nexercise date: " + exerciseDate +
                                        "\nlength:        " + lengths[j] +
                                        "\nvalue:         " + values[n] + " for spread: " + spreads[n] +
                                        "\nvalue:         " + values[n + 1] + " for spread: " + spreads[n + 1]);

                                if (values_cash[n] > values_cash[n + 1])
                                    Assert.Fail("NPV is decreasing with the spread " +
                                        "in a payer swaption (cash delivered):" +
                                        "\nexercise date: " + exerciseDate +
                                        "\nlength: " + lengths[j] +
                                        "\nvalue:  " + values_cash[n] + " for spread: " + spreads[n] +
                                        "\nvalue:  " + values_cash[n + 1] + " for spread: " + spreads[n + 1]);
                            }
                        }
                        else
                        {
                            for (int n = 0; n < spreads.Length - 1; n++)
                            {
                                if (values[n] < values[n + 1])
                                    Assert.Fail("NPV is increasing with the spread " +
                                        "in a receiver swaption (physical delivered):" +
                                        "\nexercise date: " + exerciseDate +
                                        "\nlength: " + lengths[j] +
                                        "\nvalue:  " + values[n] + " for spread: " + spreads[n] +
                                        "\nvalue:  " + values[n + 1] + " for spread: " + spreads[n + 1]);

                                if (values_cash[n] < values_cash[n+1])
                                Assert.Fail("NPV is increasing with the spread " +
                                    "in a receiver swaption (cash delivered):" +
                                    "\nexercise date: " + exerciseDate +
                                    "\nlength: " + lengths[j] +
                                    "\nvalue:  " + values_cash[n  ] + " for spread: " + spreads[n] +
                                    "\nvalue:  " + values_cash[n+1] + " for spread: " + spreads[n+1]);
                            }
                        }
                    }
                }
            }
        }
Exemple #10
0
      public RendistatoCalculator(RendistatoBasket basket, Euribor euriborIndex, Handle<YieldTermStructure> discountCurve)
      {
         basket_ = basket;
         euriborIndex_ = euriborIndex;
         discountCurve_ = discountCurve;
         yields_ = new InitializedList<double>(basket_.size(), 0.05); 
         durations_ = new List<double>(basket_.size());
         nSwaps_ = 15;  // TODO: generalize number of swaps and their lenghts
         swaps_ = new List<VanillaSwap>(nSwaps_);
         swapLenghts_ = new List<double>(nSwaps_);
         swapBondDurations_ = new InitializedList<double?>(nSwaps_, null);
         swapBondYields_ = new InitializedList<double?>(nSwaps_, 0.05);
         swapRates_ = new InitializedList<double?>(nSwaps_, null);

         basket_.registerWith(update);
         euriborIndex_.registerWith(update);
         discountCurve_.registerWith(update);

         double dummyRate = 0.05;
         for (int i=0; i<nSwaps_; ++i) 
         {
            swapLenghts_[i] = (i+1);
            swaps_[i] = new MakeVanillaSwap( new Period((int)swapLenghts_[i],TimeUnit.Years), 
                                             euriborIndex_, dummyRate, new Period(1,TimeUnit.Days))
                                             .withDiscountingTermStructure(discountCurve_);
         }
      }
Exemple #11
0
        public override void calculate()
        {
            /* both DTS, YTS ref dates and pricing date consistency
             * checks? settlement... */
            Utils.QL_REQUIRE(!discountCurve_.empty(), () => "no discount term structure set");
            Utils.QL_REQUIRE(!defaultTS_.empty(), () => "no ctpty default term structure set");
            Utils.QL_REQUIRE(!swaptionletEngine_.empty(), () => "no swap option engine set");

            Date priceDate = defaultTS_.link.referenceDate();

            double cumOptVal = 0.0, cumPutVal = 0.0;
            // Vanilla swap so 0 leg is floater

            int  index        = 0;
            Date nextFD       = arguments_.fixedPayDates[index];
            Date swapletStart = priceDate;

            while (nextFD < priceDate)
            {
                index++;
                nextFD = arguments_.fixedPayDates[index];
            }


            // Compute fair spread for strike value:
            // copy args into the non risky engine
            Swap.Arguments noCVAArgs = baseSwapEngine_.link.getArguments() as Swap.Arguments;

            noCVAArgs.legs  = this.arguments_.legs;
            noCVAArgs.payer = this.arguments_.payer;

            baseSwapEngine_.link.calculate();

            double baseSwapRate = ((FixedRateCoupon)arguments_.legs[0][0]).rate();

            Swap.Results vSResults = baseSwapEngine_.link.getResults() as Swap.Results;

            double?baseSwapFairRate = -baseSwapRate * vSResults.legNPV[1] / vSResults.legNPV[0];
            double?baseSwapNPV      = vSResults.value;

            VanillaSwap.Type reversedType = arguments_.type == VanillaSwap.Type.Payer
                                         ? VanillaSwap.Type.Receiver
                                         : VanillaSwap.Type.Payer;

            // Swaplet options summatory:
            while (nextFD != arguments_.fixedPayDates.Last())
            {
                // iFD coupon not fixed, create swaptionlet:
                IborIndex swapIndex = ((FloatingRateCoupon)arguments_.legs[1][0]).index() as IborIndex;

                // Alternatively one could cap this period to, say, 1M
                Period baseSwapsTenor = new Period(arguments_.fixedPayDates.Last().serialNumber()
                                                   - swapletStart.serialNumber(), TimeUnit.Days);
                VanillaSwap swaplet = new MakeVanillaSwap(baseSwapsTenor, swapIndex, baseSwapFairRate)
                                      .withType(arguments_.type)
                                      .withNominal(arguments_.nominal)
                                      .withEffectiveDate(swapletStart)
                                      .withTerminationDate(arguments_.fixedPayDates.Last()).value();

                VanillaSwap revSwaplet = new MakeVanillaSwap(baseSwapsTenor, swapIndex, baseSwapFairRate)
                                         .withType(reversedType)
                                         .withNominal(arguments_.nominal)
                                         .withEffectiveDate(swapletStart)
                                         .withTerminationDate(arguments_.fixedPayDates.Last()).value();

                Swaption swaptionlet = new Swaption(swaplet, new EuropeanExercise(swapletStart));
                Swaption putSwaplet  = new Swaption(revSwaplet, new EuropeanExercise(swapletStart));
                swaptionlet.setPricingEngine(swaptionletEngine_.currentLink());
                putSwaplet.setPricingEngine(swaptionletEngine_.currentLink());

                // atm underlying swap means that the value of put = value
                // call so this double pricing is not needed
                cumOptVal += swaptionlet.NPV() * defaultTS_.link.defaultProbability(
                    swapletStart, nextFD);
                cumPutVal += putSwaplet.NPV() * invstDTS_.link.defaultProbability(swapletStart, nextFD);

                swapletStart = nextFD;
                index++;
                nextFD = arguments_.fixedPayDates[index];
            }

            results_.value    = baseSwapNPV - (1.0 - ctptyRecoveryRate_) * cumOptVal + (1.0 - invstRecoveryRate_) * cumPutVal;
            results_.fairRate = -baseSwapRate * (vSResults.legNPV[1] - (1.0 - ctptyRecoveryRate_) * cumOptVal +
                                                 (1.0 - invstRecoveryRate_) * cumPutVal) / vSResults.legNPV[0];
        }