// Calculate Yield from dirty price public static double YieldFromFullPrice(double fullPrice, double yieldGuess, Date[] CashFlowsDate, double[] CashFlows, int freq, Dc dc, Date SettlementDate, Compounding compounding, double FaceValue) { int N = CashFlowsDate.GetLength(0); // number of Cash flows dates int k = Array.FindIndex(CashFlowsDate, n => n > SettlementDate); // get index of first cash flow after settlement date Date[] Dates = new Date[N - k]; // array with pay dates after settlement double[] Flows = new double[N - k]; // flows after settlement Array.Copy(CashFlowsDate, k, Dates, 0, N - k); // fill array with needed data Array.Copy(CashFlows, k, Flows, 0, N - k); // fill array with needed data // define my function: we should find yield that match starting price NumMethod.myMethodDelegate fname = y_ => fullPrice - FullPriceFromYield(y_, Dates, Flows, freq, dc, SettlementDate, compounding, FaceValue); // return yield return(NumMethod.NewRapNum(fname, yieldGuess)); }
public static void SimpleBootstrap20Y() { #region data // We load a set of data (not real) DataForCapletExample1 data1 = new DataForCapletExample1(); double[] df = data1.df(); double[] yf = data1.yf(); double[] T = data1.T(); int N = df.Length; double[] fwd = new double[N]; double[] atmfwd = new double[N]; double[] capletVol = new double[N]; double[] capPrice = new double[N]; double df_ini = data1.df_ini; double[] capVol = data1.capVol(); #endregion // calculate fwd fwd[0] = ((df_ini / df[0]) - 1) / yf[0]; for (int i = 1; i < df.Length; i++) { fwd[i] = ((df[i - 1] / df[i]) - 1) / yf[i]; } // calculate ATM strike double summ = 0.0; for (int i = 0; i < df.Length; i++) { summ += yf[i] * df[i]; atmfwd[i] = (df_ini - df[i]) / summ; } double shorterCap = 0.0; // calculate cap price using flat vol for (int i = 0; i < N; i++) { shorterCap = 0.0; for (int j = 0; j <= i; j++) { capPrice[i] += Formula.CapletBlack(T[j], yf[j], 100, atmfwd[i], capVol[i], df[j], fwd[j]); } for (int j = 0; j < i; j++) { shorterCap += Formula.CapletBlack(T[j], yf[j], 100, atmfwd[i], capletVol[j], df[j], fwd[j]); } NumMethod.myMethodDelegate fname = s => capPrice[i] - shorterCap - Formula.CapletBlack(T[i], yf[i], 100, atmfwd[i], s, df[i], fwd[i]); capletVol[i] = NumMethod.NewRapNum(fname, 0.20); } #region print results ExcelMechanisms exl = new ExcelMechanisms(); Vector <double> CapletVol = new Vector <double>(capletVol, 1); Vector <double> CapVol = new Vector <double>(capVol, 1); Vector <double> xarr = new Vector <double>(T, 1); List <string> labels = new List <string>() { "CapletVol", "CapVol" }; List <Vector <double> > yarrs = new List <Vector <double> >() { CapletVol, CapVol }; exl.printInExcel <double>(xarr, labels, yarrs, "Caplet vs Cap Vol", "Term", "Volatility"); #endregion }
public static void SimpleBootstrap() { #region data // Array of discount factor double[] df = new double[] { 0.994236269575566, 0.991625192926998, 0.989041421054714, 0.986231394133455, 0.983496974873945, 0.980646228901972, 0.977577789248498, 0.974244477497738, 0.97067019775667, 0.966860206840406, 0.96281976156406, 0.958481789220407, 0.953769370400552, 0.948855174348367, 0.94375920324068, 0.93838613470982, 0.93274533960824, 0.926957758932136, 0.92108389607756 }; // array of yf of each caplet double[] yf = new double[] { 0.255555555555556, 0.261111111111111, 0.252777777777778, 0.244444444444444, 0.261111111111111, 0.252777777777778, 0.252777777777778, 0.252777777777778, 0.252777777777778, 0.252777777777778, 0.252777777777778, 0.252777777777778, 0.252777777777778, 0.255555555555556, 0.252777777777778, 0.252777777777778, 0.255555555555556, 0.255555555555556, 0.252777777777778 }; // array of expiry of each caplet double[] T_1 = new double[] { 0.252054794520548, 0.50958904109589, 0.758904109589041, 1, 1.25753424657534, 1.50684931506849, 1.75616438356164, 2.00547945205479, 2.25479452054795, 2.5041095890411, 2.75342465753425, 3.0027397260274, 3.25205479452055, 3.5041095890411, 3.75342465753425, 4.0027397260274, 4.25479452054795, 4.50684931506849, 4.75616438356164 }; int N = df.Length; // number of elements double[] fwd = new double[N]; // to contain forward rate double[] atmfwd = new double[N]; // to contain ATM forward Cap strike double[] capletVol = new double[N]; // to contain each caplet volatilities double[] capPrice = new double[N]; // to contain Cap price double df_ini = 0.99702; // first discount factor on T[0] // Cap Volatility from the market double[] capVol = new double[] { 0.5458, 0.5458, 0.5458, 0.55289, 0.557646575342466, 0.569168493150685, 0.582581643835616, 0.595015616438357, 0.563876164383561, 0.532736712328767, 0.501597260273972, 0.470798904109589, 0.470699178082192, 0.470598356164384, 0.470498630136986, 0.470348767123288, 0.465635342465753, 0.460921917808219, 0.456259726027397 }; #endregion // calculate fwd fwd[0] = ((df_ini / df[0]) - 1) / yf[0]; for (int i = 1; i < df.Length; i++) { fwd[i] = ((df[i - 1] / df[i]) - 1) / yf[i]; } // calculate ATM strike double summ = 0.0; for (int i = 0; i < df.Length; i++) { summ += yf[i] * df[i]; atmfwd[i] = (df_ini - df[i]) / summ; } double shorterCap = 0.0; // Shorter Cap is the same Cap without last caplet // calculate cap price using cal vol for (int i = 0; i < N; i++) { shorterCap = 0.0; // Note: here I use cap Vol for (int j = 0; j <= i; j++) { capPrice[i] += Formula.CapletBlack(T_1[j], yf[j], 100, atmfwd[i], capVol[i], df[j], fwd[j]); } // Note: here I use Caplet vol for (int j = 0; j < i; j++) { shorterCap += Formula.CapletBlack(T_1[j], yf[j], 100, atmfwd[i], capletVol[j], df[j], fwd[j]); } // Inizialize Newton Raphson solver NumMethod.myMethodDelegate fname = s => capPrice[i] - shorterCap - Formula.CapletBlack(T_1[i], yf[i], 100, atmfwd[i], s, df[i], fwd[i]); capletVol[i] = NumMethod.NewRapNum(fname, 0.20); // the missing caplet volatility } // Print results Console.WriteLine("Time ATMCapStrike CapletVol CapVol"); for (int i = 0; i < capletVol.Length; i++) { // Caplet expiry is T_1+yf (expiry + caplet year factor) Console.WriteLine("{0:N2} {1:p5} {2:p5} {3:p5}", T_1[i] + yf[i], atmfwd[i], capletVol[i], capVol[i]); } }
public static void SimpleBootstrapOneCaplet() { #region InputData double[] yf = new double[] { 0.25278, 0.25556, 0.25556, 0.25 }; double[] T = new double[] { 0.25, 0.50, 0.75, 1.0 }; double[] df = new double[] { 0.99406, 0.99153, 0.98904, 0.98633 }; // One curve framework: traditional fwd calc double[] fwd = new double[4]; fwd[0] = ((0.99695 / df[0]) - 1) / yf[0]; for (int i = 1; i < df.Length; i++) { fwd[i] = ((df[i - 1] / df[i]) - 1) / yf[i]; } double K = 0.0102; double sigma1Y3M = 0.2402; double sigma1Y = 0.2364; #endregion // Price of 1Y3M (18 months) Cap @ vol = sigma1Y3M double pxCap1Y3M = Formula.CapBlack(T, yf, 1, K, sigma1Y3M, df, fwd); // Price of 1Y Cap @ vol=sigma1Y double pxCap1Y = 0.0; for (int i = 0; i < df.Length - 1; i++) { pxCap1Y += Formula.CapletBlack(T[i], yf[i], 1, K, sigma1Y, df[i], fwd[i]); } // Price of 3M Caplet starting in 1Y double pxCaplet3M = pxCap1Y3M - pxCap1Y; // Inizialize Newton-Raphson algorithm to find Caplet implied vol NumMethod.myMethodDelegate fname = s => pxCaplet3M - Formula.CapletBlack(T[3], yf[3], 1, K, s, df[3], fwd[3]); // vol is the implied vol of 3M Caplet starting in 1Y. (0.20 is a starting guess) double implVol = NumMethod.NewRapNum(fname, 0.20); // array of caplet volatility (PieceWiseConstant under1Y) double[] capletVol = new double[] { sigma1Y, sigma1Y, sigma1Y, implVol }; // printing results Console.WriteLine("1Y Cap Vol {0:p5}", sigma1Y); Console.WriteLine("1Y3M Cap Vol {0:p5}", sigma1Y3M); Console.WriteLine("Calculated Implied 3M Caplet Vol Starting in 1Y: {0:p5}", implVol); double pxCaplet = 0.0; double pxCap = 0.0; Console.WriteLine("\nUsing Caplet Volatilities"); for (int i = 0; i < df.Length; i++) { pxCaplet = Formula.CapletBlack(T[i], yf[i], 1, K, capletVol[i], df[i], fwd[i]); pxCap += pxCaplet; Console.WriteLine("Caplet #: {0} CapletVol:{1:p4} Px: {2:n5} Cumulated Price: {3:n7}", i + 1, capletVol[i], pxCaplet, pxCap); } Console.WriteLine("Price Cap as sum of Caplets using Caplet Vol: {0:n7}", pxCap); // reset pxCaplet = 0.0; pxCap = 0.0; Console.WriteLine("\nUsing Cap Volatilities"); for (int i = 0; i < df.Length; i++) { pxCaplet = Formula.CapletBlack(T[i], yf[i], 1, K, sigma1Y3M, df[i], fwd[i]); pxCap += pxCaplet; Console.WriteLine("Caplet #: {0} CapletVol:{1:p4} Px: {2:n5} Cumulated Price: {3:n7}", i + 1, sigma1Y3M, pxCaplet, pxCap); } Console.WriteLine("Price Cap as sum of Caplets using Cap Vol: {0:n7}", pxCap); // pxCap = pxCap1Y3M }