public override double fixing(Date fixingDate, bool forecastTodaysFixing) { if (!isValidFixingDate(fixingDate)) { throw new ArgumentException("Fixing date " + fixingDate + " is not valid"); } TimeSeries <double> fixings = IndexManager.instance().getHistory(name()).value(); if (fixings.ContainsKey(fixingDate)) { return(fixings[fixingDate]); } else { Date today = Settings.evaluationDate(); if (fixingDate < today || (fixingDate == today && !forecastTodaysFixing && Settings.enforcesTodaysHistoricFixings)) { // must have been fixed if (IndexManager.MissingPastFixingCallBack == null) { throw new ArgumentException("Missing " + name() + " fixing for " + fixingDate); } else { // try to load missing fixing from external source double fixing = IndexManager.MissingPastFixingCallBack(this, fixingDate); // add to history addFixing(fixingDate, fixing); return(fixing); } } if ((fixingDate == today) && !forecastTodaysFixing) { // might have been fixed but forecast since it does not exist // so fall through and forecast } // forecast return(forecastFixing(fixingDate)); } }
//! Implemented in order to manage the case of par coupon public override double indexFixing() { #if QL_USE_INDEXED_COUPON return(index_.fixing(fixingDate())); #else if (isInArrears()) { return(index_.fixing(fixingDate())); } else { Date today = Settings.evaluationDate(); Date fixingDate = this.fixingDate(); TimeSeries <double> fixings = IndexManager.instance().getHistory(index_.name()).value(); if (fixings.ContainsKey(fixingDate)) { return(fixings[fixingDate]); } else { if (fixingDate < today) { // must have been fixed if (IndexManager.MissingPastFixingCallBack == null) { throw new ArgumentException("Missing " + index_.name() + " fixing for " + fixingDate); } else { // try to load missing fixing from external source double fixing = IndexManager.MissingPastFixingCallBack(index_, fixingDate); // add to history index_.addFixing(fixingDate, fixing); return(fixing); } } if (fixingDate == today) { // might have been fixed // fall through and forecast } } // forecast: 0) forecasting curve Handle <YieldTermStructure> termStructure = iborIndex_.forwardingTermStructure(); if (termStructure.empty()) { throw new ApplicationException("null term structure set to this instance of " + index_.name()); } // forecast: 1) startDiscount Date fixingValueDate = index_.fixingCalendar().advance(fixingDate, index_.fixingDays(), TimeUnit.Days); double startDiscount = termStructure.link.discount(fixingValueDate); // forecast: 2) endDiscount Date nextFixingDate = index_.fixingCalendar().advance(accrualEndDate_, -fixingDays, TimeUnit.Days); Date nextFixingValueDate = index_.fixingCalendar().advance(nextFixingDate, index_.fixingDays(), TimeUnit.Days); double endDiscount = termStructure.link.discount(nextFixingValueDate); // forecast: 3) spanningTime double spanningTime = index_.dayCounter().yearFraction(fixingValueDate, nextFixingValueDate); if (!(spanningTime > 0.0)) { throw new ApplicationException("cannot calculate forward rate between " + fixingValueDate + " and " + nextFixingValueDate + ": non positive time using " + index_.dayCounter().name()); } // forecast: 4) implied fixing return((startDiscount / endDiscount - 1.0) / spanningTime); } #endif }