public override double yearFraction(Date d1, Date d2, Date d3, Date d4) { if (d1 == d2) { return(0.0); } if (d2 < d1) { return(-yearFraction(d2, d1, d3, d4)); } List <Date> couponDates = getListOfPeriodDatesIncludingQuasiPayments(schedule_); double yearFractionSum = 0.0; for (int i = 0; i < couponDates.Count - 1; i++) { Date startReferencePeriod = couponDates[i]; Date endReferencePeriod = couponDates[i + 1]; if (d1 < endReferencePeriod && d2 > startReferencePeriod) { yearFractionSum += yearFractionWithReferenceDates(this, Date.Max(d1, startReferencePeriod), Date.Min(d2, endReferencePeriod), startReferencePeriod, endReferencePeriod); } } return(yearFractionSum); }
public override double swapletRate() { List <Date> fixingDates = coupon_.fixingDates(); InterestRateIndex index = coupon_.index(); int cutoffDays = 0; // to be verified Date startDate = coupon_.accrualStartDate() - cutoffDays, endDate = coupon_.accrualEndDate() - cutoffDays, d1 = startDate, d2 = startDate; if (!(fixingDates.Count > 0)) { throw new ApplicationException("fixing date list empty"); } if (!(index.valueDate(fixingDates.First()) <= startDate)) { throw new ApplicationException("first fixing date valid after period start"); } if (!(index.valueDate(fixingDates.Last()) >= endDate)) { throw new ApplicationException("last fixing date valid before period end"); } double avgBMA = 0.0; int days = 0; for (int i = 0; i < fixingDates.Count - 1; ++i) { Date valueDate = index.valueDate(fixingDates[i]); Date nextValueDate = index.valueDate(fixingDates[i + 1]); if (fixingDates[i] >= endDate || valueDate >= endDate) { break; } if (fixingDates[i + 1] < startDate || nextValueDate <= startDate) { continue; } d2 = Date.Min(nextValueDate, endDate); avgBMA += index.fixing(fixingDates[i]) * (d2 - d1); days += d2 - d1; d1 = d2; } avgBMA /= (endDate - startDate); if (!(days == endDate - startDate)) { throw new ApplicationException("averaging days " + days + " differ from " + "interest days " + (endDate - startDate)); } return(coupon_.gearing() * avgBMA + coupon_.spread()); }
public override Date maxDate() { Date maxDate = Date.Min(underlyingDividendTS_.currentLink().maxDate(), riskFreeTS_.currentLink().maxDate()); maxDate = Date.Min(maxDate, foreignRiskFreeTS_.currentLink().maxDate()); maxDate = Date.Min(maxDate, underlyingBlackVolTS_.currentLink().maxDate()); maxDate = Date.Min(maxDate, exchRateBlackVolTS_.currentLink().maxDate()); return(maxDate); }
//! accrued days at the given date public int accruedDays(Date d) { if (d <= accrualStartDate_ || d > paymentDate_) { return(0); } else { return(dayCounter().dayCount(accrualStartDate_, Date.Min(d, accrualEndDate_))); } }
public override double accruedAmount(Date d) { if (d <= accrualStartDate_ || d > paymentDate_) { return(0); } else { return(nominal() * rate() * dayCounter().yearFraction(accrualStartDate_, Date.Min(d, accrualEndDate_), refPeriodStart_, refPeriodEnd_)); } }
public override double accruedAmount(Date d) { if (d <= accrualStartDate_ || d > paymentDate_) { return(0); } else { return(nominal() * (rate_.compoundFactor(accrualStartDate_, Date.Min(d, accrualEndDate_), refPeriodStart_, refPeriodEnd_) - 1.0)); } }
//! accrued period as fraction of year at the given date public double accruedPeriod(Date d) { if (d <= accrualStartDate_ || d > paymentDate_) { return(0.0); } else { return(dayCounter().yearFraction(accrualStartDate_, Date.Min(d, accrualEndDate_), refPeriodStart_, refPeriodEnd_)); } }
public static Date startDate(Leg leg) { Utils.QL_REQUIRE(!leg.empty(), () => "empty leg"); Date d = Date.maxDate(); for (int i = 0; i < leg.Count; ++i) { Coupon c = leg[i] as Coupon; if (c != null) { d = Date.Min(d, c.accrualStartDate()); } else { d = Date.Min(d, leg[i].date()); } } return(d); }
public override void calculate() { Utils.QL_REQUIRE(integrationStep_ != null, () => "null period set"); Utils.QL_REQUIRE(!discountCurve_.empty(), () => "no discount term structure set"); Utils.QL_REQUIRE(!probability_.empty(), () => "no probability term structure set"); Date today = Settings.evaluationDate(); Date settlementDate = discountCurve_.link.referenceDate(); // Upfront Flow NPV. Either we are on-the-run (no flow) // or we are forward start double upfPVO1 = 0.0; if (!arguments_.upfrontPayment.hasOccurred(settlementDate, includeSettlementDateFlows_)) { // date determining the probability survival so we have to pay // the upfront (did not knock out) Date effectiveUpfrontDate = arguments_.protectionStart > probability_.link.referenceDate() ? arguments_.protectionStart : probability_.link.referenceDate(); upfPVO1 = probability_.link.survivalProbability(effectiveUpfrontDate) * discountCurve_.link.discount(arguments_.upfrontPayment.date()); } results_.upfrontNPV = upfPVO1 * arguments_.upfrontPayment.amount(); results_.couponLegNPV = 0.0; results_.defaultLegNPV = 0.0; for (int i = 0; i < arguments_.leg.Count; ++i) { if (arguments_.leg[i].hasOccurred(settlementDate, includeSettlementDateFlows_)) { continue; } FixedRateCoupon coupon = arguments_.leg[i] as FixedRateCoupon; // In order to avoid a few switches, we calculate the NPV // of both legs as a positive quantity. We'll give them // the right sign at the end. Date paymentDate = coupon.date(), startDate = (i == 0 ? arguments_.protectionStart : coupon.accrualStartDate()), endDate = coupon.accrualEndDate(); Date effectiveStartDate = (startDate <= today && today <= endDate) ? today : startDate; double couponAmount = coupon.amount(); double S = probability_.link.survivalProbability(paymentDate); // On one side, we add the fixed rate payments in case of // survival. results_.couponLegNPV += S * couponAmount * discountCurve_.link.discount(paymentDate); // On the other side, we add the payment (and possibly the // accrual) in case of default. Period step = integrationStep_; Date d0 = effectiveStartDate; Date d1 = Date.Min(d0 + step, endDate); double P0 = probability_.link.defaultProbability(d0); double endDiscount = discountCurve_.link.discount(paymentDate); do { double B = arguments_.paysAtDefaultTime ? discountCurve_.link.discount(d1) : endDiscount; double P1 = probability_.link.defaultProbability(d1); double dP = P1 - P0; // accrual... if (arguments_.settlesAccrual) { if (arguments_.paysAtDefaultTime) { results_.couponLegNPV += coupon.accruedAmount(d1) * B * dP; } else { results_.couponLegNPV += couponAmount * B * dP; } } // ...and claim. double claim = arguments_.claim.amount(d1, arguments_.notional.Value, recoveryRate_); results_.defaultLegNPV += claim * B * dP; // setup for next time around the loop P0 = P1; d0 = d1; d1 = Date.Min(d0 + step, endDate); } while (d0 < endDate); } double upfrontSign = 1.0; switch (arguments_.side) { case Protection.Side.Seller: results_.defaultLegNPV *= -1.0; break; case Protection.Side.Buyer: results_.couponLegNPV *= -1.0; results_.upfrontNPV *= -1.0; upfrontSign = -1.0; break; default: Utils.QL_FAIL("unknown protection side"); break; } results_.value = results_.defaultLegNPV + results_.couponLegNPV + results_.upfrontNPV; results_.errorEstimate = null; if (results_.couponLegNPV != 0.0) { results_.fairSpread = -results_.defaultLegNPV * arguments_.spread / results_.couponLegNPV; } else { results_.fairSpread = null; } double upfrontSensitivity = upfPVO1 * arguments_.notional.Value; if (upfrontSensitivity != 0.0) { results_.fairUpfront = -upfrontSign * (results_.defaultLegNPV + results_.couponLegNPV) / upfrontSensitivity; } else { results_.fairUpfront = null; } if (arguments_.spread != 0.0) { results_.couponLegBPS = results_.couponLegNPV * basisPoint / arguments_.spread; } else { results_.couponLegBPS = null; } if (arguments_.upfront.HasValue && arguments_.upfront.Value != 0.0) { results_.upfrontBPS = results_.upfrontNPV * basisPoint / (arguments_.upfront.Value); } else { results_.upfrontBPS = null; } }