Example #1
0
        public SwapSpreadIndex(String familyName,
                               SwapIndex swapIndex1,
                               SwapIndex swapIndex2,
                               double gearing1 = 1.0,
                               double gearing2 = -1.0)
            : base(familyName, swapIndex1.tenor(), // does not make sense, but we have to provide one
                   swapIndex1.fixingDays(), swapIndex1.currency(), swapIndex1.fixingCalendar(), swapIndex1.dayCounter())
        {
            swapIndex1_ = swapIndex1;
            swapIndex2_ = swapIndex2;
            gearing1_   = gearing1;
            gearing2_   = gearing2;

            swapIndex1_.registerWith(update);
            swapIndex2_.registerWith(update);

            name_ = swapIndex1_.name() + "(" + gearing1 + ") + "
                    + swapIndex2_.name() + "(" + gearing1 + ")";

            Utils.QL_REQUIRE(swapIndex1_.fixingDays() == swapIndex2_.fixingDays(), () =>
                             "index1 fixing days ("
                             + swapIndex1_.fixingDays() + ")"
                             + "must be equal to index2 fixing days ("
                             + swapIndex2_.fixingDays() + ")");

            Utils.QL_REQUIRE(swapIndex1_.fixingCalendar() == swapIndex2_.fixingCalendar(), () =>
                             "index1 fixingCalendar ("
                             + swapIndex1_.fixingCalendar() + ")"
                             + "must be equal to index2 fixingCalendar ("
                             + swapIndex2_.fixingCalendar() + ")");

            Utils.QL_REQUIRE(swapIndex1_.currency() == swapIndex2_.currency(), () =>
                             "index1 currency (" + swapIndex1_.currency() + ")"
                             + "must be equal to index2 currency ("
                             + swapIndex2_.currency() + ")");

            Utils.QL_REQUIRE(swapIndex1_.dayCounter() == swapIndex2_.dayCounter(), () =>
                             "index1 dayCounter ("
                             + swapIndex1_.dayCounter() + ")"
                             + "must be equal to index2 dayCounter ("
                             + swapIndex2_.dayCounter() + ")");

            Utils.QL_REQUIRE(swapIndex1_.fixedLegTenor() == swapIndex2_.fixedLegTenor(), () =>
                             "index1 fixedLegTenor ("
                             + swapIndex1_.fixedLegTenor() + ")"
                             + "must be equal to index2 fixedLegTenor ("
                             + swapIndex2_.fixedLegTenor());

            Utils.QL_REQUIRE(swapIndex1_.fixedLegConvention() == swapIndex2_.fixedLegConvention(), () =>
                             "index1 fixedLegConvention ("
                             + swapIndex1_.fixedLegConvention() + ")"
                             + "must be equal to index2 fixedLegConvention ("
                             + swapIndex2_.fixedLegConvention());
        }
Example #2
0
 public DigitalCmsLeg(Schedule schedule, SwapIndex index)
 {
     schedule_          = schedule;
     index_             = index;
     paymentAdjustment_ = BusinessDayConvention.Following;
     inArrears_         = false;
     longCallOption_    = Position.Type.Long;
     callATM_           = false;
     longPutOption_     = Position.Type.Long;
     putATM_            = false;
 }
Example #3
0
 public CmsCoupon(double nominal,
                  Date paymentDate,
                  Date startDate,
                  Date endDate,
                  int fixingDays,
                  SwapIndex swapIndex,
                  double gearing        = 1.0,
                  double spread         = 0.0,
                  Date refPeriodStart   = null,
                  Date refPeriodEnd     = null,
                  DayCounter dayCounter = null,
                  bool isInArrears      = false)
     : base(paymentDate, nominal, startDate, endDate, fixingDays, swapIndex, gearing, spread, refPeriodStart, refPeriodEnd, dayCounter, isInArrears)
 {
     swapIndex_ = swapIndex;
 }
 public SwaptionVolCube2(Handle <SwaptionVolatilityStructure> atmVolStructure,
                         List <Period> optionTenors,
                         List <Period> swapTenors,
                         List <double> strikeSpreads,
                         List <List <Handle <Quote> > > volSpreads,
                         SwapIndex swapIndexBase,
                         SwapIndex shortSwapIndexBase,
                         bool vegaWeightedSmileFit)
     : base(atmVolStructure, optionTenors, swapTenors, strikeSpreads, volSpreads, swapIndexBase,
            shortSwapIndexBase, vegaWeightedSmileFit)
 {
     volSpreadsInterpolator_ = new List <Interpolation2D>();
     volSpreadsMatrix_       = new List <Matrix>(nStrikes_);
     for (int i = 0; i < nStrikes_; i++)
     {
         volSpreadsMatrix_.Add(new Matrix(optionTenors.Count, swapTenors.Count, 0.0));
     }
 }
