public override double swapletRate() { OvernightIndex index = coupon_.index() as OvernightIndex; List <Date> fixingDates = coupon_.fixingDates(); List <double> dt = coupon_.dt(); int n = dt.Count; int i = 0; double compoundFactor = 1.0; // already fixed part Date today = Settings.evaluationDate(); while (fixingDates[i] < today && i < n) { // rate must have been fixed double?pastFixing = IndexManager.instance().getHistory(index.name()).value()[fixingDates[i]]; Utils.QL_REQUIRE(pastFixing != null, () => "Missing " + index.name() + " fixing for " + fixingDates[i].ToString()); compoundFactor *= (1.0 + pastFixing.GetValueOrDefault() * dt[i]); ++i; } // today is a border case if (fixingDates[i] == today && i < n) { // might have been fixed try { double?pastFixing = IndexManager.instance().getHistory(index.name()).value()[fixingDates[i]]; if (pastFixing != null) { compoundFactor *= (1.0 + pastFixing.GetValueOrDefault() * dt[i]); ++i; } else { // fall through and forecast } } catch (Exception) { // fall through and forecast } } // forward part using telescopic property in order // to avoid the evaluation of multiple forward fixings if (i < n) { Handle <YieldTermStructure> curve = index.forwardingTermStructure(); Utils.QL_REQUIRE(!curve.empty(), () => "null term structure set to this instance of" + index.name()); List <Date> dates = coupon_.valueDates(); double startDiscount = curve.link.discount(dates[i]); double endDiscount = curve.link.discount(dates[n]); compoundFactor *= startDiscount / endDiscount; } double rate = (compoundFactor - 1.0) / coupon_.accrualPeriod(); return(coupon_.gearing() * rate + coupon_.spread()); }
public override double fixing(Date fixingDate, bool forecastTodaysFixing) { Date today = Settings.evaluationDate(); Date todayMinusLag = today - availabilityLag_; KeyValuePair <Date, Date> limm = Utils.inflationPeriod(todayMinusLag, frequency_); Date lastFix = limm.Key - 1; Date flatMustForecastOn = lastFix + 1; Date interpMustForecastOn = lastFix + 1 - new Period(frequency_); if (interpolated() && fixingDate >= interpMustForecastOn) { return(forecastFixing(fixingDate)); } if (!interpolated() && fixingDate >= flatMustForecastOn) { return(forecastFixing(fixingDate)); } // four cases with ratio() and interpolated() if (ratio()) { if (interpolated()) { // IS ratio, IS interpolated KeyValuePair <Date, Date> lim = Utils.inflationPeriod(fixingDate, frequency_); Date fixMinus1Y = new NullCalendar().advance(fixingDate, new Period(-1, TimeUnit.Years), BusinessDayConvention.ModifiedFollowing); KeyValuePair <Date, Date> limBef = Utils.inflationPeriod(fixMinus1Y, frequency_); double dp = lim.Value + 1 - lim.Key; double dpBef = limBef.Value + 1 - limBef.Key; double dl = fixingDate - lim.Key; // potentially does not work on 29th Feb double dlBef = fixMinus1Y - limBef.Key; // get the four relevant fixings // recall that they are stored flat for every day double?limFirstFix = IndexManager.instance().getHistory(name()).value()[lim.Key]; if (limFirstFix == null) { throw new ApplicationException("Missing " + name() + " fixing for " + lim.Key); } double?limSecondFix = IndexManager.instance().getHistory(name()).value()[lim.Value + 1]; if (limSecondFix == null) { throw new ApplicationException("Missing " + name() + " fixing for " + lim.Value + 1); } double?limBefFirstFix = IndexManager.instance().getHistory(name()).value()[limBef.Key]; if (limBefFirstFix == null) { throw new ApplicationException("Missing " + name() + " fixing for " + limBef.Key); } double?limBefSecondFix = IndexManager.instance().getHistory(name()).value()[limBef.Value + 1]; if (limBefSecondFix == null) { throw new ApplicationException("Missing " + name() + " fixing for " + limBef.Value + 1); } double linearNow = limFirstFix.Value + (limSecondFix.Value - limFirstFix.Value) * dl / dp; double linearBef = limBefFirstFix.Value + (limBefSecondFix.Value - limBefFirstFix.Value) * dlBef / dpBef; double wasYES = linearNow / linearBef - 1.0; return(wasYES); } else { // IS ratio, NOT interpolated double?pastFixing = IndexManager.instance().getHistory(name()).value()[fixingDate]; if (pastFixing == null) { throw new ApplicationException("Missing " + name() + " fixing for " + fixingDate); } Date previousDate = fixingDate - new Period(1, TimeUnit.Years); double?previousFixing = IndexManager.instance().getHistory(name()).value()[previousDate]; if (previousFixing == null) { throw new ApplicationException("Missing " + name() + " fixing for " + previousDate); } return(pastFixing.Value / previousFixing.Value - 1.0); } } else { // NOT ratio if (interpolated()) { // NOT ratio, IS interpolated KeyValuePair <Date, Date> lim = Utils.inflationPeriod(fixingDate, frequency_); double dp = lim.Value + 1 - lim.Key; double dl = fixingDate - lim.Key; double?limFirstFix = IndexManager.instance().getHistory(name()).value()[lim.Key]; if (limFirstFix == null) { throw new ApplicationException("Missing " + name() + " fixing for " + lim.Key); } double?limSecondFix = IndexManager.instance().getHistory(name()).value()[lim.Value + 1]; if (limSecondFix == null) { throw new ApplicationException("Missing " + name() + " fixing for " + lim.Value + 1); } double linearNow = limFirstFix.Value + (limSecondFix.Value - limFirstFix.Value) * dl / dp; return(linearNow); } else { // NOT ratio, NOT interpolated // so just flat double?pastFixing = IndexManager.instance().getHistory(name()).value()[fixingDate]; if (pastFixing == null) { throw new ApplicationException("Missing " + name() + " fixing for " + fixingDate); } return(pastFixing.Value); } } // QL_FAIL("YoYInflationIndex::fixing, should never get here"); }
//! clears all stored historical fixings public void clearFixings() { IndexManager.instance().clearHistory(name()); }
//! returns the fixing TimeSeries public ObservableValue <TimeSeries <double> > timeSeries() { return(IndexManager.instance().getHistory(name())); }
//! 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 }
// Clears all stored historical fixings public void clearFixings() { checkNativeFixingsAllowed(); IndexManager.instance().clearHistory(name()); }
// Returns the fixing TimeSeries public TimeSeries <double?> timeSeries() { return(IndexManager.instance().getHistory(name())); }