public CPICashFlow(double notional, ZeroInflationIndex index, Date baseDate, double baseFixing, Date fixingDate, Date paymentDate, bool growthOnly = false, InterpolationType interpolation = InterpolationType.AsIndex, Frequency frequency = Frequency.NoFrequency) : base(notional, index, baseDate, fixingDate, paymentDate, growthOnly) { baseFixing_ = baseFixing; interpolation_ = interpolation; frequency_ = frequency; Utils.QL_REQUIRE(Math.Abs(baseFixing_) > 1e-16, () => "|baseFixing|<1e-16, future divide-by-zero error"); if (interpolation_ != InterpolationType.AsIndex) { Utils.QL_REQUIRE(frequency_ != Frequency.NoFrequency, () => "non-index interpolation w/o frequency"); } }
public CPILeg(Schedule schedule, ZeroInflationIndex index, double baseCPI, Period observationLag) { schedule_ = schedule; index_ = index; baseCPI_ = baseCPI; observationLag_ = observationLag; paymentDayCounter_ = new Thirty360(); paymentAdjustment_ = BusinessDayConvention.ModifiedFollowing; paymentCalendar_ = schedule.calendar(); fixingDays_ = new List <int>() { 0 }; observationInterpolation_ = InterpolationType.AsIndex; subtractInflationNominal_ = true; spreads_ = new List <double>() { 0 }; }
public CPICoupon(double baseCPI, // user provided, could be arbitrary Date paymentDate, double nominal, Date startDate, Date endDate, int fixingDays, ZeroInflationIndex index, Period observationLag, InterpolationType observationInterpolation, DayCounter dayCounter, double fixedRate, // aka gearing double spread = 0.0, Date refPeriodStart = null, Date refPeriodEnd = null, Date exCouponDate = null) : base(paymentDate, nominal, startDate, endDate, fixingDays, index, observationLag, dayCounter, refPeriodStart, refPeriodEnd, exCouponDate) { baseCPI_ = baseCPI; fixedRate_ = fixedRate; spread_ = spread; observationInterpolation_ = observationInterpolation; Utils.QL_REQUIRE(Math.Abs(baseCPI_) > 1e-16, () => "|baseCPI_| < 1e-16, future divide-by-zero problem"); }
/* 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; } }
public CPISwap(Type type, double nominal, bool subtractInflationNominal, // float+spread leg double spread, DayCounter floatDayCount, Schedule floatSchedule, BusinessDayConvention floatPaymentRoll, int fixingDays, IborIndex floatIndex, // fixed x inflation leg double fixedRate, double baseCPI, DayCounter fixedDayCount, Schedule fixedSchedule, BusinessDayConvention fixedPaymentRoll, Period observationLag, ZeroInflationIndex fixedIndex, InterpolationType observationInterpolation = InterpolationType.AsIndex, double?inflationNominal = null) : base(2) { type_ = type; nominal_ = nominal; subtractInflationNominal_ = subtractInflationNominal; spread_ = spread; floatDayCount_ = floatDayCount; floatSchedule_ = floatSchedule; floatPaymentRoll_ = floatPaymentRoll; fixingDays_ = fixingDays; floatIndex_ = floatIndex; fixedRate_ = fixedRate; baseCPI_ = baseCPI; fixedDayCount_ = fixedDayCount; fixedSchedule_ = fixedSchedule; fixedPaymentRoll_ = fixedPaymentRoll; fixedIndex_ = fixedIndex; observationLag_ = observationLag; observationInterpolation_ = observationInterpolation; Utils.QL_REQUIRE(floatSchedule_.Count > 0, () => "empty float schedule"); Utils.QL_REQUIRE(fixedSchedule_.Count > 0, () => "empty fixed schedule"); // todo if roll!=unadjusted then need calendars ... inflationNominal_ = inflationNominal ?? nominal_; List <CashFlow> floatingLeg; if (floatSchedule_.Count > 1) { floatingLeg = new IborLeg(floatSchedule_, floatIndex_) .withFixingDays(fixingDays_) .withPaymentDayCounter(floatDayCount_) .withSpreads(spread_) .withNotionals(nominal_) .withPaymentAdjustment(floatPaymentRoll_); } else { floatingLeg = new List <CashFlow>(); } if (floatSchedule_.Count == 1 || !subtractInflationNominal_ || (subtractInflationNominal && Math.Abs(nominal_ - inflationNominal_) > 0.00001) ) { Date payNotional; if (floatSchedule_.Count == 1) { // no coupons payNotional = floatSchedule_[0]; payNotional = floatSchedule_.calendar().adjust(payNotional, floatPaymentRoll_); } else { // use the pay date of the last coupon payNotional = floatingLeg.Last().date(); } double floatAmount = subtractInflationNominal_ ? nominal_ - inflationNominal_ : nominal_; CashFlow nf = new SimpleCashFlow(floatAmount, payNotional); floatingLeg.Add(nf); } // a CPIleg know about zero legs and inclusion of base inflation notional List <CashFlow> cpiLeg = new CPILeg(fixedSchedule_, fixedIndex_, baseCPI_, observationLag_) .withFixedRates(fixedRate_) .withPaymentDayCounter(fixedDayCount_) .withObservationInterpolation(observationInterpolation_) .withSubtractInflationNominal(subtractInflationNominal_) .withNotionals(inflationNominal_) .withPaymentAdjustment(fixedPaymentRoll_); foreach (CashFlow cashFlow in cpiLeg) { cashFlow.registerWith(update); } if (floatingLeg.Count > 0) { foreach (CashFlow cashFlow in floatingLeg) { cashFlow.registerWith(update); } } legs_[0] = cpiLeg; legs_[1] = floatingLeg; if (type_ == Type.Payer) { payer_[0] = 1.0; payer_[1] = -1.0; } else { payer_[0] = -1.0; payer_[1] = 1.0; } }