/// <summary> /// /// </summary> /// <param name="bond"></param> /// <param name="settleDate"></param> /// <param name="ytm"></param> /// <returns>the unrounded all-in price</returns> public static double UnroundedAIP(this BesaJseBond bond, Date settleDate, double ytm) { var N = 100.0; var typicalCoupon = N * bond.annualCouponRate / 2; var t0 = bond.GetLastCouponDateOnOrBefore(settleDate); var t1 = bond.GetNextCouponDate(t0); var tradingWithNextCoupon = t1 - settleDate > bond.booksCloseDateDays; var d = tradingWithNextCoupon ? settleDate - t0 : settleDate - t1; var couponAtT1 = tradingWithNextCoupon ? typicalCoupon : 0.0; var v = 1 / (1 + ytm / 2); var n = (int)Math.Round((bond.maturityDate - t1) / 182.625); double brokenPeriod, brokenPeriodDf; if (n > 0) { brokenPeriod = ((double)t1 - settleDate) / (t1 - t0); brokenPeriodDf = Math.Pow(v, brokenPeriod); } else { brokenPeriod = ((double)t1 - settleDate) / 182.25; brokenPeriodDf = 1 / (1 + ytm * brokenPeriod / 2); } var A1 = (couponAtT1 + typicalCoupon * v * (1 - Math.Pow(v, n)) / (1 - v) + N * Math.Pow(v, n)); var unroundedAip = brokenPeriodDf * A1; return(unroundedAip); }
/// <summary> /// /// </summary> /// <param name="bond"></param> /// <param name="settleDate"></param> /// <param name="ytm"></param> /// <returns>the unrounded accrued accrued interest</returns> public static double UnroundedAccruedInterest(this BesaJseBond bond, Date settleDate) { var N = 100.0; var t0 = bond.GetLastCouponDateOnOrBefore(settleDate); var t1 = bond.GetNextCouponDate(t0); var tradingWithNextCoupon = t1 - settleDate > bond.booksCloseDateDays; var d = tradingWithNextCoupon ? settleDate - t0 : settleDate - t1; var unroundedAccrued = N * bond.annualCouponRate * d / 365.0; return(unroundedAccrued); }
/// <summary> /// /// </summary> /// <param name="bond"></param> /// <param name="settleDate"></param> /// <param name="ytm"></param> /// <returns></returns> public static ResultStore GetSpotMeasures(this BesaJseBond bond, Date settleDate, double ytm) { var N = 100.0; var typicalCoupon = N * bond.annualCouponRate / 2; var t0 = bond.GetLastCouponDateOnOrBefore(settleDate); var t1 = bond.GetNextCouponDate(t0); var n = (int)Math.Round((bond.maturityDate - t1) / 182.625); var tradingWithNextCoupon = t1 - settleDate > bond.booksCloseDateDays; var d = tradingWithNextCoupon ? settleDate - t0 : settleDate - t1; var unroundedAccrued = N * bond.annualCouponRate * d / 365.0; var roundedAccrued = Math.Round(unroundedAccrued, 5); var couponAtT1 = tradingWithNextCoupon ? typicalCoupon : 0.0; var v = 1 / (1 + ytm / 2); double brokenPeriodDf; if (n > 0) { brokenPeriodDf = Math.Pow(v, ((double)t1 - settleDate) / (t1 - t0)); } else { brokenPeriodDf = 1 / (1 + ytm * ((double)t1 - settleDate) / 365.0); } var unroundedAip = brokenPeriodDf * (couponAtT1 + typicalCoupon * v * (1 - Math.Pow(v, n)) / (1 - v) + N * Math.Pow(v, n)); var unroundedClean = unroundedAip - unroundedAccrued; var roundedClean = Math.Round(unroundedClean, 5); var roundedAip = roundedClean + roundedAccrued; var results = new ResultStore(); results.Add(Keys.RoundedAip, roundedAip); results.Add(Keys.RoundedClean, roundedClean); results.Add(Keys.UnroundedAip, unroundedAip); results.Add(Keys.UnroundedClean, unroundedClean); results.Add(Keys.UnroundedAccrued, unroundedAccrued); results.Add(Keys.TradingWithNextCoupon, tradingWithNextCoupon ? 1.0 : 0.0); return(results); }
private static double[] DeltaAndConvexity(this BesaJseBond bond, Date settleDate, double ytm) { var N = 100.0; var typicalCoupon = N * bond.annualCouponRate / 2; var t0 = bond.GetLastCouponDateOnOrBefore(settleDate); var t1 = bond.GetNextCouponDate(t0); var v = 1 / (1 + ytm / 2); var n = (int)Math.Round((bond.maturityDate - t1) / 182.625); double brokenPeriod, brokenPeriodDf, dB_dZ; double d2B_dZ2 = 0; if (n > 0) { brokenPeriod = ((double)t1 - settleDate) / (t1 - t0); brokenPeriodDf = Math.Pow(v, brokenPeriod); dB_dZ = brokenPeriod * Math.Pow(v, brokenPeriod - 1); d2B_dZ2 = brokenPeriod * (brokenPeriod - 1) * Math.Pow(v, brokenPeriod - 2); } else { brokenPeriod = ((double)t1 - settleDate) / 182.25; brokenPeriodDf = 1 / (1 + ytm * brokenPeriod / 2); dB_dZ = brokenPeriod / Math.Pow(v + brokenPeriod * (1 - v), 2); } var A1 = bond.UnroundedAIP(settleDate, ytm) / brokenPeriodDf; var dA1_dZ = typicalCoupon * ((1 - (n + 1) * Math.Pow(v, n) + n * Math.Pow(v, n + 1)) / Math.Pow(1 - v, 2)) + n * N * Math.Pow(v, n - 1); var dA_dZ = dB_dZ * A1 + dA1_dZ * brokenPeriodDf; var d2A1_dZ2 = typicalCoupon * ((2 - n * (n + 1) * Math.Pow(v, n - 1) + 2 * (Math.Pow(n, 2) - 1) * Math.Pow(v, n) - n * (n - 1) * Math.Pow(v, n + 1)) / Math.Pow(1 - v, 3)) + n * (n - 1) * N * Math.Pow(v, n - 2); var d2A_dZ2 = d2B_dZ2 * A1 + 2 * dB_dZ * dA1_dZ + d2A1_dZ2 * brokenPeriodDf; var dA_dy = -(Math.Pow(v, 2) / 2) * dA_dZ; var d2A_dy2 = (Math.Pow(v, 4) / 4) * d2A_dZ2 + (Math.Pow(v, 3) / 2) * dA_dZ; var delta = dA_dy / 100; var convexity = d2A_dy2 / bond.UnroundedAIP(settleDate, ytm); double[] measures = new double[2]; measures[0] = delta; measures[1] = convexity; return(measures); }