示例#1
0
        public override void initialize(FloatingRateCoupon coupon)
        {
            coupon_ = coupon as CmsSpreadCoupon;
            Utils.QL_REQUIRE(coupon_ != null, () => "CMS spread coupon needed");
            index_   = coupon_.swapSpreadIndex();
            gearing_ = coupon_.gearing();
            spread_  = coupon_.spread();

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

            // if no coupon discount curve is given just use the discounting curve
            // from the _first_ swap index.
            // for double calculation this curve cancels out in the computation, so
            // e.g. the discounting
            // swap engine will produce correct results, even if the
            // couponDiscountCurve is not set here.
            // only the price member function in this class will be dependent on the
            // coupon discount curve.

            today_ = Settings.Instance.evaluationDate();

            if (couponDiscountCurve_.empty())
            {
                couponDiscountCurve_ =
                    index_.swapIndex1().exogenousDiscount()
                        ? index_.swapIndex1().discountingTermStructure()
                        : index_.swapIndex1().forwardingTermStructure();
            }

            discount_ = paymentDate_ > couponDiscountCurve_.currentLink().referenceDate()
                            ? couponDiscountCurve_.currentLink().discount(paymentDate_)
                            : 1.0;

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

            gearing1_ = index_.gearing1();
            gearing2_ = index_.gearing2();

            Utils.QL_REQUIRE(gearing1_ > 0.0 && gearing2_ < 0.0,
                             () => "gearing1 (" + gearing1_
                             + ") should be positive while gearing2 ("
                             + gearing2_ + ") should be negative");

            c1_ = new CmsCoupon(
                coupon_.nominal(), coupon_.date(), coupon_.accrualStartDate(),
                coupon_.accrualEndDate(), coupon_.fixingDays,
                index_.swapIndex1(), 1.0, 0.0, coupon_.referencePeriodStart,
                coupon_.referencePeriodEnd, coupon_.dayCounter(),
                coupon_.isInArrears());

            c2_ = new CmsCoupon(
                coupon_.nominal(), coupon_.date(), coupon_.accrualStartDate(),
                coupon_.accrualEndDate(), coupon_.fixingDays,
                index_.swapIndex2(), 1.0, 0.0, coupon_.referencePeriodStart,
                coupon_.referencePeriodEnd, coupon_.dayCounter(),
                coupon_.isInArrears());

            c1_.setPricer(cmsPricer1_);
            c2_.setPricer(cmsPricer2_);

            if (fixingDate_ > today_)
            {
                fixingTime_ = cmsPricer1_.swaptionVolatility().currentLink().timeFromReference(
                    fixingDate_);

                swapRate1_ = c1_.indexFixing();
                swapRate2_ = c2_.indexFixing();

                adjustedFixing1_ = c1_.adjustedFixing;
                adjustedFixing2_ = c2_.adjustedFixing;

                SwaptionVolatilityStructure swvol = cmsPricer1_.swaptionVolatility();
                SwaptionVolatilityCube      swcub = swvol as SwaptionVolatilityCube;

                if (inheritedVolatilityType_ && volType_ == VolatilityType.ShiftedLognormal)
                {
                    shift1_ =
                        swvol.shift(fixingDate_, index_.swapIndex1().tenor());
                    shift2_ =
                        swvol.shift(fixingDate_, index_.swapIndex2().tenor());
                }

                if (swcub == null)
                {
                    // not a cube, just an atm surface given, so we can
                    // not easily convert volatilities and just forbid it
                    Utils.QL_REQUIRE(inheritedVolatilityType_,
                                     () => "if only an atm surface is given, the volatility type must be inherited");
                    vol1_ = swvol.volatility(
                        fixingDate_, index_.swapIndex1().tenor(), swapRate1_);
                    vol2_ = swvol.volatility(
                        fixingDate_, index_.swapIndex2().tenor(), swapRate2_);
                }
                else
                {
                    vol1_ = swcub.smileSection(fixingDate_,
                                               index_.swapIndex1().tenor())
                            .volatility(swapRate1_, volType_, shift1_);
                    vol2_ = swcub.smileSection(fixingDate_,
                                               index_.swapIndex2().tenor())
                            .volatility(swapRate2_, volType_, shift2_);
                }

                if (volType_ == VolatilityType.ShiftedLognormal)
                {
                    mu1_ = 1.0 / fixingTime_ * Math.Log((adjustedFixing1_ + shift1_) /
                                                        (swapRate1_ + shift1_));
                    mu2_ = 1.0 / fixingTime_ * Math.Log((adjustedFixing2_ + shift2_) /
                                                        (swapRate2_ + shift2_));
                }
                // for the normal volatility case we do not need the drifts
                // but rather use adjusted doubles directly in the integrand

                rho_ = Math.Max(Math.Min(correlation().currentLink().value(), 0.9999),
                                -0.9999); // avoid division by zero in integrand
            }
            else
            {
                // fixing is in the past or today
                adjustedFixing1_ = c1_.indexFixing();
                adjustedFixing2_ = c2_.indexFixing();
            }
        }