// Calculate sensitivities public static void Sensitivities() { #region Inputs // Start input Date refDate = new Date(2019, 2, 25); // I populate market rates set: from file, from real time, ... RateSet mktRates = new RateSet(refDate); // Depos mktRates.Add(1.243e-2, "1m", BuildingBlockType.EURDEPO); mktRates.Add(1.435e-2, "3m", BuildingBlockType.EURDEPO); mktRates.Add(1.720e-2, "6m", BuildingBlockType.EURDEPO); // Swap Vs 6M mktRates.Add(1.869e-2, "1Y", BuildingBlockType.EURSWAP6M); mktRates.Add(2.316e-2, "2Y", BuildingBlockType.EURSWAP6M); mktRates.Add(2.544e-2, "3Y", BuildingBlockType.EURSWAP6M); mktRates.Add(2.745e-2, "4Y", BuildingBlockType.EURSWAP6M); mktRates.Add(2.915e-2, "5Y", BuildingBlockType.EURSWAP6M); mktRates.Add(3.057e-2, "6Y", BuildingBlockType.EURSWAP6M); mktRates.Add(3.175e-2, "7Y", BuildingBlockType.EURSWAP6M); mktRates.Add(3.273e-2, "8Y", BuildingBlockType.EURSWAP6M); mktRates.Add(3.362e-2, "9Y", BuildingBlockType.EURSWAP6M); mktRates.Add(3.442e-2, "10Y", BuildingBlockType.EURSWAP6M); mktRates.Add(3.589e-2, "12Y", BuildingBlockType.EURSWAP6M); mktRates.Add(3.750e-2, "15Y", BuildingBlockType.EURSWAP6M); mktRates.Add(3.835e-2, "20Y", BuildingBlockType.EURSWAP6M); mktRates.Add(3.787e-2, "25Y", BuildingBlockType.EURSWAP6M); // I shift 1bp up 10y swap input rate int IndexShifted = 12; RateSet mktRates2 = mktRates.ShiftedRateSet(IndexShifted, 0.0001); // print out first and second market input rates for (int i = 0; i < mktRates.Count; i++) { Console.WriteLine("First: {0} {1} Second: {2} {3}", mktRates.Item(i).M.GetPeriodStringFormat(), mktRates.Item(i).V, mktRates2.Item(i).M.GetPeriodStringFormat(), mktRates2.Item(i).V); } #endregion end Inputs #region building curve // First curve: using markets rates SingleCurveBuilderInterpBestFit <OnLogDf, SimpleCubicInterpolator> c1 = new SingleCurveBuilderInterpBestFit <OnLogDf, SimpleCubicInterpolator>(mktRates); // Second curve: like c1 but 10Y input rate is shifted SingleCurveBuilderInterpBestFit <OnLogDf, SimpleCubicInterpolator> c2 = new SingleCurveBuilderInterpBestFit <OnLogDf, SimpleCubicInterpolator>(mktRates2); string swapTenor = "10y"; // you can change it #endregion end building curve #region myFunction Func <SwapStyle, IRateCurve, double> NPV = (BB, c) => { #region FixLeg // fixed leg data double[] yfFixLeg = BB.scheduleLeg1.GetYFVect(BB.swapLeg1.DayCount); // fixed is leg 1 // dfs array of fixed lag Date[] dfDates = BB.scheduleLeg1.payDates; // serial date of fixed lag (each dates we should find df) // # of fixed cash flows int n_fix = dfDates.Length; double NPV_fix = 0.0; // calculate df for (int i = 0; i < n_fix; i++) { NPV_fix += c.Df(dfDates[i]) * yfFixLeg[i] * BB.rateValue; // df*yf } // NPV_fix *= BB.rateValue; #endregion #region FloatLeg // fixed leg data double[] yfFloatLeg = BB.scheduleLeg2.GetYFVect(BB.swapLeg2.DayCount); // float is leg 2 // dfs array of fixed lag Date[] dfDatesFloat = BB.scheduleLeg2.payDates; // serial date of float lag (each dates we should find df) Date[] toDateFloat = BB.scheduleLeg2.toDates; // # of fixed cash flows int n_float = dfDatesFloat.Length; double[] fwd = new double[n_float]; fwd[0] = ((1 / c.Df(toDateFloat[0])) - 1) / refDate.YF(toDateFloat[0], Dc._Act_360);; for (int i = 1; i < n_float; i++) { double yf = toDateFloat[i - 1].YF(toDateFloat[i], Dc._Act_360); double df_ini = c.Df(toDateFloat[i - 1]); double df_end = c.Df(toDateFloat[i]); fwd[i] = ((df_ini / df_end) - 1) / yf; } double NPV_float = 0.0; // calculate df for (int i = 0; i < n_float; i++) { NPV_float += c.Df(dfDatesFloat[i]) * yfFloatLeg[i] * fwd[i]; // df*yf } #endregion return(NPV_fix - NPV_float); }; #endregion #region Print results // test forward swap starting in ref date (it should be like simple spot swap) double swapRate = c1.SwapFwd(refDate, swapTenor); // I create the swap according to standard convention SwapStyle y = (SwapStyle) new BuildingBlockFactory().CreateBuildingBlock(refDate, swapRate, swapTenor, BuildingBlockType.EURSWAP6M); // initial NPV double iniMTM = NPV(y, c1) * 100000000; // print out Console.WriteLine("IRS to be priced tenor: {0}. IRS to be priced rate: {1:f5}", swapTenor, swapRate); Console.WriteLine("{0} swap ATM fwd according the starting curve: {1:f5}. Starting P&L {2:f}", swapTenor, swapRate, iniMTM); Console.WriteLine("Let's shift {0} rate from {1:f5} to {2:f5}", mktRates.Item(IndexShifted).M.GetPeriodStringFormat(), mktRates.Item(IndexShifted).V, mktRates2.Item(IndexShifted).V); // NPV after shift double endMTM = NPV(y, c2) * 100000000; Console.WriteLine("{0} swap ATM fwd after shifting: {1:f5}. P&L after shifting {2:f}", swapTenor, c2.SwapFwd(refDate, swapTenor), endMTM); Console.WriteLine("Press a key to continue"); Console.ReadLine(); #endregion }