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()); if ((swapObsLag_ - pShift) <= zii_.availabilityLag()) { throw new ApplicationException( "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.registerWith(update); }
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, Calendar infCalendar, BusinessDayConvention infConvention) : base(2) { type_ = type; nominal_ = nominal; fixedRate_ = fixedRate; infIndex_ = infIndex; observationLag_ = observationLag; dayCounter_ = dayCounter; // first check compatibility of index and swap definitions if (infIndex_.interpolated()) { Period pShift = new Period(infIndex_.frequency()); if ((observationLag_ - pShift) <= infIndex_.availabilityLag()) { throw new ApplicationException( "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 { if (infIndex_.availabilityLag() >= observationLag_) { throw new ApplicationException( "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 == new BusinessDayConvention()) { infConvention = fixConvention; } 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) { for (int i = 0; i < legs_[j].Count; i++) { legs_[j][i].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: throw new ApplicationException("Unknown zero-inflation-swap type"); } }