Example #5
0
 public MakeCms(Period swapTenor,
                SwapIndex swapIndex,
                IborIndex iborIndex,
                double iborSpread   = 0.0,
                Period forwardStart = null,
                Date maturityDate   = null)
 {
     swapTenor_     = swapTenor;
     swapIndex_     = swapIndex;
     iborIndex_     = iborIndex;
     iborSpread_    = iborSpread;
     iborCap_       = null;
     iborFloor_     = null;
     useAtmSpread_  = false;
     forwardStart_  = forwardStart ?? new Period(0, TimeUnit.Days);
     cmsSpread_     = 0.0;
     cmsGearing_    = 1.0;
     cmsCap_        = null;
     cmsFloor_      = null;
     effectiveDate_ = null;
     cmsCalendar_   = swapIndex.fixingCalendar();
     floatCalendar_ = iborIndex.fixingCalendar();
     payCms_        = true;
     nominal_       = 1.0;
     maturityDate_  = maturityDate;
     cmsTenor_      = new Period(3, TimeUnit.Months);
     floatTenor_    = iborIndex.tenor();
     cmsConvention_ = BusinessDayConvention.ModifiedFollowing;
     cmsTerminationDateConvention_ = BusinessDayConvention.ModifiedFollowing;
     floatConvention_ = iborIndex.businessDayConvention();
     floatTerminationDateConvention_ = iborIndex.businessDayConvention();
     cmsRule_             = DateGeneration.Rule.Backward;
     floatRule_           = DateGeneration.Rule.Backward;
     cmsEndOfMonth_       = false;
     floatEndOfMonth_     = false;
     cmsFirstDate_        = null;
     cmsNextToLastDate_   = null;
     floatFirstDate_      = null;
     floatNextToLastDate_ = null;
     cmsDayCount_         = new Actual360();
     floatDayCount_       = iborIndex.dayCounter();
     engine_ = new DiscountingSwapEngine(swapIndex.forwardingTermStructure());
 }
Example #6
0
            //===========================================================================//
            //                            GFunctionWithShifts                            //
            //===========================================================================//
            public GFunctionWithShifts(CmsCoupon coupon, Handle <Quote> meanReversion)
            {
                meanReversion_   = meanReversion;
                calibratedShift_ = 0.03;
                tmpRs_           = 10000000.0;
                accuracy_        = 1.0e-14;

                SwapIndex   swapIndex = coupon.swapIndex();
                VanillaSwap swap      = swapIndex.underlyingSwap(coupon.fixingDate());

                swapRateValue_ = swap.fairRate();

                objectiveFunction_ = new ObjectiveFunction(this, swapRateValue_);

                Schedule schedule = swap.fixedSchedule();
                Handle <YieldTermStructure> rateCurve = swapIndex.forwardingTermStructure();
                DayCounter dc = swapIndex.dayCounter();

                swapStartTime_   = dc.yearFraction(rateCurve.link.referenceDate(), schedule.startDate());
                discountAtStart_ = rateCurve.link.discount(schedule.startDate());

                double paymentTime = dc.yearFraction(rateCurve.link.referenceDate(), coupon.date());

                shapedPaymentTime_ = shapeOfShift(paymentTime);

                List <CashFlow> fixedLeg = new List <CashFlow>(swap.fixedLeg());
                int             n        = fixedLeg.Count;

                shapedSwapPaymentTimes_ = new List <double>();
                swapPaymentDiscounts_   = new List <double>();
                accruals_ = new List <double>();

                for (int i = 0; i < n; ++i)
                {
                    Coupon coupon1 = fixedLeg[i] as Coupon;
                    accruals_.Add(coupon1.accrualPeriod());
                    Date   paymentDate     = new Date(coupon1.date().serialNumber());
                    double swapPaymentTime = dc.yearFraction(rateCurve.link.referenceDate(), paymentDate);
                    shapedSwapPaymentTimes_.Add(shapeOfShift(swapPaymentTime));
                    swapPaymentDiscounts_.Add(rateCurve.link.discount(paymentDate));
                }
                discountRatio_ = swapPaymentDiscounts_.Last() / discountAtStart_;
            }
