Exemple #1
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);
        }
    }
}
Exemple #2
0
        public Swap value()
        {
            Date startDate;

            if (effectiveDate_ != null)
            {
                startDate = effectiveDate_;
            }
            else
            {
                int  fixingDays = iborIndex_.fixingDays();
                Date refDate    = Settings.Instance.evaluationDate();
                // if the evaluation date is not a business day
                // then move to the next business day
                refDate = floatCalendar_.adjust(refDate);
                Date spotDate = floatCalendar_.advance(refDate, new Period(fixingDays, TimeUnit.Days));
                startDate = spotDate + forwardStart_;
            }

            Date terminationDate = maturityDate_ == null ? startDate + swapTenor_ : maturityDate_;

            Schedule cmsSchedule = new Schedule(startDate, terminationDate,
                                                cmsTenor_, cmsCalendar_,
                                                cmsConvention_,
                                                cmsTerminationDateConvention_,
                                                cmsRule_, cmsEndOfMonth_,
                                                cmsFirstDate_, cmsNextToLastDate_);

            Schedule floatSchedule = new Schedule(startDate, terminationDate,
                                                  floatTenor_, floatCalendar_,
                                                  floatConvention_,
                                                  floatTerminationDateConvention_,
                                                  floatRule_, floatEndOfMonth_,
                                                  floatFirstDate_, floatNextToLastDate_);

            List <CashFlow> cmsLeg = new CmsLeg(cmsSchedule, swapIndex_)
                                     .withPaymentDayCounter(cmsDayCount_)
                                     .withFixingDays(swapIndex_.fixingDays())
                                     .withGearings(cmsGearing_)
                                     .withSpreads(cmsSpread_)
                                     .withCaps(cmsCap_)
                                     .withFloors(cmsFloor_)
                                     .withNotionals(nominal_)
                                     .withPaymentAdjustment(cmsConvention_);

            if (couponPricer_ != null)
            {
                Utils.setCouponPricer(cmsLeg, couponPricer_);
            }

            double?usedSpread = iborSpread_;

            if (useAtmSpread_)
            {
                Utils.QL_REQUIRE(!iborIndex_.forwardingTermStructure().empty(), () =>
                                 "null term structure set to this instance of " + iborIndex_.name());
                Utils.QL_REQUIRE(!swapIndex_.forwardingTermStructure().empty(), () =>
                                 "null term structure set to this instance of " + swapIndex_.name());
                Utils.QL_REQUIRE(couponPricer_ != null, () => "no CmsCouponPricer set (yet)");
                List <CashFlow> fLeg = new IborLeg(floatSchedule, iborIndex_)
                                       .withPaymentDayCounter(floatDayCount_)
                                       .withFixingDays(iborIndex_.fixingDays())
                                       .withCaps(iborCap_)
                                       .withFloors(iborFloor_)
                                       .withNotionals(nominal_)
                                       .withPaymentAdjustment(floatConvention_);

                if (iborCouponPricer_ != null)
                {
                    Utils.setCouponPricer(fLeg, iborCouponPricer_);
                }

                Swap temp = new Swap(cmsLeg, fLeg);
                temp.setPricingEngine(engine_);

                double?npv = temp.legNPV(0) + temp.legNPV(1);

                usedSpread = -npv / temp.legBPS(1) * 1e-4;
            }
            else
            {
                Utils.QL_REQUIRE(usedSpread.HasValue, () => "null spread set");
            }

            List <CashFlow> floatLeg = new IborLeg(floatSchedule, iborIndex_)
                                       .withSpreads(usedSpread.Value)
                                       .withPaymentDayCounter(floatDayCount_)
                                       .withFixingDays(iborIndex_.fixingDays())
                                       .withGearings(iborGearing_)
                                       .withCaps(iborCap_)
                                       .withFloors(iborFloor_)
                                       .withPaymentAdjustment(floatConvention_)
                                       .withNotionals(nominal_);

            if (iborCouponPricer_ != null)
            {
                Utils.setCouponPricer(floatLeg, iborCouponPricer_);
            }

            Swap swap;

            if (payCms_)
            {
                swap = new Swap(cmsLeg, floatLeg);
            }
            else
            {
                swap = new Swap(floatLeg, cmsLeg);
            }
            swap.setPricingEngine(engine_);
            return(swap);
        }
        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;
            }
        }