예제 #1
0
파일: Functions.cs 프로젝트: colinnaylor/CN
        private static TermStructure CalcCurveFromMaturity(DateTime Maturity, DateTime StartDate, double CouponRate,
                                                           NextWorkingDayConvention nextDay, int Freq, Dictionary <DateTime, DateTime> Holidays,
                                                           bool FixedCashPayments)
        {
            List <TermPoint> points = new List <TermPoint>();

            DateTime pointDate = Maturity;
            bool     lastPoint = true;

            while (pointDate > StartDate)
            {
                if (lastPoint)
                {
                    // Only do the last point once, decrement the date next time around
                    lastPoint = false;
                }
                else
                {
                    pointDate = pointDate.AddMonths(-(12 / Freq));
                }

                TermPoint point = new TermPoint();
                point.Rate      = CouponRate;
                point.PointDate = pointDate;
                int month = point.PointDate.Month;

                point.PayDate = GetWorkingDayDate(1, pointDate.AddDays(-1), Holidays, nextDay);

                if (!FixedCashPayments)
                {
                    point.PointDate = point.PayDate;
                }

                points.Add(point);
            }
            ;

            TermStructure ts = new TermStructure();

            for (int i = points.Count - 1; i >= 0; i--)
            {
                ts.Points.Add(points[i]);
            }

            return(ts);
        }
예제 #2
0
        private void BootstrapSwapRates(InputData inputData)
        {
            // prev rate starts off as the most recent Future rate
            Rate prev = inputData.FutureData[inputData.FutureData.Count - 1];

            foreach (Rate rate in inputData.SwapData)
            {
                double fixedCoupon = rate.SwapRate / 100;

                DateTime lastDate = rate.TermDate.AddMonths(-12 / inputData.SwapFixedPaymentFrequency);

                TermStructure ts = Functions.GetTermStructure(lastDate, rate.StartDate, rate.StartDate, fixedCoupon,
                                                              inputData.SwapFixedDayCountConvention, inputData.NextWorkingDay, inputData.SwapFixedPaymentFrequency, inputData.Holidays, false);

                ts.PrintStructure();
                double fixedCash = Functions.PresentValue(rate.StartDate, 0, ts, inputData, inputData.Holidays, false);

                ts = Functions.GetTermStructure(rate.TermDate, lastDate, lastDate, fixedCoupon,
                                                inputData.SwapFixedDayCountConvention, inputData.NextWorkingDay, inputData.SwapFixedPaymentFrequency, inputData.Holidays, false);
                ts.PrintStructure();

                double accrued        = 1 + Functions.AccruedForDaysInPeriod(lastDate, rate.TermDate, ts, fixedCoupon, false);
                double discountFactor = 0;

                accrued = accrued > 0 ? discountFactor = (1 - fixedCash) / accrued : 1 - fixedCash;

                // Adjust rates to curve basis
                if (inputData.DayCountConvention != inputData.SwapFixedDayCountConvention)
                {
                    rate.Term = Functions.DaysBetween(rate.StartDate, rate.TermDate, inputData.DayCountConvention);
                }

                rate.SpotRate = 100 * Functions.GetRateFromDiscountFactor(discountFactor, rate.Term, Functions.DaysInYear(inputData.DayCountConvention));
                inputData.Rates.Add(rate);
            }
        }