Example #7
0
        public override void initialize(FloatingRateCoupon coupon)
        {
            coupon_ = coupon as CmsCoupon;
            Utils.QL_REQUIRE(coupon_ != null, () => "CMS coupon needed");
            gearing_ = coupon_.gearing();
            spread_  = coupon_.spread();

            fixingDate_  = coupon_.fixingDate();
            paymentDate_ = coupon_.date();
            SwapIndex swapIndex = coupon_.swapIndex();

            rateCurve_ = swapIndex.forwardingTermStructure().link;

            Date today = Settings.Instance.evaluationDate();

            if (paymentDate_ > today)
            {
                discount_ = rateCurve_.discount(paymentDate_);
            }
            else
            {
                discount_ = 1.0;
            }

            spreadLegValue_ = spread_ * coupon_.accrualPeriod() * discount_;

            if (fixingDate_ > today)
            {
                swapTenor_ = swapIndex.tenor();
                VanillaSwap swap = swapIndex.underlyingSwap(fixingDate_);

                swapRateValue_ = swap.fairRate();

                annuity_ = Math.Abs(swap.fixedLegBPS() / Const.BASIS_POINT);

                int        q                    = (int)swapIndex.fixedLegTenor().frequency();
                Schedule   schedule             = swap.fixedSchedule();
                DayCounter dc                   = swapIndex.dayCounter();
                double     startTime            = dc.yearFraction(rateCurve_.referenceDate(), swap.startDate());
                double     swapFirstPaymentTime = dc.yearFraction(rateCurve_.referenceDate(), schedule.date(1));
                double     paymentTime          = dc.yearFraction(rateCurve_.referenceDate(), paymentDate_);
                double     delta                = (paymentTime - startTime) / (swapFirstPaymentTime - startTime);

                switch (modelOfYieldCurve_)
                {
                case GFunctionFactory.YieldCurveModel.Standard:
                    gFunction_ = GFunctionFactory.newGFunctionStandard(q, delta, swapTenor_.length());
                    break;

                case GFunctionFactory.YieldCurveModel.ExactYield:
                    gFunction_ = GFunctionFactory.newGFunctionExactYield(coupon_);
                    break;

                case GFunctionFactory.YieldCurveModel.ParallelShifts:
                {
                    Handle <Quote> nullMeanReversionQuote = new Handle <Quote>(new SimpleQuote(0.0));
                    gFunction_ = GFunctionFactory.newGFunctionWithShifts(coupon_, nullMeanReversionQuote);
                }
                break;

                case GFunctionFactory.YieldCurveModel.NonParallelShifts:
                    gFunction_ = GFunctionFactory.newGFunctionWithShifts(coupon_, meanReversion_);
                    break;

                default:
                    Utils.QL_FAIL("unknown/illegal gFunction type");
                    break;
                }
                vanillaOptionPricer_ = new BlackVanillaOptionPricer(swapRateValue_, fixingDate_, swapTenor_, swaptionVolatility().link);
            }
        }
