/* 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. */ ZeroCouponInflationSwap::ZeroCouponInflationSwap( Type type, Real nominal, const Date& startDate, // start date of contract (only) const Date& maturity, // this is pre-adjustment! const Calendar& fixCalendar, BusinessDayConvention fixConvention, const DayCounter& dayCounter, Rate fixedRate, const boost::shared_ptr<ZeroInflationIndex> &infIndex, const Period& observationLag, bool adjustInfObsDates, Calendar infCalendar, BusinessDayConvention infConvention) : Swap(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(infIndex_->frequency()); 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 { 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==Calendar()) infCalendar = fixCalendar; if (infConvention==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. Real T = inflationYearFraction(infIndex_->frequency(), infIndex_->interpolated(), dayCounter_, baseDate_, obsDate_); // N.B. the -1.0 is because swaps only exchange growth, not notionals as well Real fixedAmount = nominal * ( std::pow(1.0 + fixedRate, T) - 1.0 ); legs_[0].push_back(boost::shared_ptr<CashFlow>( new SimpleCashFlow(fixedAmount, fixedPayDate))); bool growthOnly = true; legs_[1].push_back(boost::shared_ptr<CashFlow>( new IndexedCashFlow(nominal,infIndex,baseDate_,obsDate_,infPayDate,growthOnly))); for (Size j=0; j<2; ++j) { for (Leg::iterator i = legs_[j].begin(); i!= legs_[j].end(); ++i) registerWith(*i); } switch (type_) { case Payer: payer_[0] = +1.0; payer_[1] = -1.0; break; case Receiver: payer_[0] = -1.0; payer_[1] = +1.0; break; default: QL_FAIL("Unknown zero-inflation-swap type"); } }
inline const double shiftedP (void) const {return isGhost? (*_pression)+pShift() :(*_pression) ;}