예제 #3
0
파일: Functions.cs 프로젝트: colinnaylor/CN
        internal static double AccruedForDaysInPeriod(DateTime AccrueFrom, DateTime AccrueTo, TermStructure ts, double Rate, bool FixedCashPayments)
        {
            double    ret         = 0;
            TermPoint periodStart = ts.Points[0];
            TermPoint periodEnd   = null;

            if (AccrueTo > ts.Points[0].PointDate && AccrueFrom < ts.Points[ts.PointCount - 1].PointDate)
            {
                // Find the applicable period
                foreach (TermPoint point in ts.Points)
                {
                    if (point.PointDate <= AccrueFrom)
                    {
                        periodStart = point;
                    }
                    else if (point.PointDate >= AccrueTo)
                    {
                        periodEnd = point;
                        break;
                    }
                }
                // If the caller has asked for Accrued to a point past the end of the term structure it is not valid
                // and the PeriodEnd variable will be equal to zero
                if (periodEnd == null)
                {
                    throw new Exception(string.Format("AccrueTo data [{0}] is past the end of the curve [{1}].", AccrueTo.ToString("dd MMM yy"), ts.Points[ts.PointCount - 1].PointDate.ToString("dd MMM yy")));
                }

                int days         = DaysBetween(AccrueFrom, AccrueTo, ts.DayCount);
                int periodLength = DaysBetween(periodStart.PointDate, periodEnd.PointDate, ts.DayCount);
                int freq         = (int)Math.Round((double)365 / periodLength, 0);

                // We need to get the rate of the point to which we are accrueing up to
                // A rate quoted within the Curve is the portion of rate for that period. So the rate according to the curve for a
                // semi annual bond paying 5% would be 2.5%
                if (Rate == 0)
                {
                    Rate = periodEnd.Amount;
                }

                if (FixedCashPayments)
                {
                    if (periodLength > 366)
                    {
                        // it's longer than a year.
                        // We need to work out the accrued as if a coupon "was" paid each year
                        // This will take account of when a Feb 29 occurrs

                        // Split the accrued to before and after an imaginary paydate being one year before the real pay date
                        DateTime couponPoint2 = periodEnd.PointDate;
                        do
                        {
                            DateTime couponPoint = couponPoint2.AddYears(-1);
                            periodLength = DaysBetween(couponPoint, couponPoint2, ts.DayCount);

                            if (couponPoint < AccrueTo)
                            {
                                if (couponPoint2 < AccrueTo)
                                {
                                    // We have done the part up to AccrueTo
                                    if (AccrueFrom < couponPoint)
                                    {
                                        days = DaysBetween(couponPoint, couponPoint2, ts.DayCount);
                                    }
                                    else
                                    {
                                        days = DaysBetween(AccrueFrom, couponPoint, ts.DayCount);
                                    }
                                }
                                else
                                {
                                    // Work out accrued from the CouponPoint to the AccrueTo date
                                    if (AccrueFrom < couponPoint)
                                    {
                                        days = DaysBetween(couponPoint, AccrueTo, ts.DayCount);
                                    }
                                    else
                                    {
                                        days = DaysBetween(AccrueFrom, AccrueTo, ts.DayCount);
                                    }
                                }
                                ret += (Rate * days / periodLength);
                            }
                            couponPoint2 = couponPoint;
                        } while (couponPoint2 < AccrueFrom);
                    }
                    else
                    {
                        if (periodLength != 0)
                        {
                            ret += (Rate / freq) * (days / periodLength);
                        }
                    }
                }
                else
                {
                    switch (ts.DayCount)
                    {
                    case DayCountConvention.e30_360:
                    case DayCountConvention.e30E_360:
                    case DayCountConvention.e30E1_360:
                    case DayCountConvention.eActual_360:
                        ret = Rate * days / 360;
                        break;

                    case DayCountConvention.eActual_365:
                    case DayCountConvention.eActualNL_365:
                        ret = Rate * days / 365;
                        break;

                    case DayCountConvention.eActual_Actual:
                        // Check for leap years
                        int year1 = (int)DateTime.Parse("1 Jan " + AccrueTo.AddYears(1).Year).Subtract(DateTime.Parse("1 Jan " + AccrueFrom.Year)).TotalDays;

                        if (year1 == 731)
                        {     // it goes into two years one of which is a leap year
                              // A bit different for this
                              // This assumes that the period is <= 1 year, ie, cannot span more than 2 adjacent years

                            // Days = startpoint up to the first of next year
                            days = (int)DateTime.Parse("1 Jan " + periodEnd.PointDate.Year).Subtract(periodStart.PointDate).TotalDays;
                            // Days2 = the first of the next year to the end point
                            int days2 = (int)periodEnd.PointDate.Subtract(DateTime.Parse("1 Jan " + periodEnd.PointDate.Year)).TotalDays;

                            // Number of days in each seperate period which falls in each year
                            year1 = (int)DateTime.Parse("1 Jan " + periodEnd.PointDate.Year).Subtract(DateTime.Parse("1 Jan " + periodStart.PointDate.Year)).TotalDays;
                            int year2 = (int)DateTime.Parse("1 Jan " + periodEnd.PointDate.Year + 1).Subtract(DateTime.Parse("1 Jan " + periodEnd.PointDate.Year)).TotalDays;

                            ret = (((Rate / year1) * days)) + (((Rate / year2) * days2));
                        }
                        else
                        {
                            ret = (Rate * days) / year1;
                        }
                        break;
                    }
                }
            }

            return(ret);
        }
예제 #4
0
파일: Functions.cs 프로젝트: colinnaylor/CN
        internal static double PresentValue(DateTime ValueDate, double SpreadOverLibor, TermStructure ts, InputData inputData, Dictionary <DateTime, DateTime> Holidays, bool FixedCashPayments)
        {
            double ret = 0;

            // LastPaymentDate should be the date from which we wish to start accrueing interest.
            // This is either the lastcoupon payment (for fixed cash payments) or the Startdate if that is later and not Fixed Cash Payments
            // The curve passed in (Rates) would have either the lastcouponpayment or the startdate as the preceding point
            DateTime           lastPayDate = DateTime.MinValue;
            DayCountConvention dayC        = ts.DayCount;

            foreach (TermPoint point in ts.Points)
            {
                lastPayDate = point.PointDate;
                if (point.PointDate >= ValueDate)
                {
                    break;
                }
            }

            for (int p = 1; p < ts.PointCount; p++)
            {
                DateTime nextPaymentDate = ts.Points[p].PointDate;
                DateTime nextPayDate     = ts.Points[p].PayDate;
                int      daysToDiscount  = DaysBetween(ValueDate, nextPayDate, dayC);

                if (daysToDiscount > 0)
                {
                    double fixingRate = ts.Points[p].Rate;

                    double discountFactor = GetDiscountFactor(daysToDiscount, inputData.Rates, dayC);
                    int    daysToAccrue   = DaysBetween(lastPayDate, nextPaymentDate, dayC);

                    double paymentValue = AccruedForDaysInPeriod(ts.Points[p - 1].PointDate, ts.Points[p].PointDate, ts, fixingRate + SpreadOverLibor, FixedCashPayments);

                    ret += paymentValue * discountFactor;
                }
                lastPayDate = nextPayDate;
            }

            return(ret);
        }
