public double fairRate() { // What does this mean before or after trade date? // Always means that NPV is zero for _this_ instrument // if it was created with _this_ rate // _knowing_ the time from base to obs (etc). IndexedCashFlow icf = legs_[1][0] as IndexedCashFlow; if (icf == null) { throw new ApplicationException("failed to downcast to IndexedCashFlow in ::fairRate()"); } // +1 because the IndexedCashFlow has growthOnly=true double growth = icf.amount() / icf.notional() + 1.0; double T = Utils.inflationYearFraction(infIndex_.frequency(), infIndex_.interpolated(), dayCounter_, baseDate_, obsDate_); return(Math.Pow(growth, 1.0 / T) - 1.0); // we cannot use this simple definition because // it does not work for already-issued instruments // return infIndex_->zeroInflationTermStructure()->zeroRate( // maturityDate(), observationLag(), infIndex_->interpolated()); }
public double fairRate() { // What does this mean before or after trade date? // Always means that NPV is zero for _this_ instrument // if it was created with _this_ rate // _knowing_ the time from base to obs (etc). IndexedCashFlow icf = legs_[1][0] as IndexedCashFlow; Utils.QL_REQUIRE(icf != null, () => "failed to downcast to IndexedCashFlow in ::fairRate()"); // +1 because the IndexedCashFlow has growthOnly=true double growth = icf.amount() / icf.notional() + 1.0; double T = Utils.inflationYearFraction(infIndex_.frequency(), infIndex_.interpolated(), dayCounter_, baseDate_, obsDate_); return(Math.Pow(growth, 1.0 / T) - 1.0); }
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"); } }