Example #8
0
        public AmortizingCmsRateBond(int settlementDays,
                                     List <double> notionals,
                                     Schedule schedule,
                                     SwapIndex index,
                                     DayCounter paymentDayCounter,
                                     BusinessDayConvention paymentConvention = BusinessDayConvention.Following,
                                     int fixingDays         = 0,
                                     List <double> gearings = null,
                                     List <double> spreads  = null,
                                     List <double?> caps    = null,
                                     List <double?> floors  = null,
                                     bool inArrears         = false,
                                     Date issueDate         = null)
            : base(settlementDays, schedule.calendar(), issueDate)
        {
            // Optional value check
            if (gearings == null)
            {
                gearings = new List <double>()
                {
                    1.0
                }
            }
            ;
            if (spreads == null)
            {
                spreads = new List <double>()
                {
                    0
                }
            }
            ;
            if (caps == null)
            {
                caps = new List <double?>();
            }
            if (floors == null)
            {
                floors = new List <double?>();
            }

            maturityDate_ = schedule.endDate();

            cashflows_ = new CmsLeg(schedule, index)
                         .withPaymentDayCounter(paymentDayCounter)
                         .withFixingDays(fixingDays)
                         .withGearings(gearings)
                         .withSpreads(spreads)
                         .withCaps(caps)
                         .withFloors(floors)
                         .inArrears(inArrears)
                         .withNotionals(notionals)
                         .withPaymentAdjustment(paymentConvention);

            addRedemptionsToCashflows();

            Utils.QL_REQUIRE(!cashflows().empty(), () => "bond with no cashflows!");

            index.registerWith(update);
        }
    }
}
Example #9
0
        private void init(BusinessDayConvention?paymentConvention1, BusinessDayConvention?paymentConvention2)
        {
            Utils.QL_REQUIRE(nominal1_.Count == schedule1_.Count - 1, () =>
                             "nominal1 size (" + nominal1_.Count +
                             ") does not match schedule1 size (" + schedule1_.size() + ")");
            Utils.QL_REQUIRE(nominal2_.Count == schedule2_.Count - 1, () =>
                             "nominal2 size (" + nominal2_.Count + ") does not match schedule2 size ("
                             + nominal2_.Count + ")");
            Utils.QL_REQUIRE(gearing1_.Count == 0 || gearing1_.Count == nominal1_.Count, () =>
                             "nominal1 size (" + nominal1_.Count + ") does not match gearing1 size ("
                             + gearing1_.Count + ")");
            Utils.QL_REQUIRE(gearing2_.Count == 0 || gearing2_.Count == nominal2_.Count, () =>
                             "nominal2 size (" + nominal2_.Count + ") does not match gearing2 size ("
                             + gearing2_.Count + ")");
            Utils.QL_REQUIRE(cappedRate1_.Count == 0 || cappedRate1_.Count == nominal1_.Count, () =>
                             "nominal1 size (" + nominal1_.Count + ") does not match cappedRate1 size ("
                             + cappedRate1_.Count + ")");
            Utils.QL_REQUIRE(cappedRate2_.Count == 0 || cappedRate2_.Count == nominal2_.Count, () =>
                             "nominal2 size (" + nominal2_.Count + ") does not match cappedRate2 size ("
                             + cappedRate2_.Count + ")");
            Utils.QL_REQUIRE(flooredRate1_.Count == 0 || flooredRate1_.Count == nominal1_.Count, () =>
                             "nominal1 size (" + nominal1_.Count + ") does not match flooredRate1 size ("
                             + flooredRate1_.Count + ")");
            Utils.QL_REQUIRE(flooredRate2_.Count == 0 || flooredRate2_.Count == nominal2_.Count, () =>
                             "nominal2 size (" + nominal2_.Count + ") does not match flooredRate2 size ("
                             + flooredRate2_.Count + ")");

            if (paymentConvention1 != null)
            {
                paymentConvention1_ = paymentConvention1.Value;
            }
            else
            {
                paymentConvention1_ = schedule1_.businessDayConvention();
            }

            if (paymentConvention2 != null)
            {
                paymentConvention2_ = paymentConvention2.Value;
            }
            else
            {
                paymentConvention2_ = schedule2_.businessDayConvention();
            }

            if (gearing1_.Count == 0)
            {
                gearing1_ = new InitializedList <double>(nominal1_.Count, 1.0);
            }
            if (gearing2_.Count == 0)
            {
                gearing2_ = new InitializedList <double>(nominal2_.Count, 1.0);
            }
            if (spread1_.Count == 0)
            {
                spread1_ = new InitializedList <double>(nominal1_.Count, 0.0);
            }
            if (spread2_.Count == 0)
            {
                spread2_ = new InitializedList <double>(nominal2_.Count, 0.0);
            }
            if (cappedRate1_.Count == 0)
            {
                cappedRate1_ = new InitializedList <double?>(nominal1_.Count, null);
            }
            if (cappedRate2_.Count == 0)
            {
                cappedRate2_ = new InitializedList <double?>(nominal2_.Count, null);
            }
            if (flooredRate1_.Count == 0)
            {
                flooredRate1_ = new InitializedList <double?>(nominal1_.Count, null);
            }
            if (flooredRate2_.Count == 0)
            {
                flooredRate2_ = new InitializedList <double?>(nominal2_.Count, null);
            }

            bool isNull = cappedRate1_[0] == null;

            for (int i = 0; i < cappedRate1_.Count; i++)
            {
                if (isNull)
                {
                    Utils.QL_REQUIRE(cappedRate1_[i] == null, () =>
                                     "cappedRate1 must be null for all or none entry (" + (i + 1)
                                     + "th is " + cappedRate1_[i] + ")");
                }
                else
                {
                    Utils.QL_REQUIRE(cappedRate1_[i] != null, () =>
                                     "cappedRate 1 must be null for all or none entry ("
                                     + "1st is " + cappedRate1_[0] + ")");
                }
            }
            isNull = cappedRate2_[0] == null;
            for (int i = 0; i < cappedRate2_.Count; i++)
            {
                if (isNull)
                {
                    Utils.QL_REQUIRE(cappedRate2_[i] == null, () =>
                                     "cappedRate2 must be null for all or none entry ("
                                     + (i + 1) + "th is " + cappedRate2_[i] + ")");
                }
                else
                {
                    Utils.QL_REQUIRE(cappedRate2_[i] != null, () =>
                                     "cappedRate2 must be null for all or none entry ("
                                     + "1st is " + cappedRate2_[0] + ")");
                }
            }
            isNull = flooredRate1_[0] == null;
            for (int i = 0; i < flooredRate1_.Count; i++)
            {
                if (isNull)
                {
                    Utils.QL_REQUIRE(flooredRate1_[i] == null, () =>
                                     "flooredRate1 must be null for all or none entry ("
                                     + (i + 1) + "th is " + flooredRate1_[i]
                                     + ")");
                }
                else
                {
                    Utils.QL_REQUIRE(flooredRate1_[i] != null, () =>
                                     "flooredRate 1 must be null for all or none entry ("
                                     + "1st is " + flooredRate1_[0] + ")");
                }
            }
            isNull = flooredRate2_[0] == null;
            for (int i = 0; i < flooredRate2_.Count; i++)
            {
                if (isNull)
                {
                    Utils.QL_REQUIRE(flooredRate2_[i] == null, () =>
                                     "flooredRate2 must be null for all or none entry ("
                                     + (i + 1) + "th is " + flooredRate2_[i]
                                     + ")");
                }
                else
                {
                    Utils.QL_REQUIRE(flooredRate2_[i] != null, () =>
                                     "flooredRate2 must be null for all or none entry ("
                                     + "1st is " + flooredRate2_[0] + ")");
                }
            }

            // if the gearing is zero then the ibor / cms leg will be set up with
            // fixed coupons which makes trouble here in this context. We therefore
            // use a dirty trick and enforce the gearing to be non zero.
            for (int i = 0; i < gearing1_.Count; i++)
            {
                if (Utils.close(gearing1_[i], 0.0))
                {
                    gearing1_[i] = Const.QL_EPSILON;
                }
            }
            for (int i = 0; i < gearing2_.Count; i++)
            {
                if (Utils.close(gearing2_[i], 0.0))
                {
                    gearing2_[i] = Const.QL_EPSILON;
                }
            }

            IborIndex       ibor1      = index1_ as IborIndex;
            IborIndex       ibor2      = index2_ as IborIndex;
            SwapIndex       cms1       = index1_ as SwapIndex;
            SwapIndex       cms2       = index2_ as SwapIndex;
            SwapSpreadIndex cmsspread1 = index1_ as SwapSpreadIndex;
            SwapSpreadIndex cmsspread2 = index2_ as SwapSpreadIndex;

            Utils.QL_REQUIRE(ibor1 != null || cms1 != null || cmsspread1 != null, () =>
                             "index1 must be ibor or cms or cms spread");
            Utils.QL_REQUIRE(ibor2 != null || cms2 != null || cmsspread2 != null, () =>
                             "index2 must be ibor or cms");

            if (ibor1 != null)
            {
                IborLeg leg = new IborLeg(schedule1_, ibor1);
                leg = (IborLeg)leg.withPaymentDayCounter(dayCount1_)
                      .withSpreads(spread1_)
                      .withGearings(gearing1_)
                      .withPaymentAdjustment(paymentConvention1_)
                      .withNotionals(nominal1_);

                if (cappedRate1_[0] != null)
                {
                    leg = (IborLeg)leg.withCaps(cappedRate1_);
                }
                if (flooredRate1_[0] != null)
                {
                    leg = (IborLeg)leg.withFloors(flooredRate1_);
                }
                legs_[0] = leg;
            }

            if (ibor2 != null)
            {
                IborLeg leg = new IborLeg(schedule2_, ibor2);
                leg = (IborLeg)leg.withPaymentDayCounter(dayCount2_)
                      .withSpreads(spread2_)
                      .withGearings(gearing2_)
                      .withPaymentAdjustment(paymentConvention2_)
                      .withNotionals(nominal2_);

                if (cappedRate2_[0] != null)
                {
                    leg = (IborLeg)leg.withCaps(cappedRate2_);
                }
                if (flooredRate2_[0] != null)
                {
                    leg = (IborLeg)leg.withFloors(flooredRate2_);
                }
                legs_[1] = leg;
            }

            if (cms1 != null)
            {
                CmsLeg leg = new CmsLeg(schedule1_, cms1);
                leg = (CmsLeg)leg.withPaymentDayCounter(dayCount1_)
                      .withSpreads(spread1_)
                      .withGearings(gearing1_)
                      .withNotionals(nominal1_)
                      .withPaymentAdjustment(paymentConvention1_);

                if (cappedRate1_[0] != null)
                {
                    leg = (CmsLeg)leg.withCaps(cappedRate1_);
                }
                if (flooredRate1_[0] != null)
                {
                    leg = (CmsLeg)leg.withFloors(flooredRate1_);
                }
                legs_[0] = leg;
            }

            if (cms2 != null)
            {
                CmsLeg leg = new CmsLeg(schedule2_, cms2);
                leg = (CmsLeg)leg.withPaymentDayCounter(dayCount2_)
                      .withSpreads(spread2_)
                      .withGearings(gearing2_)
                      .withNotionals(nominal2_)
                      .withPaymentAdjustment(paymentConvention2_);

                if (cappedRate2_[0] != null)
                {
                    leg = (CmsLeg)leg.withCaps(cappedRate2_);
                }
                if (flooredRate2_[0] != null)
                {
                    leg = (CmsLeg)leg.withFloors(flooredRate2_);
                }
                legs_[1] = leg;
            }

            if (cmsspread1 != null)
            {
                CmsSpreadLeg leg = new CmsSpreadLeg(schedule1_, cmsspread1);
                leg = (CmsSpreadLeg)leg.withPaymentDayCounter(dayCount1_)
                      .withSpreads(spread1_)
                      .withGearings(gearing1_)
                      .withNotionals(nominal1_)
                      .withPaymentAdjustment(paymentConvention1_);
                if (cappedRate1_[0] != null)
                {
                    leg = (CmsSpreadLeg)leg.withCaps(cappedRate1_);
                }
                if (flooredRate1_[0] != null)
                {
                    leg = (CmsSpreadLeg)leg.withFloors(flooredRate1_);
                }
                legs_[0] = leg;
            }

            if (cmsspread2 != null)
            {
                CmsSpreadLeg leg = new CmsSpreadLeg(schedule2_, cmsspread2);
                leg = (CmsSpreadLeg)leg.withPaymentDayCounter(dayCount2_)
                      .withSpreads(spread2_)
                      .withGearings(gearing2_)
                      .withNotionals(nominal2_)
                      .withPaymentAdjustment(paymentConvention2_);

                if (cappedRate2_[0] != null)
                {
                    leg = (CmsSpreadLeg)leg.withCaps(cappedRate2_);
                }
                if (flooredRate2_[0] != null)
                {
                    leg = (CmsSpreadLeg)leg.withFloors(flooredRate2_);
                }
                legs_[1] = leg;
            }

            if (intermediateCapitalExchange_)
            {
                for (int i = 0; i < legs_[0].Count - 1; i++)
                {
                    double cap = nominal1_[i] - nominal1_[i + 1];
                    if (!Utils.close(cap, 0.0))
                    {
                        legs_[0].Insert(i + 1, new Redemption(cap, legs_[0][i].date()));
                        nominal1_.Insert(i + 1, nominal1_[i]);
                        i++;
                    }
                }
                for (int i = 0; i < legs_[1].Count - 1; i++)
                {
                    double cap = nominal2_[i] - nominal2_[i + 1];
                    if (!Utils.close(cap, 0.0))
                    {
                        legs_[1].Insert(i + 1, new Redemption(cap, legs_[1][i].date()));
                        nominal2_.Insert(i + 1, nominal2_[i]);
                        i++;
                    }
                }
            }

            if (finalCapitalExchange_)
            {
                legs_[0].Add(new Redemption(nominal1_.Last(), legs_[0].Last().date()));
                nominal1_.Add(nominal1_.Last());
                legs_[1].Add(new Redemption(nominal2_.Last(), legs_[1].Last().date()));
                nominal2_.Add(nominal2_.Last());
            }

            foreach (var c in legs_[0])
            {
                c.registerWith(update);
            }

            foreach (var c in legs_[1])
            {
                c.registerWith(update);
            }

            switch (type_)
            {
            case VanillaSwap.Type.Payer:
                payer_[0] = -1.0;
                payer_[1] = +1.0;
                break;

            case VanillaSwap.Type.Receiver:
                payer_[0] = +1.0;
                payer_[1] = -1.0;
                break;

            default:
                Utils.QL_FAIL("Unknown float float - swap type");
                break;
            }
        }