예제 #5
0
파일: Functions.cs 프로젝트: colinnaylor/CN
        internal static TermStructure GetTermStructure(DateTime Maturity, DateTime StartDate, DateTime FirstCouponDate, double CouponRate,
                                                       DayCountConvention dayCount, NextWorkingDayConvention nextDay, int Freq, Dictionary <DateTime, DateTime> Holidays,
                                                       bool FixedCashPayments)
        {
            TermStructure ts = CalcCurveFromMaturity(Maturity, StartDate, CouponRate, nextDay, Freq, Holidays, false);

            ts.DayCount = dayCount;

            // Calc daycount depending on accrual rule
            int yearDays = DaysInYear(dayCount);

            int       point;
            TermPoint tp;
            TermPoint ltp;

            for (point = 1; point < ts.PointCount; point++)
            {
                tp  = ts.Points[point];
                ltp = ts.Points[point - 1];

                tp.Term = DaysBetween(ltp.PointDate, tp.PointDate, dayCount);

                if (FixedCashPayments)
                {
                    int lastYear = (int)tp.PointDate.Subtract(tp.PointDate.AddYears(-1)).TotalDays;
                    if (tp.Term <= yearDays || lastYear == -366)
                    {
                        tp.EffectiveRate = tp.Rate / Freq * yearDays / tp.Term;
                    }
                    else
                    {
                        tp.EffectiveRate = tp.Rate;
                    }
                }
                else
                {
                    tp.EffectiveRate = tp.Rate;
                }
            }

            point = 0;
            while (point > -1 && ts.PointCount > 1)
            {
                tp = ts.Points[point];
                if (tp.PointDate < StartDate)
                {
                    tp.PointDate = StartDate;
                    tp           = ts.Points[point + 1];
                    tp.Term      = DaysBetween(StartDate, tp.PointDate, dayCount);
                }
                else if (tp.PointDate > StartDate && tp.PointDate < FirstCouponDate && point != 0)
                {
                    ts.Points.Remove(tp);

                    if (point < ts.PointCount && point > 0)
                    {
                        tp      = ts.Points[point];
                        ltp     = ts.Points[point - 1];
                        tp.Term = DaysBetween(ltp.PointDate, tp.PointDate, dayCount);
                    }

                    point--;
                }
                else if (tp.PointDate >= FirstCouponDate)
                {
                    point = -2; // get out
                }
                point++;
            }

            int totalTerm = 0;

            for (point = 1; point < ts.PointCount; point++)
            {
                tp  = ts.Points[point];
                ltp = ts.Points[point - 1];

                // BUT for actual / actual and in a leap year some more calculations need to be done.
                // e.g.  Period  2 jan 96 to 1 jan 97 = (365/366 + 1/365)  NOT including the last day but including the first day
                if (dayCount == DayCountConvention.eActual_Actual && FixedCashPayments == false &&
                    ltp.PointDate.Year != tp.PointDate.Year)
                {
                    tp.YearFraction =
                        ltp.PointDate.Subtract(DateTime.Parse("1 Jan " + ltp.PointDate.AddYears(1).Year)).TotalDays
                        /
                        DateTime.Parse("1 Jan " + ltp.PointDate.AddYears(1).Year).Subtract(DateTime.Parse("1 Jan " + ltp.PointDate.Year)).TotalDays
                        +
                        tp.PointDate.Subtract(DateTime.Parse("1 Jan " + tp.PointDate.Year)).TotalDays
                        /
                        DateTime.Parse("1 Jan " + tp.PointDate.AddYears(1).Year).Subtract(DateTime.Parse("1 Jan " + tp.PointDate.Year)).TotalDays;
                }
                else
                {
                    if (tp.Rate > 0 && FixedCashPayments)
                    {
                        tp.YearFraction = tp.EffectiveRate * tp.Term / yearDays / tp.Rate;
                    }
                    else
                    {
                        tp.YearFraction = (double)tp.Term / (double)yearDays;
                    }
                }

                tp.Amount = tp.Rate * tp.YearFraction;

                // Reset daycounts to be cummulative
                totalTerm += tp.Term;
                tp.Term    = totalTerm;
            }

            return(ts);
        }