// d1 < refPeriodStart < refPeriodEnd
// AND d2 <= refPeriodEnd
// this case is long first coupon
// the last notional payment date
final Date previousRef = refPeriodStart.add(new Period(
-months, TimeUnit.Months));
if (d2.gt(refPeriodStart))
return yearFraction(d1, refPeriodStart, previousRef,
refPeriodStart)
+ yearFraction(refPeriodStart, d2,
refPeriodStart, refPeriodEnd);
else
return yearFraction(d1, d2, previousRef,
refPeriodStart);
}
} else {
// TODO: code review :: please verify against QL/C++ code
// here refPeriodEnd is the last notional payment date
// d1 < refPeriodEnd < d2 AND refPeriodStart < refPeriodEnd
QL.require(refPeriodStart.le(d1) , "invalid dates"); // TODO: message
// now it is: refPeriodStart <= d1 < refPeriodEnd < d2
// the part from d1 to refPeriodEnd
double sum = yearFraction(d1, refPeriodEnd, refPeriodStart, refPeriodEnd);
// the part from refPeriodEnd to d2
// count how many regular periods are in [refPeriodEnd, d2],
// then add the remaining time
int i = 0;
Date newRefStart, newRefEnd;
do {
newRefStart = refPeriodEnd.add(new Period(months * i, TimeUnit.Months));
newRefEnd = refPeriodEnd.add(new Period(months * (i + 1), TimeUnit.Months));
if (d2.lt(newRefEnd))
break;
else {
sum += period;
i++;