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); }
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); }
internal static DateTime GetWorkingDayDate(int workingDays, DateTime Start, Dictionary <DateTime, DateTime> Holidays, NextWorkingDayConvention nd) { int moveDay; int startMonth; int days = 0; DateTime workDay; // Adjust for preceeding working days if (workingDays < 0) { // We are moving backwards, just like H. G. Wells moveDay = -1; } else { moveDay = 1; } workDay = Start; startMonth = Start.Month; while (days != workingDays) { workDay = workDay.AddDays(moveDay); // Is it a weekend if (workDay.DayOfWeek != DayOfWeek.Saturday && workDay.DayOfWeek != DayOfWeek.Sunday) { // Is it a Holiday if (!Holidays.ContainsKey(workDay)) { // It is a working day. Increment our counter */ days += moveDay; } } } if (nd == NextWorkingDayConvention.eNextWorkDayUnlessNewMonth) { // Check to see if it has gone to the next month if (workDay.Month != startMonth) { // It did, oh dear, we didn't want that to happen ! // We need the last business day of the month we were in workDay = GetWorkingDayDate(-1, DateTime.Parse("1 " + workDay.ToString("MMM yyyy")), Holidays, nd); } } return(workDay); }