public void testATMRate() { CommonVars vars = new CommonVars(); int[] lengths = { 1, 2, 3, 5, 7, 10, 15, 20 }; double[] strikes = { 0.0, 0.03, 0.04, 0.05, 0.06, 0.07 }; double[] vols = { 0.01, 0.05, 0.10, 0.15, 0.20 }; Date startDate = vars.termStructure.link.referenceDate(); for (int i = 0; i < lengths.Length; i++) { List<CashFlow> leg = vars.makeLeg(startDate, lengths[i]); Date maturity = vars.calendar.advance(startDate, lengths[i], TimeUnit.Years, vars.convention); Schedule schedule = new Schedule(startDate, maturity, new Period(vars.frequency), vars.calendar, vars.convention, vars.convention, DateGeneration.Rule.Forward, false); for (int j = 0; j < strikes.Length; j++) { for (int k = 0; k < vols.Length; k++) { CapFloor cap = vars.makeCapFloor(CapFloorType.Cap, leg, strikes[j], vols[k]); CapFloor floor = vars.makeCapFloor(CapFloorType.Floor, leg, strikes[j], vols[k]); double capATMRate = cap.atmRate(vars.termStructure); double floorATMRate = floor.atmRate(vars.termStructure); if (!checkAbsError(floorATMRate, capATMRate, 1.0e-10)) Assert.Fail( "Cap ATM Rate and floor ATM Rate should be equal :\n" + " length: " + lengths[i] + " years\n" + " volatility: " + vols[k] + "\n" + " strike: " + strikes[j] + "\n" + " cap ATM rate: " + capATMRate + "\n" + " floor ATM rate:" + floorATMRate + "\n" + " relative Error:" + Utilities.relativeError(capATMRate, floorATMRate, capATMRate) * 100 + "%"); VanillaSwap swap = new VanillaSwap(VanillaSwap.Type.Payer, vars.nominals[0], schedule, floorATMRate, vars.index.dayCounter(), schedule, vars.index, 0.0, vars.index.dayCounter()); swap.setPricingEngine((IPricingEngine)( new DiscountingSwapEngine(vars.termStructure))); double swapNPV = swap.NPV(); if (!checkAbsError(swapNPV, 0, 1.0e-10)) Assert.Fail( "the NPV of a Swap struck at ATM rate " + "should be equal to 0:\n" + " length: " + lengths[i] + " years\n" + " volatility: " + vols[k] + "\n" + " ATM rate: " + floorATMRate + "\n" + " swap NPV: " + swapNPV); } } } }
public void testVega() { CommonVars vars = new CommonVars(); int[] lengths = { 1, 2, 3, 4, 5, 6, 7, 10, 15, 20, 30 }; double[] vols = { 0.01, 0.05, 0.10, 0.15, 0.20 }; double[] strikes = { 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09 }; CapFloorType[] types = { CapFloorType.Cap, CapFloorType.Floor }; Date startDate = vars.termStructure.link.referenceDate(); double shift = 1e-8; double tolerance = 0.005; for (int i = 0; i < lengths.Length; i++) { for (int j = 0; j < vols.Length; j++) { for (int k = 0; k < strikes.Length; k++) { for (int h = 0; h < types.Length; h++) { List <CashFlow> leg = vars.makeLeg(startDate, lengths[i]); CapFloor capFloor = vars.makeCapFloor(types[h], leg, strikes[k], vols[j]); CapFloor shiftedCapFloor2 = vars.makeCapFloor(types[h], leg, strikes[k], vols[j] + shift); CapFloor shiftedCapFloor1 = vars.makeCapFloor(types[h], leg, strikes[k], vols[j] - shift); double value1 = shiftedCapFloor1.NPV(); double value2 = shiftedCapFloor2.NPV(); double numericalVega = (value2 - value1) / (2 * shift); if (numericalVega > 1.0e-4) { double analyticalVega = (double)capFloor.result("vega"); double discrepancy = Math.Abs(numericalVega - analyticalVega); discrepancy /= numericalVega; if (discrepancy > tolerance) { QAssert.Fail( "failed to compute cap/floor vega:" + "\n lengths: " + new Period(lengths[j], TimeUnit.Years) + "\n strike: " + strikes[k] + "\n types: " + types[h] + "\n calculated: " + analyticalVega + "\n expected: " + numericalVega + "\n discrepancy: " + discrepancy + "\n tolerance: " + tolerance); } } } } } } }
public void testParity() { CommonVars vars = new CommonVars(); int[] lengths = { 1, 2, 3, 5, 7, 10, 15, 20 }; double[] strikes = { 0.0, 0.03, 0.04, 0.05, 0.06, 0.07 }; double[] vols = { 0.01, 0.05, 0.10, 0.15, 0.20 }; Date startDate = vars.termStructure.link.referenceDate(); for (int i = 0; i < lengths.Length; i++) { for (int j = 0; j < strikes.Length; j++) { for (int k = 0; k < vols.Length; k++) { List <CashFlow> leg = vars.makeLeg(startDate, lengths[i]); Instrument cap = vars.makeCapFloor(CapFloorType.Cap, leg, strikes[j], vols[k]); Instrument floor = vars.makeCapFloor(CapFloorType.Floor, leg, strikes[j], vols[k]); Date maturity = vars.calendar.advance(startDate, lengths[i], TimeUnit.Years, vars.convention); Schedule schedule = new Schedule(startDate, maturity, new Period(vars.frequency), vars.calendar, vars.convention, vars.convention, DateGeneration.Rule.Forward, false); VanillaSwap swap = new VanillaSwap(VanillaSwap.Type.Payer, vars.nominals[0], schedule, strikes[j], vars.index.dayCounter(), schedule, vars.index, 0.0, vars.index.dayCounter()); swap.setPricingEngine((IPricingEngine) new DiscountingSwapEngine(vars.termStructure)); // FLOATING_POINT_EXCEPTION if (Math.Abs((cap.NPV() - floor.NPV()) - swap.NPV()) > 1.0e-10) { QAssert.Fail( "put/call parity violated:\n" + " length: " + lengths[i] + " years\n" + " volatility: " + vols[k] + "\n" + " strike: " + strikes[j] + "\n" + " cap value: " + cap.NPV() + "\n" + " floor value: " + floor.NPV() + "\n" + " swap value: " + swap.NPV()); } } } } }
public void testConsistency() { CommonVars vars = new CommonVars(); int[] lengths = { 1, 2, 3, 5, 7, 10, 15, 20 }; double[] cap_rates = { 0.03, 0.04, 0.05, 0.06, 0.07 }; double[] floor_rates = { 0.03, 0.04, 0.05, 0.06, 0.07 }; double[] vols = { 0.01, 0.05, 0.10, 0.15, 0.20 }; Date startDate = vars.termStructure.link.referenceDate(); for (int i = 0; i < lengths.Length; i++) { for (int j = 0; j < cap_rates.Length; j++) { for (int k = 0; k < floor_rates.Length; k++) { for (int l = 0; l < vols.Length; l++) { List <CashFlow> leg = vars.makeLeg(startDate, lengths[i]); Instrument cap = vars.makeCapFloor(CapFloorType.Cap, leg, cap_rates[j], vols[l]); Instrument floor = vars.makeCapFloor(CapFloorType.Floor, leg, floor_rates[k], vols[l]); Collar collar = new Collar(leg, new InitializedList <double>(1, cap_rates[j]), new InitializedList <double>(1, floor_rates[k])); collar.setPricingEngine(vars.makeEngine(vols[l])); if (Math.Abs((cap.NPV() - floor.NPV()) - collar.NPV()) > 1e-10) { QAssert.Fail( "inconsistency between cap, floor and collar:\n" + " length: " + lengths[i] + " years\n" + " volatility: " + vols[l] + "\n" + " cap value: " + cap.NPV() + " at strike: " + cap_rates[j] + "\n" + " floor value: " + floor.NPV() + " at strike: " + floor_rates[k] + "\n" + " collar value: " + collar.NPV()); } } } } } }
public void testCachedValue() { CommonVars vars = new CommonVars(); Date cachedToday = new Date(14, Month.March, 2002), cachedSettlement = new Date(18, Month.March, 2002); Settings.setEvaluationDate(cachedToday); vars.termStructure.linkTo(Utilities.flatRate(cachedSettlement, 0.05, new Actual360())); Date startDate = vars.termStructure.link.referenceDate(); List <CashFlow> leg = vars.makeLeg(startDate, 20); Instrument cap = vars.makeCapFloor(CapFloorType.Cap, leg, 0.07, 0.20); Instrument floor = vars.makeCapFloor(CapFloorType.Floor, leg, 0.03, 0.20); // par coupon price double cachedCapNPV = 6.87570026732, cachedFloorNPV = 2.65812927959; // index fixing price //Real cachedCapNPV = 6.87630307745, // cachedFloorNPV = 2.65796764715; // test Black cap price against cached value if (Math.Abs(cap.NPV() - cachedCapNPV) > 1.0e-11) { QAssert.Fail("failed to reproduce cached cap value:\n" + " calculated: " + cap.NPV() + "\n" + " expected: " + cachedCapNPV); } // test Black floor price against cached value if (Math.Abs(floor.NPV() - cachedFloorNPV) > 1.0e-11) { QAssert.Fail("failed to reproduce cached floor value:\n" + " calculated: " + floor.NPV() + "\n" + " expected: " + cachedFloorNPV); } }
public void testImpliedVolatility() { CommonVars vars = new CommonVars(); int maxEvaluations = 100; double tolerance = 1.0e-6; CapFloorType[] types = { CapFloorType.Cap, CapFloorType.Floor }; double[] strikes = { 0.02, 0.03, 0.04 }; int[] lengths = { 1, 5, 10 }; // test data double[] rRates = { 0.02, 0.03, 0.04 }; double[] vols = { 0.01, 0.20, 0.30, 0.70, 0.90 }; for (int k = 0; k < lengths.Length; k++) { List <CashFlow> leg = vars.makeLeg(vars.settlement, lengths[k]); for (int i = 0; i < types.Length; i++) { for (int j = 0; j < strikes.Length; j++) { CapFloor capfloor = vars.makeCapFloor(types[i], leg, strikes[j], 0.0); for (int n = 0; n < rRates.Length; n++) { for (int m = 0; m < vols.Length; m++) { double r = rRates[n]; double v = vols[m]; vars.termStructure.linkTo(Utilities.flatRate(vars.settlement, r, new Actual360())); capfloor.setPricingEngine(vars.makeEngine(v)); double value = capfloor.NPV(); double implVol = 0.0; try { implVol = capfloor.impliedVolatility(value, vars.termStructure, 0.10, tolerance, maxEvaluations); } catch (Exception e) { // couldn't bracket? capfloor.setPricingEngine(vars.makeEngine(0.0)); double value2 = capfloor.NPV(); if (Math.Abs(value - value2) < tolerance) { // ok, just skip: continue; } // otherwise, report error QAssert.Fail("implied vol failure: " + typeToString(types[i]) + " strike: " + strikes[j] + " risk-free: " + r + " length: " + lengths[k] + "Y" + " volatility: " + v + e.Message); } if (Math.Abs(implVol - v) > tolerance) { // the difference might not matter capfloor.setPricingEngine(vars.makeEngine(implVol)); double value2 = capfloor.NPV(); if (Math.Abs(value - value2) > tolerance) { QAssert.Fail( typeToString(types[i]) + ":" + " strike: " + strikes[j] + "\n" + " risk-free rate: " + r + "\n" + " length: " + lengths[k] + " years\n\n" + " original volatility: " + v + "\n" + " price: " + value + "\n" + " implied volatility: " + implVol + "\n" + " corresponding price: " + value2); } } } } } } } }
public void testATMRate() { CommonVars vars = new CommonVars(); int[] lengths = { 1, 2, 3, 5, 7, 10, 15, 20 }; double[] strikes = { 0.0, 0.03, 0.04, 0.05, 0.06, 0.07 }; double[] vols = { 0.01, 0.05, 0.10, 0.15, 0.20 }; Date startDate = vars.termStructure.link.referenceDate(); for (int i = 0; i < lengths.Length; i++) { List <CashFlow> leg = vars.makeLeg(startDate, lengths[i]); Date maturity = vars.calendar.advance(startDate, lengths[i], TimeUnit.Years, vars.convention); Schedule schedule = new Schedule(startDate, maturity, new Period(vars.frequency), vars.calendar, vars.convention, vars.convention, DateGeneration.Rule.Forward, false); for (int j = 0; j < strikes.Length; j++) { for (int k = 0; k < vols.Length; k++) { CapFloor cap = vars.makeCapFloor(CapFloorType.Cap, leg, strikes[j], vols[k]); CapFloor floor = vars.makeCapFloor(CapFloorType.Floor, leg, strikes[j], vols[k]); double capATMRate = cap.atmRate(vars.termStructure); double floorATMRate = floor.atmRate(vars.termStructure); if (!checkAbsError(floorATMRate, capATMRate, 1.0e-10)) { QAssert.Fail( "Cap ATM Rate and floor ATM Rate should be equal :\n" + " length: " + lengths[i] + " years\n" + " volatility: " + vols[k] + "\n" + " strike: " + strikes[j] + "\n" + " cap ATM rate: " + capATMRate + "\n" + " floor ATM rate:" + floorATMRate + "\n" + " relative Error:" + Utilities.relativeError(capATMRate, floorATMRate, capATMRate) * 100 + "%"); } VanillaSwap swap = new VanillaSwap(VanillaSwap.Type.Payer, vars.nominals[0], schedule, floorATMRate, vars.index.dayCounter(), schedule, vars.index, 0.0, vars.index.dayCounter()); swap.setPricingEngine((IPricingEngine)( new DiscountingSwapEngine(vars.termStructure))); double swapNPV = swap.NPV(); if (!checkAbsError(swapNPV, 0, 1.0e-10)) { QAssert.Fail( "the NPV of a Swap struck at ATM rate " + "should be equal to 0:\n" + " length: " + lengths[i] + " years\n" + " volatility: " + vols[k] + "\n" + " ATM rate: " + floorATMRate + "\n" + " swap NPV: " + swapNPV); } } } } }
public void testStrikeDependency() { CommonVars vars = new CommonVars(); int[] lengths = { 1, 2, 3, 5, 7, 10, 15, 20 }; double[] vols = { 0.01, 0.05, 0.10, 0.15, 0.20 }; double[] strikes = { 0.03, 0.04, 0.05, 0.06, 0.07 }; Date startDate = vars.termStructure.link.referenceDate(); for (int i = 0; i < lengths.Length; i++) { for (int j = 0; j < vols.Length; j++) { // store the results for different strikes... List <double> cap_values = new List <double>(), floor_values = new List <double>(); for (int k = 0; k < strikes.Length; k++) { List <CashFlow> leg = vars.makeLeg(startDate, lengths[i]); Instrument cap = vars.makeCapFloor(CapFloorType.Cap, leg, strikes[k], vols[j]); cap_values.Add(cap.NPV()); Instrument floor = vars.makeCapFloor(CapFloorType.Floor, leg, strikes[k], vols[j]); floor_values.Add(floor.NPV()); } // and check that they go the right way for (int k = 0; k < cap_values.Count - 1; k++) { if (cap_values[k] < cap_values[k + 1]) { QAssert.Fail( "NPV is increasing with the strike in a cap: \n" + " length: " + lengths[i] + " years\n" + " volatility: " + vols[j] + "\n" + " value: " + cap_values[k] + " at strike: " + strikes[k] + "\n" + " value: " + cap_values[k + 1] + " at strike: " + strikes[k + 1]); } } // same for floors for (int k = 0; k < floor_values.Count - 1; k++) { if (floor_values[k] > floor_values[k + 1]) { QAssert.Fail( "NPV is decreasing with the strike in a floor: \n" + " length: " + lengths[i] + " years\n" + " volatility: " + vols[j] + "\n" + " value: " + floor_values[k] + " at strike: " + strikes[k] + "\n" + " value: " + floor_values[k + 1] + " at strike: " + strikes[k + 1]); } } } } }
public void testVega() { CommonVars vars = new CommonVars(); int[] lengths = { 1, 2, 3, 4, 5, 6, 7, 10, 15, 20, 30 }; double[] vols = { 0.01, 0.05, 0.10, 0.15, 0.20 }; double[] strikes = { 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09 }; CapFloorType[] types = { CapFloorType.Cap, CapFloorType.Floor }; Date startDate = vars.termStructure.link.referenceDate(); double shift = 1e-8; double tolerance = 0.005; for (int i = 0; i < lengths.Length; i++) { for (int j = 0; j < vols.Length; j++) { for (int k = 0; k < strikes.Length; k++) { for (int h = 0; h < types.Length; h++) { List<CashFlow> leg = vars.makeLeg(startDate, lengths[i]); CapFloor capFloor = vars.makeCapFloor(types[h], leg, strikes[k], vols[j]); CapFloor shiftedCapFloor2 = vars.makeCapFloor(types[h], leg, strikes[k], vols[j] + shift); CapFloor shiftedCapFloor1 = vars.makeCapFloor(types[h], leg, strikes[k], vols[j] - shift); double value1 = shiftedCapFloor1.NPV(); double value2 = shiftedCapFloor2.NPV(); double numericalVega = (value2 - value1) / (2 * shift); if (numericalVega > 1.0e-4) { double analyticalVega = (double)capFloor.result("vega"); double discrepancy = Math.Abs(numericalVega - analyticalVega); discrepancy /= numericalVega; if (discrepancy > tolerance) Assert.Fail( "failed to compute cap/floor vega:" + "\n lengths: " + new Period(lengths[j], TimeUnit.Years) + "\n strike: " + strikes[k] + "\n types: " + types[h] + "\n calculated: " + analyticalVega + "\n expected: " + numericalVega + "\n discrepancy: " + discrepancy + "\n tolerance: " + tolerance); } } } } } }
public void testStrikeDependency() { CommonVars vars = new CommonVars(); int[] lengths = { 1, 2, 3, 5, 7, 10, 15, 20 }; double[] vols = { 0.01, 0.05, 0.10, 0.15, 0.20 }; double[] strikes = { 0.03, 0.04, 0.05, 0.06, 0.07 }; Date startDate = vars.termStructure.link.referenceDate(); for (int i = 0; i < lengths.Length; i++) { for (int j = 0; j < vols.Length; j++) { // store the results for different strikes... List<double> cap_values = new List<double>(), floor_values = new List<double>(); for (int k = 0; k < strikes.Length; k++) { List<CashFlow> leg = vars.makeLeg(startDate, lengths[i]); Instrument cap = vars.makeCapFloor(CapFloorType.Cap, leg, strikes[k], vols[j]); cap_values.Add(cap.NPV()); Instrument floor = vars.makeCapFloor(CapFloorType.Floor, leg, strikes[k], vols[j]); floor_values.Add(floor.NPV()); } // and check that they go the right way for (int k = 0; k < cap_values.Count - 1; k++) { if (cap_values[k] < cap_values[k + 1]) Assert.Fail( "NPV is increasing with the strike in a cap: \n" + " length: " + lengths[i] + " years\n" + " volatility: " + vols[j] + "\n" + " value: " + cap_values[k] + " at strike: " + strikes[k] + "\n" + " value: " + cap_values[k + 1] + " at strike: " + strikes[k + 1]); } // same for floors for (int k = 0; k < floor_values.Count - 1; k++) { if (floor_values[k] > floor_values[k + 1]) Assert.Fail( "NPV is decreasing with the strike in a floor: \n" + " length: " + lengths[i] + " years\n" + " volatility: " + vols[j] + "\n" + " value: " + floor_values[k] + " at strike: " + strikes[k] + "\n" + " value: " + floor_values[k + 1] + " at strike: " + strikes[k + 1]); } } } }
public void testParity() { CommonVars vars = new CommonVars(); int[] lengths = { 1, 2, 3, 5, 7, 10, 15, 20 }; double[] strikes = { 0.0, 0.03, 0.04, 0.05, 0.06, 0.07 }; double[] vols = { 0.01, 0.05, 0.10, 0.15, 0.20 }; Date startDate = vars.termStructure.link.referenceDate(); for (int i = 0; i < lengths.Length; i++) { for (int j = 0; j < strikes.Length; j++) { for (int k = 0; k < vols.Length; k++) { List<CashFlow> leg = vars.makeLeg(startDate, lengths[i]); Instrument cap = vars.makeCapFloor(CapFloorType.Cap, leg, strikes[j], vols[k]); Instrument floor = vars.makeCapFloor(CapFloorType.Floor, leg, strikes[j], vols[k]); Date maturity = vars.calendar.advance(startDate, lengths[i], TimeUnit.Years, vars.convention); Schedule schedule = new Schedule(startDate, maturity, new Period(vars.frequency), vars.calendar, vars.convention, vars.convention, DateGeneration.Rule.Forward, false); VanillaSwap swap = new VanillaSwap(VanillaSwap.Type.Payer, vars.nominals[0], schedule, strikes[j], vars.index.dayCounter(), schedule, vars.index, 0.0, vars.index.dayCounter()); swap.setPricingEngine((IPricingEngine)new DiscountingSwapEngine(vars.termStructure)); // FLOATING_POINT_EXCEPTION if (Math.Abs((cap.NPV() - floor.NPV()) - swap.NPV()) > 1.0e-10) { Assert.Fail( "put/call parity violated:\n" + " length: " + lengths[i] + " years\n" + " volatility: " + vols[k] + "\n" + " strike: " + strikes[j] + "\n" + " cap value: " + cap.NPV() + "\n" + " floor value: " + floor.NPV() + "\n" + " swap value: " + swap.NPV()); } } } } }
public void testImpliedVolatility() { CommonVars vars = new CommonVars(); int maxEvaluations = 100; double tolerance = 1.0e-6; CapFloorType[] types = { CapFloorType.Cap, CapFloorType.Floor }; double[] strikes = { 0.02, 0.03, 0.04 }; int[] lengths = { 1, 5, 10 }; // test data double[] rRates = { 0.02, 0.03, 0.04 }; double[] vols = { 0.01, 0.20, 0.30, 0.70, 0.90 }; for (int k = 0; k < lengths.Length; k++) { List<CashFlow> leg = vars.makeLeg(vars.settlement, lengths[k]); for (int i = 0; i < types.Length; i++) { for (int j = 0; j < strikes.Length; j++) { CapFloor capfloor = vars.makeCapFloor(types[i], leg, strikes[j], 0.0); for (int n = 0; n < rRates.Length; n++) { for (int m = 0; m < vols.Length; m++) { double r = rRates[n]; double v = vols[m]; vars.termStructure.linkTo(Utilities.flatRate(vars.settlement, r, new Actual360())); capfloor.setPricingEngine(vars.makeEngine(v)); double value = capfloor.NPV(); double implVol = 0.0; try { implVol = capfloor.impliedVolatility(value, vars.termStructure, 0.10, tolerance, maxEvaluations); } catch (Exception e) { // couldn't bracket? capfloor.setPricingEngine(vars.makeEngine(0.0)); double value2 = capfloor.NPV(); if (Math.Abs(value - value2) < tolerance) { // ok, just skip: continue; } // otherwise, report error Assert.Fail("implied vol failure: " + typeToString(types[i]) + " strike: " + strikes[j] + " risk-free: " + r + " length: " + lengths[k] + "Y" + " volatility: " + v + e.Message); } if (Math.Abs(implVol - v) > tolerance) { // the difference might not matter capfloor.setPricingEngine(vars.makeEngine(implVol)); double value2 = capfloor.NPV(); if (Math.Abs(value - value2) > tolerance) { Assert.Fail( typeToString(types[i]) + ":" + " strike: " + strikes[j] + "\n" + " risk-free rate: " + r + "\n" + " length: " + lengths[k] + " years\n\n" + " original volatility: " + v + "\n" + " price: " + value + "\n" + " implied volatility: " + implVol + "\n" + " corresponding price: " + value2); } } } } } } } }
public void testConsistency() { CommonVars vars = new CommonVars(); int[] lengths = { 1, 2, 3, 5, 7, 10, 15, 20 }; double[] cap_rates = { 0.03, 0.04, 0.05, 0.06, 0.07 }; double[] floor_rates = { 0.03, 0.04, 0.05, 0.06, 0.07 }; double[] vols = { 0.01, 0.05, 0.10, 0.15, 0.20 }; Date startDate = vars.termStructure.link.referenceDate(); for (int i = 0; i < lengths.Length; i++) { for (int j = 0; j < cap_rates.Length; j++) { for (int k = 0; k < floor_rates.Length; k++) { for (int l = 0; l < vols.Length; l++) { List<CashFlow> leg = vars.makeLeg(startDate, lengths[i]); Instrument cap = vars.makeCapFloor(CapFloorType.Cap, leg, cap_rates[j], vols[l]); Instrument floor = vars.makeCapFloor(CapFloorType.Floor, leg, floor_rates[k], vols[l]); Collar collar = new Collar(leg, new InitializedList<double>(1, cap_rates[j]), new InitializedList<double>(1, floor_rates[k])); collar.setPricingEngine(vars.makeEngine(vols[l])); if (Math.Abs((cap.NPV() - floor.NPV()) - collar.NPV()) > 1e-10) { Assert.Fail( "inconsistency between cap, floor and collar:\n" + " length: " + lengths[i] + " years\n" + " volatility: " + vols[l] + "\n" + " cap value: " + cap.NPV() + " at strike: " + cap_rates[j] + "\n" + " floor value: " + floor.NPV() + " at strike: " + floor_rates[k] + "\n" + " collar value: " + collar.NPV()); } } } } } }
public void testCachedValue() { CommonVars vars = new CommonVars(); Date cachedToday = new Date(14, Month.March, 2002), cachedSettlement = new Date(18, Month.March, 2002); Settings.setEvaluationDate(cachedToday); vars.termStructure.linkTo(Utilities.flatRate(cachedSettlement, 0.05, new Actual360())); Date startDate = vars.termStructure.link.referenceDate(); List<CashFlow> leg = vars.makeLeg(startDate, 20); Instrument cap = vars.makeCapFloor(CapFloorType.Cap, leg, 0.07, 0.20); Instrument floor = vars.makeCapFloor(CapFloorType.Floor, leg, 0.03, 0.20); // par coupon price double cachedCapNPV = 6.87570026732, cachedFloorNPV = 2.65812927959; // index fixing price //Real cachedCapNPV = 6.87630307745, // cachedFloorNPV = 2.65796764715; // test Black cap price against cached value if (Math.Abs(cap.NPV() - cachedCapNPV) > 1.0e-11) Assert.Fail("failed to reproduce cached cap value:\n" + " calculated: " + cap.NPV() + "\n" + " expected: " + cachedCapNPV); // test Black floor price against cached value if (Math.Abs(floor.NPV() - cachedFloorNPV) > 1.0e-11) Assert.Fail("failed to reproduce cached floor value:\n" + " calculated: " + floor.NPV() + "\n" + " expected: " + cachedFloorNPV); }