//===========================================================================// // 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_; }
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_ = coupon_.swapIndex(); forwardCurve_ = swapIndex_.forwardingTermStructure(); if (swapIndex_.exogenousDiscount()) { discountCurve_ = swapIndex_.discountingTermStructure(); } else { discountCurve_ = forwardCurve_; } // if no coupon discount curve is given just use the discounting curve // from the swap index. for rate 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_ = QLCore.Settings.Instance.evaluationDate(); if (paymentDate_ > today_ && !couponDiscountCurve_.empty()) { couponDiscountRatio_ = couponDiscountCurve_.link.discount(paymentDate_) / discountCurve_.link.discount(paymentDate_); } else { couponDiscountRatio_ = 1.0; } spreadLegValue_ = spread_ * coupon_.accrualPeriod() * discountCurve_.link.discount(paymentDate_) * couponDiscountRatio_; if (fixingDate_ > today_) { swapTenor_ = swapIndex_.tenor(); swap_ = swapIndex_.underlyingSwap(fixingDate_); swapRateValue_ = swap_.fairRate(); annuity_ = 1.0E4 * Math.Abs(swap_.fixedLegBPS()); SmileSection sectionTmp = swaptionVolatility().link.smileSection(fixingDate_, swapTenor_); // adjust bounds by section's shift shiftedLowerBound_ = settings_.lowerRateBound_ - sectionTmp.shift(); shiftedUpperBound_ = settings_.upperRateBound_ - sectionTmp.shift(); // if the section does not provide an atm level, we enhance it to // have one, no need to exit with an exception ... if (sectionTmp.atmLevel() == null) { smileSection_ = new AtmSmileSection(sectionTmp, swapRateValue_); } else { smileSection_ = sectionTmp; } // compute linear model's parameters double gx = 0.0, gy = 0.0; for (int i = 0; i < swap_.fixedLeg().Count; i++) { Coupon c = swap_.fixedLeg()[i] as Coupon; double yf = c.accrualPeriod(); Date d = c.date(); double pv = yf * discountCurve_.link.discount(d); gx += pv * GsrG(d); gy += pv; } double gamma = gx / gy; Date lastd = swap_.fixedLeg().Last().date(); a_ = discountCurve_.link.discount(paymentDate_) * (gamma - GsrG(paymentDate_)) / (discountCurve_.link.discount(lastd) * GsrG(lastd) + swapRateValue_ * gy * gamma); b_ = discountCurve_.link.discount(paymentDate_) / gy - a_ * swapRateValue_; } }