public ADouble ParDepositRateAD(Deposit deposit) { ADouble discFactor = ADDiscCurve.DiscFactor(deposit.StartDate, deposit.EndDate, deposit.DayCount, Interpolation); ADouble cvg = DateHandling.Cvg(deposit.StartDate, deposit.EndDate, deposit.DayCount); return(1.0 / cvg * (1.0 / discFactor - 1.0)); }
public double OisCompoundedRateAD(DateTime asOf, DateTime startDate, DateTime endDate, DayRule dayRule, DayCount dayCount, InterpMethod interpolation) { double CompoundedRate = 1; double CompoundedRate2 = 1; DateTime RollDate = startDate; while (RollDate.Date < endDate.Date) { DateTime NextBusinessDay = DateHandling.AddTenorAdjust(RollDate, "1B", DayRule.F); double Rate = ZeroRate(NextBusinessDay, interpolation); double fwdOisRate = FwdRate(asOf, RollDate, NextBusinessDay, DayRule.F, dayCount, interpolation); double disc1 = DiscFactor(asOf, RollDate, dayCount, interpolation); double disc2 = DiscFactor(asOf, NextBusinessDay, dayCount, interpolation); double Days = NextBusinessDay.Subtract(RollDate).TotalDays; double shortCvg = DateHandling.Cvg(RollDate, NextBusinessDay, dayCount); RollDate = NextBusinessDay; CompoundedRate *= (1 + fwdOisRate * shortCvg); CompoundedRate2 *= disc1 / disc2; } double coverage = DateHandling.Cvg(startDate, endDate, dayCount); return((CompoundedRate2 - 1) / coverage); }
public ADouble DepositNpvAD(Deposit deposit) { ADouble discFactor = ADDiscCurve.DiscFactor(deposit.AsOf, deposit.EndDate, deposit.DayCount, Interpolation); ADouble cvg = DateHandling.Cvg(deposit.StartDate, deposit.EndDate, deposit.DayCount); return(deposit.TradeSign * discFactor * deposit.Notional * (1.0 + deposit.FixedRate * cvg)); }
public ADouble FwdRate(DateTime asOf, DateTime startDate, DateTime endDate, DayRule dayRule, DayCount dayCount, InterpMethod interpolation) { ADouble ps = DiscFactor(asOf, startDate, dayCount, interpolation); ADouble pe = DiscFactor(asOf, endDate, dayCount, interpolation); ADouble cvg = DateHandling.Cvg(startDate, endDate, dayCount); return((ps / pe - 1.0) / cvg); }
private double CalcSimpleConvexity(DateTime asOf, DateTime startDate, DateTime endDate, DayCount dayCount) { // i.e. Convexity Adjustment = 0.5*vol^2*T*(T+delta), T's measured in year fractions. // Source: Linderstrøm double cvgAsOfToStart = DateHandling.Cvg(asOf, startDate, dayCount); double cvgAsOfToEnd = DateHandling.Cvg(asOf, endDate, dayCount); return(0.5 * 0.0012 * 0.0012 * cvgAsOfToEnd * cvgAsOfToEnd); }
public ADouble FraNpvAD(Fra fra) { ADouble fraRate = ADFwdCurveCollection.GetCurve(fra.ReferenceIndex).FwdRate(fra.AsOf, fra.StartDate, fra.EndDate, fra.DayRule, fra.DayCount, Interpolation); ADouble notional = fra.Notional; ADouble discFactor = ADDiscCurve.DiscFactor(fra.AsOf, fra.EndDate, fra.DayCount, Interpolation); ADouble coverage = DateHandling.Cvg(fra.StartDate, fra.EndDate, fra.DayCount); return(fra.TradeSign * notional * discFactor * coverage * (fraRate - fra.FixedRate)); }
public double FraNpv(Fra fra) { double fraRate = FwdCurveCollection.GetCurve(fra.ReferenceIndex).FwdRate(fra.AsOf, fra.StartDate, fra.EndDate, fra.DayRule, fra.DayCount, Interpolation); double notional = fra.Notional; double discFactor = DiscCurve.DiscFactor(fra.AsOf, fra.StartDate, fra.DayCount, Interpolation); // Note from today and to startDate => Market FRA double coverage = DateHandling.Cvg(fra.StartDate, fra.EndDate, fra.DayCount); return(fra.TradeSign * notional * discFactor * coverage * (fraRate - fra.FixedRate)); }
public ADouble OisRateAD(OisSwap swap, InterpMethod interpolation) { ADouble floatContribution = 0.0; ADouble annuity = OisAnnuityAD(swap.FixedSchedule, interpolation); DateTime asOf = swap.FloatSchedule.AsOf; for (int i = 0; i < swap.FloatSchedule.AdjEndDates.Count; i++) { DateTime startDate = swap.FloatSchedule.AdjStartDates[i]; DateTime endDate = swap.FloatSchedule.AdjEndDates[i]; ADouble compoundedRate = OisCompoundedRateAD(asOf, startDate, endDate, swap.FloatSchedule.DayRule, swap.FloatSchedule.DayCount, interpolation); ADouble discFactor = DiscFactor(asOf, endDate, swap.FixedSchedule.DayCount, interpolation); ADouble coverage = DateHandling.Cvg(startDate, endDate, swap.FloatSchedule.DayCount); floatContribution = floatContribution + discFactor * compoundedRate * coverage; } return(floatContribution / annuity); }
private void GenerateSchedule(DateTime asOf, DateTime startDate, DateTime endDate, DayCount dayCount, DayRule dayRule, CurveTenor tenor, StubPlacement stub = StubPlacement.NullStub) { // This only works for short stubs atm, although NullStub will generate a long stub DateTime AdjStart = DateHandling.AdjustDate(startDate, dayRule); DateTime AdjEnd = DateHandling.AdjustDate(endDate, dayRule); string tenorString = EnumToStr.CurveTenor(tenor); string TenorLetter = DateHandling.GetTenorLetterFromTenor(tenorString); double TenorNumber = DateHandling.GetTenorNumberFromTenor(tenorString); int periods = CalculatePeriods(startDate, endDate, tenor); // Create estimate of how long the schedule should be //double YearsUpper = DateHandling.Cvg(AdjStart, AdjEnd, dayCount); //double YearLower = DateHandling.Cvg(AsOf, AdjStart, dayCount); // Will be sorted at end (when coverages are also calculated) UnAdjStartDates.Add(StartDate); UnAdjEndDates.Add(EndDate); AdjStartDates.Add(AdjStart); AdjEndDates.Add(AdjEnd); //if (StrToEnum.ConvertTenorLetter(TenorLetter) == Tenor.M) //{ // periods = periodsInMonths / (int)TenorNumber; // //WholePeriods = periodsInMonths / (int) TenorNumber; // //double tempPeriods = YearsUpper * 12 / TenorNumber; // //WholePeriods = (int)Math.Truncate(tempPeriods); //} //else if (StrToEnum.ConvertTenorLetter(TenorLetter) == Tenor.Y) //{ // periods = periodsInMonths / (12 * (int)TenorNumber); // //WholePeriods = (int) Math.Truncate(YearsUpper); //} //else //{ // throw new ArgumentException("Can only roll out swap calender for month and year tenors"); //} if (stub == StubPlacement.Beginning) { periods += 1 * 12 / (int)Math.Round(TenorNumber); for (int i = 1; i < periods; i++) { UnAdjEndDates.Add(DateHandling.AddTenorAdjust(UnAdjEndDates[i - 1], "-" + tenorString)); AdjEndDates.Add(DateHandling.AdjustDate(UnAdjEndDates[i], DayRule)); UnAdjStartDates.Add(UnAdjEndDates[i]); AdjStartDates.Add(DateHandling.AdjustDate(UnAdjStartDates[i], DayRule)); } } else if (stub == StubPlacement.End) { periods += 1 * 12 / (int)Math.Round(TenorNumber); for (int i = 1; i < periods; i++) { UnAdjStartDates.Add(DateHandling.AddTenorAdjust(UnAdjStartDates[i - 1], tenorString)); AdjStartDates.Add(DateHandling.AdjustDate(UnAdjStartDates[i], DayRule)); UnAdjEndDates.Add(UnAdjStartDates[i]); AdjEndDates.Add(DateHandling.AdjustDate(UnAdjEndDates[i], DayRule)); } } else if (stub == StubPlacement.NullStub) { for (int i = 1; i < periods; i++) { UnAdjEndDates.Add(DateHandling.AddTenorAdjust(UnAdjEndDates[i - 1], "-" + tenorString)); AdjEndDates.Add(DateHandling.AdjustDate(UnAdjEndDates[i], DayRule)); UnAdjStartDates.Add(UnAdjEndDates[i]); AdjStartDates.Add(DateHandling.AdjustDate(UnAdjStartDates[i], DayRule)); } } // Sort dates according to date UnAdjStartDates.Sort(new Comparison <DateTime>((x, y) => x.CompareTo(y))); UnAdjEndDates.Sort(new Comparison <DateTime>((x, y) => x.CompareTo(y))); AdjStartDates.Sort(new Comparison <DateTime>((x, y) => x.CompareTo(y))); AdjEndDates.Sort(new Comparison <DateTime>((x, y) => x.CompareTo(y))); for (int i = 0; i < AdjStartDates.Count; i++) { Coverages.Add(DateHandling.Cvg(AdjStartDates[i], AdjEndDates[i], DayCount)); } }
// Ideally, this should be a derived class on SwapSchedule, since an // OIS schedule (in this context) is either a short period, or 1Y schedule with // a stub in the end. For our purpose, we just define a derived the class // that only works for our purpose (i.e. it's not general.) public OisSchedule(DateTime asOf, string startTenor, string endTenor, string settlementLag, DayCount dayCount, DayRule dayRule) : base(asOf, startTenor, endTenor, dayCount, dayRule) { Tenor startTenorEnum = GetLetterFromTenor(startTenor); Tenor endTenorEnum = GetLetterFromTenor(endTenor); UnAdjStartDates.Add(StartDate); AdjStartDates.Add(StartDate); // Just to make sure we compare with both "1Y" and "12M" (because i'm lazy in correcting for DayCount) if (CompareTenors(endTenor, "1Y") == false && CompareTenors(endTenor, "12M") == false) { // Simple OIS swap double cvg = DateHandling.Cvg(StartDate, EndDate, dayCount); UnAdjEndDates.Add(EndDate); AdjEndDates.Add(DateHandling.AdjustDate(EndDate)); Coverages.Add(cvg); return; } else { int months = 0; // 1Y periods + stub int periods, years; if (endTenorEnum == Tenor.Y) { periods = GetNumberFromTenor(endTenor); years = periods; } else if (endTenorEnum == Tenor.M) { years = (int)Math.Truncate(GetNumberFromTenor(endTenor) / 12.0); if (GetNumberFromTenor(endTenor) % 12 == 0) { months = 0; periods = years; } else { months = GetNumberFromTenor(endTenor) - 12 * years; periods = years + 1; } } else { throw new InvalidOperationException("OIS Schedule only works for Y,M endTenors"); } UnAdjEndDates.Add(DateHandling.AddTenorAdjust(StartDate, "1Y")); AdjEndDates.Add(DateHandling.AdjustDate(UnAdjEndDates[0], DayRule.N)); Coverages.Add(DateHandling.Cvg(AdjStartDates[0], AdjEndDates[0], DayCount)); // Generate Schedule // We start from 1 since first days are filled out // We only end here if we have more than 1 period for (int j = 1; j <= periods; j++) { if (periods > years && periods == j + 1) // In case we have tenor like "18M" and have to create a stub periods { string excessTenor = months.ToString() + "M"; UnAdjStartDates.Add(DateHandling.AddTenorAdjust(UnAdjStartDates[j - 1], "1Y", dayRule)); AdjStartDates.Add(DateHandling.AdjustDate(UnAdjStartDates[j], dayRule)); UnAdjEndDates.Add(DateHandling.AddTenorAdjust(UnAdjEndDates[j - 1], excessTenor, dayRule)); AdjEndDates.Add(DateHandling.AdjustDate(UnAdjEndDates[j], dayRule)); Coverages.Add(DateHandling.Cvg(AdjStartDates[j], AdjEndDates[j], DayCount)); } else { if (j < periods) { UnAdjStartDates.Add(DateHandling.AddTenorAdjust(UnAdjStartDates[j - 1], "1Y", dayRule)); AdjStartDates.Add(DateHandling.AdjustDate(UnAdjStartDates[j], dayRule)); UnAdjEndDates.Add(DateHandling.AddTenorAdjust(UnAdjEndDates[j - 1], "1Y", dayRule)); AdjEndDates.Add(DateHandling.AdjustDate(UnAdjEndDates[j], dayRule)); Coverages.Add(DateHandling.Cvg(AdjStartDates[j], AdjEndDates[j], DayCount)); } } } } }
public ADouble DiscFactor(DateTime asOf, DateTime date, DayCount dayCount, InterpMethod interpolation) { return(ADouble.Exp(-1.0 * ZeroRate(date, interpolation) * DateHandling.Cvg(asOf, date, dayCount))); }