public ZeroCouponInflationSwapHelper( Handle <Quote> quote, Period swapObsLag, // lag on swap observation of index Date maturity, Calendar calendar, // index may have null calendar as valid on every day BusinessDayConvention paymentConvention, DayCounter dayCounter, ZeroInflationIndex zii) : base(quote) { swapObsLag_ = swapObsLag; maturity_ = maturity; calendar_ = calendar; paymentConvention_ = paymentConvention; dayCounter_ = dayCounter; zii_ = zii; if (zii_.interpolated()) { // if interpolated then simple earliestDate_ = maturity_ - swapObsLag_; latestDate_ = maturity_ - swapObsLag_; } else { // but if NOT interpolated then the value is valid // for every day in an inflation period so you actually // get an extended validity, however for curve building // just put the first date because using that convention // for the base date throughout KeyValuePair <Date, Date> limStart = Utils.inflationPeriod(maturity_ - swapObsLag_, zii_.frequency()); earliestDate_ = limStart.Key; latestDate_ = limStart.Key; } // check that the observation lag of the swap // is compatible with the availability lag of the index AND // it's interpolation (assuming the start day is spot) if (zii_.interpolated()) { Period pShift = new Period(zii_.frequency()); Utils.QL_REQUIRE((swapObsLag_ - pShift) > zii_.availabilityLag(), () => "inconsistency between swap observation of index " + swapObsLag_ + " index availability " + zii_.availabilityLag() + " index period " + pShift + " and index availability " + zii_.availabilityLag() + " need (obsLag-index period) > availLag"); } Settings.Instance.registerWith(update); }
/* Generally inflation indices are available with a lag of 1month * and then observed with a lag of 2-3 months depending whether * they use an interpolated fixing or not. Here, we make the * swap use the interpolation of the index to avoid incompatibilities. */ public ZeroCouponInflationSwap(Type type, double nominal, Date startDate, // start date of contract (only) Date maturity, // this is pre-adjustment! Calendar fixCalendar, BusinessDayConvention fixConvention, DayCounter dayCounter, double fixedRate, ZeroInflationIndex infIndex, Period observationLag, bool adjustInfObsDates = false, Calendar infCalendar = null, BusinessDayConvention?infConvention = null) : base(2) { type_ = type; nominal_ = nominal; startDate_ = startDate; maturityDate_ = maturity; fixCalendar_ = fixCalendar; fixConvention_ = fixConvention; fixedRate_ = fixedRate; infIndex_ = infIndex; observationLag_ = observationLag; adjustInfObsDates_ = adjustInfObsDates; infCalendar_ = infCalendar; dayCounter_ = dayCounter; // first check compatibility of index and swap definitions if (infIndex_.interpolated()) { Period pShift = new Period(infIndex_.frequency()); Utils.QL_REQUIRE(observationLag_ - pShift > infIndex_.availabilityLag(), () => "inconsistency between swap observation of index " + observationLag_ + " index availability " + infIndex_.availabilityLag() + " interpolated index period " + pShift + " and index availability " + infIndex_.availabilityLag() + " need (obsLag-index period) > availLag"); } else { Utils.QL_REQUIRE(infIndex_.availabilityLag() < observationLag_, () => "index tries to observe inflation fixings that do not yet exist: " + " availability lag " + infIndex_.availabilityLag() + " versus obs lag = " + observationLag_); } if (infCalendar_ == null) { infCalendar_ = fixCalendar_; } if (infConvention == null) { infConvention_ = fixConvention_; } else { infConvention_ = infConvention.Value; } if (adjustInfObsDates_) { baseDate_ = infCalendar_.adjust(startDate - observationLag_, infConvention_); obsDate_ = infCalendar_.adjust(maturity - observationLag_, infConvention_); } else { baseDate_ = startDate - observationLag_; obsDate_ = maturity - observationLag_; } Date infPayDate = infCalendar_.adjust(maturity, infConvention_); Date fixedPayDate = fixCalendar_.adjust(maturity, fixConvention_); // At this point the index may not be able to forecast // i.e. do not want to force the existence of an inflation // term structure before allowing users to create instruments. double T = Utils.inflationYearFraction(infIndex_.frequency(), infIndex_.interpolated(), dayCounter_, baseDate_, obsDate_); // N.B. the -1.0 is because swaps only exchange growth, not notionals as well double fixedAmount = nominal * (Math.Pow(1.0 + fixedRate, T) - 1.0); legs_[0].Add(new SimpleCashFlow(fixedAmount, fixedPayDate)); bool growthOnly = true; legs_[1].Add(new IndexedCashFlow(nominal, infIndex, baseDate_, obsDate_, infPayDate, growthOnly)); for (int j = 0; j < 2; ++j) { legs_[j].ForEach((i, x) => x.registerWith(update)); } switch (type_) { case Type.Payer: payer_[0] = +1.0; payer_[1] = -1.0; break; case Type.Receiver: payer_[0] = -1.0; payer_[1] = +1.0; break; default: Utils.QL_FAIL("Unknown zero-inflation-swap type"); break; } }