Пример #1
0
            public override double yearFraction(Date d1, Date d2, Date refPeriodStart, Date refPeriodEnd)
            {
                if (d1 == d2)
                {
                    return(0);
                }
                if (d1 > d2)
                {
                    return(-yearFraction(d2, d1, null, null));
                }

                Date   newD2 = d2, temp = d2;
                double sum = 0;

                while (temp > d1)
                {
                    temp = newD2 - TimeUnit.Years;
                    if (temp.Day == 28 && temp.Month == 2 && Date.IsLeapYear(temp.Year))
                    {
                        temp += 1;
                    }
                    if (temp >= d1)
                    {
                        sum  += 1;
                        newD2 = temp;
                    }
                }

                double den = 365;

                if (Date.IsLeapYear(newD2.Year))
                {
                    temp = new Date(29, Month.February, newD2.Year);
                    if (newD2 > temp && d1 <= temp)
                    {
                        den += 1;
                    }
                }
                else if (Date.IsLeapYear(d1.Year))
                {
                    temp = new Date(29, Month.February, d1.Year);
                    if (newD2 > temp && d1 <= temp)
                    {
                        den += 1;
                    }
                }

                return(sum + Date.daysBetween(d1, newD2) / den);
            }
Пример #2
0
            public override double yearFraction(Date d1, Date d2, Date refPeriodStart, Date refPeriodEnd)
            {
                if (d1 == d2)
                {
                    return(0);
                }
                if (d1 > d2)
                {
                    return(-yearFraction(d2, d1, null, null));
                }

                int    y1 = d1.Year, y2 = d2.Year;
                double dib1 = (Date.IsLeapYear(y1) ? 366 : 365),
                       dib2 = (Date.IsLeapYear(y2) ? 366 : 365);

                double sum = y2 - y1 - 1;

                sum += Date.daysBetween(d1, new Date(1, Month.January, y1 + 1)) / dib1;
                sum += Date.daysBetween(new Date(1, Month.January, y2), d2) / dib2;
                return(sum);
            }
Пример #3
0
            public override double yearFraction(Date d1, Date d2, Date d3, Date d4)
            {
                if (d1 == d2)
                {
                    return(0);
                }
                if (d1 > d2)
                {
                    return(-yearFraction(d2, d1, d3, d4));
                }

                // when the reference period is not specified, try taking it equal to (d1,d2)
                Date refPeriodStart = (d3 ?? d1);
                Date refPeriodEnd   = (d4 ?? d2);

                Utils.QL_REQUIRE(refPeriodEnd > refPeriodStart && refPeriodEnd > d1, () =>
                                 "Invalid reference period: date 1: " + d1 + ", date 2: " + d2 +
                                 ", reference period start: " + refPeriodStart + ", reference period end: " + refPeriodEnd);

                // estimate roughly the length in months of a period
                int months = (int)(0.5 + 12 * (refPeriodEnd - refPeriodStart) / 365.0);

                // for short periods...
                if (months == 0)
                {
                    // ...take the reference period as 1 year from d1
                    refPeriodStart = d1;
                    refPeriodEnd   = d1 + TimeUnit.Years;
                    months         = 12;
                }

                double period = months / 12.0;

                if (d2 <= refPeriodEnd)
                {
                    // here refPeriodEnd is a future (notional?) payment date
                    if (d1 >= refPeriodStart)
                    {
                        // here refPeriodStart is the last (maybe notional) payment date.
                        // refPeriodStart <= d1 <= d2 <= refPeriodEnd
                        // [maybe the equality should be enforced, since	refPeriodStart < d1 <= d2 < refPeriodEnd	could give wrong results] ???
                        return(period * Date.daysBetween(d1, d2) / Date.daysBetween(refPeriodStart, refPeriodEnd));
                    }
                    else
                    {
                        // here refPeriodStart is the next (maybe notional) payment date and refPeriodEnd is the second next (maybe notional) payment date.
                        // d1 < refPeriodStart < refPeriodEnd
                        // AND d2 <= refPeriodEnd
                        // this case is long first coupon

                        // the last notional payment date
                        Date previousRef = refPeriodStart - new Period(months, TimeUnit.Months);
                        if (d2 > refPeriodStart)
                        {
                            return(yearFraction(d1, refPeriodStart, previousRef, refPeriodStart) +
                                   yearFraction(refPeriodStart, d2, refPeriodStart, refPeriodEnd));
                        }
                        else
                        {
                            return(yearFraction(d1, d2, previousRef, refPeriodStart));
                        }
                    }
                }
                else
                {
                    // here refPeriodEnd is the last (notional?) payment date
                    // d1 < refPeriodEnd < d2 AND refPeriodStart < refPeriodEnd
                    Utils.QL_REQUIRE(refPeriodStart <= d1, () => "invalid dates: d1 < refPeriodStart < refPeriodEnd < d2");

                    // 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;
                    for (;;)
                    {
                        newRefStart = refPeriodEnd + new Period(months * i, TimeUnit.Months);
                        newRefEnd   = refPeriodEnd + new Period(months * (i + 1), TimeUnit.Months);
                        if (d2 < newRefEnd)
                        {
                            break;
                        }
                        else
                        {
                            sum += period;
                            i++;
                        }
                    }
                    sum += yearFraction(newRefStart, d2, newRefStart, newRefEnd);
                    return(sum);
                }
            }